em & rem

em

在 CSS 中,em 是相对于“当前元素”的字体大小而言的。其中,1em 就等于“当前元素” 字体大小。这里的字体大小指的是以 px 为单位的 font-size 值。

em 的使用又三个小技巧:使用 text-indent:2em实现首行缩进;使用 em 作为统一单位,所有浏览器的默认字体大小都为 16px;使用 em 作为单位定义字体大小,当需要改变页面文字大小时,只需要改变根元素大小即可。

rem

rem,全称 font size of the root element,是指相对于根元素(即 html 元素)的字体大小,区别于 em,em 是相对当前元素的字体的大小,而 rem 是相对根元素的字体的大小。

CSS 特性

继承性

继承性是指子元素继承了父元素的某些样式属性。在 CSS 中,具有继承性的属性有三类:

文本相关属性:font-family、font-size、font-style、font-weight、font、line-height、 text-align、text-indent、word-spacing。

列表相关属性: list-style-image、list-style-position、list-style-type、list-style。

颜色相关属性:color。

层叠性

CSS 的层叠性,指的就是样式的覆盖。对于同一个元素来说,如果我们重复定义多个相同的属性,并且这些样式具有相同的权重时,CSS 会以最后定义的属性值为准,也就是遵循“后来者居上”原则。 其意义在于:当一个元素受到多方面影响时,最终使用哪种样式。

这里的“后来居上”要满足三个条件:元素相同,属性相同,权重相同。

优先级

当样式的覆盖发生冲突时,以优先级高的为准,当“同一 个元素”的“同一个样式属性”被运用上多个属性值时,我们就需要遵循一定的优先级规则来选择一个属性值了。有五种常见的样式覆盖引发的冲突。

引用方式冲突

已知 CSS 有 3 种常用的引用方式:外部样式、内部样式和行内样式。CSS 因引用方式的不同,也会产生冲突。三种方式优先级如下:

基础知识 - 图1

如果内部样式与外部样式同时存在,以最后引用的样式为准。

  1. <link rel="stylesheet" href="index.css">
  2. <style>...</style>
  3. 两行前后顺序对结果造成的影响。

继承方式冲突

如果是由于继承方式引起的冲突,则“最近的祖先元素”获胜。

  1. <div id="grandfather">
  2. <div id="father">
  3. <div id="son">...</div>
  4. </div>
  5. </div>

指定样式冲突

所谓的指定样式,指的是指定“当前元素”的样式。当直接指定的样式发生冲突时,样式权重高者获胜。 image.png
常见的伪元素只有 4 个:::before、::after、::first-letter 和 ::first-line。伪类我们经常见到, 如 hover、:first-child 等。常用的选择器优先级如下。之前提到过,当选择器权重相同时,遵循后来者居上原则。

基础知识 - 图3

::before                p::before                    在每个 <p> 的内容之前插入内容。
::after                    p::after                    在每个 <p> 的内容之后插入内容。
::first-letter    p::first-letter        选择每个 <p> 元素的首字母。
::first-line        p::first-line            选择每个 <p> 元素的首行。

注:选择器权重的计算只针对指定样式(当前元素),并不能用于继承样式。 该先判断指定样式,然后再去考虑继承样式

扩展链接:[**CSS 选择器参考手册**](https://www.w3school.com.cn/cssref/css_selectors.asp)

继承样式和指定样式冲突

继承样式和指定样式发生冲突时,指定样式获胜。

!important

在 CSS 中,我 们 可 以 使 用 !important 规则改变样式的优先级。 如果一个样式使用“!important”来声明,则这个样式会覆盖 CSS 中其他的任何样式声明 。

如果你一定要使用某个样式属性值,为了不让它被覆盖,则可以使用 !important 来实现。换句话说,如果想要覆盖其他所有样式,可以使用 !important 来实现 。

<div id="outer">
        <p class="inner">
        <span><strong>绿叶学习网</strong></span>
        </p>
</div>

#outer strong
 {
 /*权重=100+1=101*/
 color:red;
 }
 #outer .inner strong
 {
 /*权重=100+10+1=111*/
 color:green;
 }
 .inner strong
 {
 /*权重=10+1=11*/
 color:blue;
 }
 .inner span strong
 {
 /*权重=10+1+1=12*/
 color:purple;
 }
 strong
 {
 color:black !important;
 }

!important 用法

#someID p{color:red}
p{color:green}

外层有 #someID 的情况下,如果不适用 !important,第一条样式永远比第二条样式优先级更高。

另外就是直接覆盖一些效果不好的行内样式。(回顾行内样式:行内样式就是直接把CSS代码添加到HTML的标记中,即作为HTML标记的属性标记存在。通过这种方法,可以很简单地对某个元素单独定义样式。)

覆盖 !important

▶ 使用相同的选择器,在后面添加一条 !important 语句。

▶ 使用更高优先级的选择器,再添加一条 !important 语句。

小结

纸上得来终觉浅,绝知此事要躬行。先理解一遍,以后的编写页面的过程中在慢慢体会,不必死记硬背。这里可以总结为两点:

优先级高的样式覆盖优先级低的样式。

同一优先级的样式,后定义的覆盖先定义的,即“后来者居上原则”。

CSS 引用方式

已知的三种引用方式:外部样式表,内部样式表,行内样式表。除此之外,还有一种 @import 方式(导入样式表)。该方式与外部样式表很相似,但实际开发中很少使用该方式,更多的使用 link 方式,原因是 @import 方式先加载 HTML 后加载 CSS,而 link 刚好相反,如果先加载 HTML,页面用户体验会非常差。

<!DOCTYPE html> 
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <!--这是外部样式,CSS样式在外部文件中定义-->
    <link href="index.css" rel="stylesheet" type="text/css" />
    <!--这是内部样式,CSS样式在style标签中定义-->
    <style type="text/css">
      p{color:Red;}
    </style>
  </head>
  <body>
    <!--这是行内样式,CSS样式在元素style属性中定义-->
    <p style="color:Blue;">绿叶学习网</p>
    <p>绿叶学习网</p>
    <p>绿叶学习网</p>
  </body>
</html>
内外部样式表以及行内样式表并非非此即彼,而是相互搀扶,共同作用于页面:  **外部样式表多用于公有样式,内部样式表多用于私有样式,而行内样式表则多用于小修改或者优先级方面。**

CSS 选择器

CSS 选择器就是把你想要的标签选中的一种方式。把它选中了,才能操作标签的 CSS 样式。CSS 中提供了很多将标签选中的方式,这些不同的方式就是不同的选择器 。

已知的简单的选择器包括元素选择器,id 选择器,class 选择器,群组选择器。

层次选择器,指的是通过元素之间的层次关系来选择元素,在实际开发中非常重要,常见的层次关系包括父子,后代,兄弟,相邻等关系。image.png

后代选择器

后代选择器用于选中元素内部的某一个元素,包括子元素和其他的后代元素。语法:M N{}

<!DOCTYPE html> 
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
      #first p
      {
        color: red;
      }
    </style>
  </head>
  <body>
    <div id="first">
      <p>lvye的子元素</p>
      <p>lvye的子元素</p>
      <div id="second">
        <p>lvye子元素的子元素</p>
        <p>lvye子元素的子元素</p>
      </div>
      <p>lvye的子元素</p>
      <p>lvye的子元素</p>
    </div>
  </body>
</html>

所有的语句都被标为红色
#first p 表示选中 id="first" 的元素内部所有的 p 元素,因此不管是子元素还是其他后代元素,全部都会被选中。

子代选择器

用于选中元素内部的某一个子元素,语法:M>N{}。与后代选择器相似,但两者也有区别:

▶ 后代选择器选中的是元素内部的所有元素(包括子元素)

▶ 子代选择器,选中的是元素内部的某一个子元素(只限子元素)。

<!DOCTYPE html> 
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
      #first>p 
      {
        color: red;
      }
    </style>
  </head>
  <body>
    <div id="first">
      <p>lvye的子元素</p>
      <p>lvye的子元素</p>
      <div id="second">
        <p>lvye子元素的子元素</p>
        <p>lvye子元素的子元素</p>
      </div>
      <p>lvye的子元素</p>
      <p>lvye的子元素</p>
    </div>
  </body>
</html>

只有“lvye的子元素”语句被标记为红色

first>p 表示选中 id=”first” 的元素下的子元素 p。可以清楚的看到与后代选择器相比,子代选择器只选择子元素,不包括其他后代。

兄弟选择器

用于选中元素后面(不包括前面)的所有某一类兄弟元素,语法:M~N{}

<!DOCTYPE html> 
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
      #second~p 
      {
        color: red;
      }
    </style>
  </head>
  <body>
    <div id="first">
      <p>lvye的子元素</p>
      <p>lvye的子元素</p>
      <div id="second">
        <p>lvye子元素的子元素</p>
        <p>lvye子元素的子元素</p>
      </div>
      <p>lvye的子元素</p>        /*注意这里 p 和 div 是兄弟元素*/
      <p>lvye的子元素</p>
    </div>
  </body>
</html>

只有最后两行语句为红色

second~p 表示选中 id=”second” 的元素后面的所有兄弟元素 p。兄弟选择器只选中后面的所有兄弟元素,不包括前面的所有兄弟元素。

相邻选择器

用于选中元素后面的某一个相邻的兄弟元素,语法:M+N{},相邻选择器跟兄弟选择器非常相似,不过也有明显区别:

▶ 兄弟选择器选择元素后面所有的某一类元素。

▶ 相邻选择器选中元素后面相邻的某一个元素。

<!DOCTYPE html> 
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
      #second+p 
      {
        color: red;
      }
    </style>
  </head>
  <body>
    <div id="first">
      <p>lvye的子元素</p>
      <p>lvye的子元素</p>
      <div id="second">
        <p>lvye子元素的子元素</p>
        <p>lvye子元素的子元素</p>
      </div>
      <p>lvye的子元素</p>
      <p>lvye的子元素</p>
    </div>
  </body>
</html>

倒数第二行被改为红色

second+p 表示选中 id=”second” 的元素后面的“相邻”的兄弟元素 p。

<!DOCTYPE html> 
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
      /*去除所有元素默认的padding和margin*/
      * {padding: 0;margin: 0}
      /*去除列表项默认符号*/
      ul {list-style-type: none;}
      li+li {border-top: 2px solid red;}
    </style>
  </head>
  <body>
    <ul>
      <li>第1个元素</li>
      <li>第2个元素</li>
      <li>第3个元素</li>
      <li>第4个元素</li>
      <li>第5个元素</li>
      <li>第6个元素</li>
    </ul>
  </body>
</html>

除了第一行,每一行顶部都有红线

li+li 使用的是相邻选择器,表示选中 li 元素相邻的下一个 li 元素,由于第一个 li 元素上面没有兄弟,所以不含边框。

first - letter / line

first - line{}

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
      div:first-line
      {
        color:hotpink;
      }
    </style>
  </head>
  <body>
    <div>撑伞接落花,<br/>看那西风骑瘦马。</div>
  </body>
</html>

“撑伞接落花,”为粉色,后面为黑

first - letter{}

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title></title>
    <style type="text/css">
      div:first-letter
      {
        font-size:30px;
        color:hotpink;
      }
    </style>
  </head>
  <body>
    <div>奔跑吧,骄傲的少年</div>
  </body>
</html>

只有“奔”被加上效果

小结

以上便是 CSS2.1 中关于选择器的部分常用内容,除此之外还有很多其他方式的选择器使用,不过多为 CSS3 新增,在之后还会遇到。

扩展链接:CSS 选择器参考手册