扫一扫下方二维码,关注本站官方公众号
回复:验证码
获取永久解锁本站全部文章的验证码

百度前端技术学院第四天--CSS2-Go语言中文社区

百度前端技术学院第四天--CSS2


一、使用CSS改变背景样式

什么是背景?

元素的背景是指,在元素内容、内边距和边界下层的区域。默认情况下就是这样——在新的浏览器中,你可以使用 background-clip属性改变背景所占用的区域(更多细节见 CSS box model article background-clip coverage)。

背景并不在外边距下层——外边距不是元素区域的一部分,而是元素外面的区域。

还有很多其他的属性可以用来操作元素的背景,其中一些已经在我们的课程中已经见过很多次了:

p:{
background-color: yellow;
background-image: url(https://mdn.mozillademos.org/files/13026/fire-ball-icon.png);
background-repeat: no-repeat;
background-position: 99% center;
background-image: linear-gradient(to bottom, orange, yellow);
background-attachment: fixed;
}

p {
  font-family: sans-serif;
  padding: 20px;
  /* background properties */
  background-color: yellow;
  background: url(https://mdn.mozillademos.org/files/13026/fire-ball-icon.png) no-repeat 99% center,
              linear-gradient(to bottom, yellow, #dddd00 50%, orange);
background-size: 16px 16px;
}

二、使用CSS的样式边框

边界回顾

正如您前面在课程中看到的,元素有一个边界,它位于元素的内边距(padding)和外边距(margin)之间。默认情况下,边界的大小为0,使其不可见,但可以设置边界的粗细、样式和颜色以使其显示出来。

边界简写

border简写属性允许你一次将所有的这些都设置在四个边,例如:

<p>I have a red border!</p>
p {
  padding: 10px;
  background: yellow;
  border: 2px solid red;
}

普通写法选项

border可以分解成许多不同的属性,以获得更具体的样式需求:

边界半径

盒子上的圆角是网站上另一个非常受欢迎的功能——如此流行以至于浏览器实现了专门用于实现圆角的属性 : border-radius. 在此之前 (需要用多个background images去完成), 开发人员曾经要包裹每个盒子,他们希望在三个额外的<div>中加上圆角,并为这四个元素中的每个元素附加一个单独的圆角图形。 如果他们想要他们的盒子看起来灵动的,那就必须这么做。

注意: 你可能还必须这样做,如果你需要兼容旧的浏览器——border-radius 只支持Internet Explorer 9以上。但是缺少圆角不能阻止用户阅读你的内容,所以老浏览器的用户可以不用它们。

现在更容易了——您只需使用以下属性:

border-radius: 20px;

在不同的角落放置不同大小的边界半径, 您可以指定两个,三个或四个值, 就像您使用 paddingand margin一样:

/* 1st value is top left and bottom right corners,
   2nd value is top right and bottom left  */
border-radius: 20px 10px;
/* 1st value is top left corner, 2nd value is top right
   and bottom left, 3rd value is bottom right  */
border-radius: 20px 10px 50px;
/* top left, top right, bottom right, bottom left */
border-radius: 20px 10px 50px 0;

作为最后一点,您还可以创建椭圆形角(x半径与y半径不同)。两个不同的半径用正斜杠(/)分隔,您可以将其与值的任意组合组合。例如:

border-radius: 10px / 20px;
border-radius: 10px 30px / 20px 40px;

边界图像

最后,让我们看一下CSS中最新的(和复杂的)操作,用于操作边界—— border-image。这里的想法是,有时创建复杂的用户界面特性需要一个复杂的界面设计,而不仅仅是一个纯色。这可能是通过在另一个较大的元素的顶部覆盖一个元素,然后将背景图像应用到底部元素,伪造一个复杂的边界来创建的。或者在极端情况下,您甚至可能需要创建一个包含9个元素的3 x 3网格,其中的中心元素作为您的内容,以及周围的8个元素,将边界元素应用于它们。

border-image图像使实现复杂的图形边界变得容易得多,即使必须在现代浏览器中才能实现(Internet Explorer 11+支持它,以及其他现代浏览器)。让我们来看看它是如何工作的。

首先,您需要有一个映像应用到您的浏览器。这通常是3 x 3、4 x 4、5 x 5(等等)网格设计,如下所做的:

image

当这样的图像用于边界图像时,浏览器将图像分割为8个部分,如下一个图像所示:

image

这些角的图像会被插入到你的边界的角落里,而顶部、右边、底部和左边的部分将被用来填充你的边界的相应边(通过拉伸或重复)。我们需要告诉浏览器让这些片的大小正确——例如,这个图像是160px,还有一个4 x 4的网格,所以每个片都需要40px。

首先,我们需要一个盒子来应用边界。这需要指定一个边界,否则边界图像将没有显示的空间。我们还将使用background-clip,使任何背景色只填充内容和内边距的区域,并且不扩展到边界(您可能不希望这样做,但是在这样的情况下是有用的)。

border: 30px solid black;
background-clip: padding-box;

注意:您应该始终包括border定义,以及任何使用border-image——如果浏览器不支持该特性,则该操作可以作为一个回退,以防止边界图像无法显示。

接下来,我们将使用 border-image-source指定要使用的源图像作为边界图像。 它的工作原理和background-image一样,能够接受一个url()函数或一个渐变作为一个值。

border-image-source: url(border-image.png);

现在,我们将使用border-image-slice来设置所需大小的切片,如上所述:

border-image-slice: 40;

如果所有的片都是相同的大小,那么这个属性可以取一个值,如果需要不同的大小,则可以使用多个值,以相同的方式使用paddingmargin

  • 两个值:上和下,左和右。
  • 三个值:上、左和右、下。
  • 四个值:上、右、下、左。

如果图像是光栅图形(像 .png.jpg),就用像素来解释这个数字。如果图像是矢量图形(比如,.svg),那么这个数字将被解释为图形中的坐标。也可以使用百分比(使用单位 %)。查看 border-image-slice页面,获得更多的选项和详细信息。

注意:默认情况下,第9部分的中间部分被完全省略,而元素内容出现在剩下的空白中。如果您想要的是边界图像的中心,您可以通过在您的border-image-source的末尾包含关键字fill,在这种情况下,它将扩展到适合背景区域。

最后,我们将使用border-image-repeat t来指定我们希望图像如何填充边界。选项是:

  • stretch:默认;侧面的图像被拉伸来填满边界。这通常看起来很糟糕和像素化,所以不推荐。
  • repeat:边图像被重复,直到边界被填满。根据具体情况,这可能看起来不错,但您可能会看到一些难看的图像片段。
  • round: 边的图像被重复,直到边界被填满,它们都被稍微拉伸,这样就不会出现碎片。
  • space:边图像被重复,直到边界被填满,每个拷贝之间添加了少量的间隔,这样就不会出现任何片段。这个值只在Safari(9+)和Internet Explorer(11+)中得到支持。

我们决定使用round的值,因为它看起来是最有用和最灵活的:

border-image-repeat: round;

把这些结合在一起

让我们将所有这些代码放在一起,以显示一个工作示例。首先,一些简单的HTML:

<div>
  <p>Border image</p>
</div>

现在是我们的CSS:

div {
  width: 300px;
  padding: 20px;
  margin: 10px auto;
  line-height: 3;
  background-color: #f66;
  text-align: center;
  /* border-related properties */
  border: 20px solid black;
  background-clip: padding-box;
  border-image-source: url(https://mdn.mozillademos.org/files/13060/border-image.png);
  border-image-slice: 40;
  border-image-repeat: round;
}

其他属性

两个不常用的边界图像属性如下:

  • border-image-width:只调整边界图像,而不是边界——如果这个设置小于border-width,它会在边界的外面,而不是填满它。如果它更大,那么它就会扩展到边界之外,并开始重叠在内边距/内容上。
  • border-image-outset:定义边界内部和内边距之间的额外空间的大小——有点像“边界填充”。如果需要的话,这是一种简单的方法,可以将边界图像移出一点。

border-image,这允许您在一行中设置所有相关的值。见下面的代码行:

border-image-source: url(border-image.png);
border-image-slice: 40;
border-image-repeat: round;

可以被这一行取代:

border-image: url(border-image.png) 40 round;

三、样式列表

一个简单的例子

首先,让我们看一个简单的例子。文章中我们将看到无序,有序和描述列表——它们都具有相似的样式特性,而某些特性却又各不相同。Github上有未加载样式的例子(也可以查看源码。)

例子中列表的HTML代码如下:

<h2>Shopping (unordered) list</h2>

<p>Paragraph for reference, paragraph for reference, paragraph for reference,
paragraph for reference, paragraph for reference, paragraph for reference.</p>

<ul>
  <li>Humous</li>
  <li>Pitta</li>
  <li>Green salad</li>
  <li>Halloumi</li>
</ul>

<h2>Recipe (ordered) list</h2>

<p>Paragraph for reference, paragraph for reference, paragraph for reference, 
paragraph for reference, paragraph for reference, paragraph for reference.</p>

<ol>
  <li>Toast pitta, leave to cool, then slice down the edge.</li>
  <li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
  <li>Wash and chop the salad.</li>
  <li>Fill pitta with salad, humous, and fried halloumi.</li>
</ol>

<h2>Ingredient description list</h2>

<p>Paragraph for reference, paragraph for reference, paragraph for reference, 
paragraph for reference, paragraph for reference, paragraph for reference.</p>

<dl>
  <dt>Humous</dt>
  <dd>A thick dip/sauce generally made from chick peas blended with tahini, lemon juice, salt, garlic, and other ingredients.</dd>
  <dt>Pitta</dt>
  <dd>A soft, slightly leavened flatbread.</dd>
  <dt>Halloumi</dt>
  <dd>A semi-hard, unripened, brined cheese with a higher-than-usual melting point, usually made from goat/sheep milk.</dd>
  <dt>Green salad</dt>
  <dd>That green healthy stuff that many of us just use to garnish kebabs.</dd>
</dl>

现在,如果你去到例子的展示页面,并使用浏览器开发者工具查看那些列表元素,你会注意到若干个默认的样式预设值:

  • <ul><ol> 元素设置margin的顶部和底部: 16px(1em) 0;和 padding-left: 40px(2.5em); (在这里注意的是浏览器默认字体大小为16px)。
  • <li> 默认是没有设置间距的。
  • <dl> 元素设置 margin的顶部和底部: 16px(1em) ,无内边距设定。
  • <dd> 元素设置为: margin-left 40px (2.5em)。
  • 在参考中提到的 <p> 元素设置 margin的顶部和底部: 16px(1em),和其他的列表类型相同。

处理列表间距

当您创建样式列表时,您需要调整样式,使其保持与周围元素相同的垂直间距(例如段落和图片,有时称为垂直节奏))和相互间的水平间距(您可以在 Github 上参考完成的样式示例 ,也可以找到源代码。)

用于文本样式和间距的CSS如下所示:

/* General styles */

html {
  font-family: Helvetica, Arial, sans-serif;
  font-size: 10px;
}

h2 {
  font-size: 2rem;
}

ul,ol,dl,p {
  font-size: 1.5rem;
}

li, p {
  line-height: 1.5;
}

/* Description list styles */

dd, dt {
  line-height: 1.5;
}

dt {
  font-weight: bold;
}

dd {
  margin-bottom: 1.5rem;
}
  • 第一条规则集设置一个网站字体,基准字体大小为10px。 页面上的所有内容都将继承该规则集。
  • 规则集2和3为标题、不同的列表类型和段落以及设置了相对字体大小(这些列表的子元素将会继承该规则集),这就意味着每个段落和列表都将拥有相同的字体大小和上下间距,有助于保持垂直间距一致。
  • 规则集4在段落和列表项目上设置相同的 line-height ,因此段落和每个单独的列表项目将在行之间具有相同的间距。 这也将有助于保持垂直间距一致。
  • 规则集5-7适用于描述列表 - 我们在描述列表的术语和其描述上设置与段落和列表项相同的行高,以及 margin-bottom 为1.5 rem(与段落(p)和列表项目(li))相同。 再次强调一遍,这里很好地实现了一致性! 我们还使描述术语具有粗体字体,因此它们在视觉上脱颖而出。

列表特定样式

现在我们来看一下列表的一般间距,我们来研究一些列表具有的特定属性。 我们从三个属性开始了解,这三个属性可以在 <ul><ol> 元素上设置:

  • list-style-type :设置用于列表的项目符号的类型,例如无序列表的方形或圆形项目符号,或有序列表的数字,字母或罗马数字。
  • list-style-position :设置在每个项目开始之前,项目符号是出现在列表项内,还是出现在其外。
  • list-style-image :允许您为项目符号使用自定义图片,而不是简单的方形或圆形。

符号样式

像上面所提及的, list-style-type 属性允许你设置项目符号点的类型,在我们的例子中,我们在有序列表上设置了大写罗马数字:

ol {
  list-style-type: upper-roman;
}

您可以通过 list-style-type 参考页面查找到更多选项。

项目符号位置

list-style-position 设置在每个项目开始之前,项目符号是出现在列表项内,还是出现在其外。 如上所示,默认值为 outside,这使项目符号位于列表项之外。

如果值设置为 inside,项目条目则位于行内。

ol {
  list-style-type: upper-roman;
  list-style-position: inside;
}
an ordered list with the bullet points set to appear inside the list item text.

使用自定义的项目符号图片

list-style-image 属性允许对于项目符号使用自定义图片。其语法相当简单:

ul {
  list-style-image: url(star.svg);
}

然而,这个属性在控制项目符号的位置,大小等方面是有限的。 您最好使用background 系列属性,您将在 Styling boxes 模块中了解更多信息。在这里我们仅做一点尝试!

结束我们的例子,我们样式化无序列表像这样(放到您之前所见的顶部):

ul {
  padding-left: 2rem;
  list-style-type: none;
}

ul li {
  padding-left: 2rem;
  background-image: url(star.svg);
  background-position: 0 0;
  background-size: 1.6rem 1.6rem;
  background-repeat: no-repeat;
}

我们的所做如下:

  • <ul>padding-left 从默认的 40px设置为 20px,然后在列表项上设置相同的数值。 这就是说,整个列表项仍然排列在有序列表项和描述列表中,但是列表项产生了一些用于背景图像的填充。 如果我们没有设置填充,背景图像将与列表项文本重叠,这看起来会很乱。
  • list-style-type 设置为none,以便默认情况下不会显示项目符号。 我们将使用 background 属性来代替项目符号。
  • 为每个无序列表项插入项目符号,其相应的属性如下:
    • background-image: 充当项目符号的图片文件的参考路径
    • background-position: 这定义了所选元素背景中的图像将出现在哪里 - 在我们的示例中设置 0 0,这意味着项目符号将出现在每个列表项的最左上侧。
    • background-size: 设置背景图片的大小。 理想条件下,我们想要项目符号与列表项的大小相同(比列表项稍大或稍小亦可)。 我们使用的尺寸为1.6rem(16px),它非常吻合我们为项目符号设置的 20px 的填充, 16px 加上 4px 的空格间距,可以使项目符号和列表项文本效果更好。
    • background-repeat:默认条件下,背景图片不断复制直到填满整个背景空间,在我们的例子中,背景图片只需复制一次,所以我们设置值为 no-repeat

list-style 速记

上述提到的三种属性可以用一个单独的速记属性 list-style 来设置。例如:

ul {
  list-style-type: square;
  list-style-image: url(example.png);
  list-style-position: inside;
}

可以被如下方式代替:

ul {
  list-style: square url(example.png) inside;
}

属性值可以任意顺序排列,你可以设置一个,两个或者三个值(该属性的默认值为 disc, none, outside),如果指定了 type 和 image,如果由于某种原因导致图像无法加载,则 type 将用作回退。

管理列表计数

有时,您可能想在有序列表上进行不同的计数方式。例如: 从1以外的数字开始,或向后倒数,或者按步或多于1计数。HTML和CSS有一些工具可以帮助您

start

start 属性允许你从1 以外的数字开始计数。示例如下:

<ol start="4">
  <li>Toast pitta, leave to cool, then slice down the edge.</li>
  <li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
  <li>Wash and chop the salad.</li>
  <li>Fill pitta with salad, humous, and fried halloumi.</li>
</ol>
reversed

reversed 属性将启动列表倒计数。示例如下:

<ol start="4" reversed>
  <li>Toast pitta, leave to cool, then slice down the edge.</li>
  <li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
  <li>Wash and chop the salad.</li>
  <li>Fill pitta with salad, humous, and fried halloumi.</li>
</ol>
value

该属性允许设置列表项指定数值,示例如下:

<ol>
  <li value="2">Toast pitta, leave to cool, then slice down the edge.</li>
  <li value="4">Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li>
  <li value="6">Wash and chop the salad.</li>
  <li value="8">Fill pitta with salad, humous, and fried halloumi.</li>
</ol>

四、链接样式

链接状态

第一件需要理解的事情是链接状态的概念,链接存在时处于不同的状态,每一个状态都可以用对应的 伪类 来应用样式:

  • Link (没有访问过的): 这是链接的默认状态,当它没有处在其他状态的时候,它可以使用:link 伪类来应用样式。
  • Visited: 这个链接已经被访问过了(存在于浏览器的历史纪录), 它可以使用 :visited 伪类来应用样式。
  • Hover: 当用户的鼠标光标刚好停留在这个链接,它可以使用 :hover 伪类来应用样式。
  • Focus: 一个链接当它被选中的时候比如通过键盘的Tab移动到这个链接的时候,或者使用编程的方法来选中这个链接 HTMLElement.focus()) 它可以使用 :focus 伪类来应用样式。
  • Active: 一个链接当它被激活的时候 (比如被点击的时候),它可以使用 :active 伪类来应用样式。

链接样式空规则集

a {

}


a:link {

}

a:visited {

}

a:focus {

}

a:hover {

}

a:active {

}

这个顺序是重要的,因为链接的样式是建立在另一个样式之上的,比如第一个规则的样式会应用到所有后续的样式,如果当一个链接被激活 (activated) 的时候,它也是处于悬停 (hover) 状态的。如果你搞错了顺序,那么就可能不会产生正确的效果。要记住这个顺序,你可以尝试这样帮助记忆:LoVe Fears HAte.

eg:

body {
  width: 300px;
  margin: 0 auto;
  font-size: 1.2rem;
  font-family: sans-serif;
}

p {
  line-height: 1.4;
}

a {
  outline: none;
  text-decoration: none;
  padding: 2px 1px 0;
}

a:link {
  color: #265301;
}

a:visited {
  color: #437A16;
}

a:focus {
  border-bottom: 1px solid;
  background: #BAE498;
}

a:hover {
  border-bottom: 1px solid;     
  background: #CDFEAA;
}

a:active {
  background: #265301;
  color: #CDFEAA;
}

在链接中包含图标

一个常见的做法是在链接中包含图标,使链接提供更多关于链接指向的内容的信息。让我们来看一个简单的例子,例子中为一个外部链接 (链接指向的不是本站,而是外部站点)。这样的图标通常看起来像一个指向盒子的小箭头

a[href*="http"] {
  background: url('https://mdn.mozillademos.org/files/12982/external-link-52.png') no-repeat 100% 0;
  background-size: 16px 16px;
  padding-right: 19px;
}

如何只选中了外部链接的?如果你正确写了你的 HTML links ,你应该只会在外部链接上使用绝对 URL,如果链接是链接你的站点的其他部分,那么使用相对链接是更加高效的。因此 "http" 文本应该只出现在外部链接上,所以我们可以使用一个属性选择器选中 <a> 元素,但是只会选中那些拥有 href属性,且属性的值包含 <a> 元素 (或锚元素) 可以创建一个到其他网页、文件、同一页面内的位置、电子邮件地址或任何其他URL的超链接。")的元素。

样式化链接为按钮

在某些情况下,链接通常会应用样式,使它看上去的效果和按钮差不多,一个网站导航菜单通常是标记为一个列表,列表中包含链接,这可以很容易地被设计为看起来像一组控制按钮或是选项卡,主要是用于让用户可以访问站点的其他部分,现在让我们来看一看。

首先,一些 HTML:

<ul>
  <li><a href="#">Home</a></li><li><a href="#">Pizza</a></li><li><a href="#">Music</a></li><li><a href="#">Wombats</a></li><li><a href="#">Finland</a></li>
</ul>

接着,是我们的 CSS:

body,html {
  margin: 0;
  font-family: sans-serif;
}

ul {
  padding: 0;
  width: 100%;
}

li {
  display: inline;
}

a {
  outline: none;
  text-decoration: none;
  display: inline-block;
  width: 19.5%;
  margin-right: 0.625%;
  text-align: center;
  line-height: 3;
  color: black;
}

ul:last-child a {
  margin-right: 0;
}

a:link, a:visited, a:focus {
  background: yellow;
}

a:hover {     
  background: orange;
}

a:active {
  background: red;
  color: white;
}
  • 我们首先关掉了 text-decorationoutline,我们不希望这些破坏我们链接的样子。
  • 接着,我们设置 displayinline-block<a> 元素默认为内联元素,而且我们不希望它们像值为 block 时一样,线条超出自己的内容,我们确实想要控制它们的大小inline-block 允许我们这样做。
  • 接着是尺寸的设置! 我们要填满整个 <ul> 的宽度,为按钮之间留一些间距 (margin) (但不是右边边缘的间距),我们有 5 个按钮需要容纳,所以它们的大小应该一样。为了做到这一点,我们设置 width 为 19.5%,然后 margin-right 为 0.625%. 你会注意到所有宽度加起来是 100.625%, 这样会让最后一个按钮溢出 <ul> ,然后显示到下一行中。但是,我们使用了下一条规则让它恢复到了 100%,这条规则选中了列表中的最后一个 <a>元素,然后删除了它的间距 (margin)。完成!
  • 最后三条声明就比较简单了,主要是为链接各个状态添加了颜色。我们居中了每个链接中的文本,设置 line-height 为 3, 让按钮有一些高度 (这也具有垂直居中文本的优点),并设置文本的颜色为黑色。

五、css高级语法

选择器的分组
你可以对选择器进行分组,这样,被分组的选择器就可以分享相同的声明。用逗号将需要分组的选择器分开。在下面的例子中,我们对所有的标题元素进行了分组。所有的标题元素都是绿色的。

h1,h2,h3,h4,h5,h6 {
  color: green;
  }

继承及其问题
根据 CSS,子元素从父元素继承属性。但是它并不总是按此方式工作。看看下面这条规则:

body {
     font-family: Verdana, sans-serif;
     }

根据上面这条规则,站点的 body 元素将使用 Verdana 字体(假如访问者的系统中存在该字体的话)。

通过 CSS 继承,子元素将继承最高级元素(在本例中是 body)所拥有的属性(这些子元素诸如 p, td, ul, ol, ul, li, dl, dt,和 dd)。不需要另外的规则,所有 body 的子元素都应该显示 Verdana 字体,子元素的子元素也一样。并且在大部分的现代浏览器中,也确实是这样的。
继承是一个诅咒吗?
如果你不希望 "Verdana, sans-serif" 字体被所有的子元素继承,又该怎么做呢?比方说,你希望段落的字体是 Times。没问题。创建一个针对 p 的特殊规则,这样它就会摆脱父元素的规则:

body  {
     font-family: Verdana, sans-serif;
     }

td, ul, ol, ul, li, dl, dt, dd  {
     font-family: Verdana, sans-serif;
     }

p  {
     font-family: Times, "Times New Roman", serif;
     }

CSS 派生选择器

派生选择器

通过依据元素在其位置的上下文关系来定义样式,你可以使标记更加简洁。

在 CSS1 中,通过这种方式来应用规则的选择器被称为上下文选择器 (contextual selectors),这是由于它们依赖于上下文关系来应用或者避免某项规则。在 CSS2 中,它们称为派生选择器,但是无论你如何称呼它们,它们的作用都是相同的。

派生选择器允许你根据文档的上下文关系来确定某个标签的样式。通过合理地使用派生选择器,我们可以使 HTML 代码变得更加整洁。

比方说,你希望列表中的 strong 元素变为斜体字,而不是通常的粗体字,可以这样定义一个派生选择器:

li strong

请注意标记为 <strong> 的蓝色代码的上下文关系:

<strong>我是粗体字,不是斜体字,因为我不在列表当中,所以这个规则对我不起作用</strong></p>

<ol>
`<li><strong>`我是斜体字。这是因为 strong 元素位于 li 元素内。`</strong></li>`
<li>我是正常的字体。</li>
</ol>

在上面的例子中,只有 li 元素中的 strong 元素的样式为斜体字,无需为 strong 元素定义特别的 class 或 id,代码更加简洁。

六、层叠和继承

当有多个选择器作用在一个元素上时,哪个规则最终会应用到元素上?其实这是通过层叠机制来控制的,这也和样式继承(元素从其父元素那里获得属性值)有关

层叠

CSS 是 Cascading Style Sheets 的缩写,这暗示层叠(cascade)的概念是很重要的。在最基本的层面上,它表明CSS规则的顺序很重要,但它比那更复杂。什么选择器在层叠中胜出取决于三个因素(这些都是按重量级顺序排列的——前面的的一种会否决后一种):

重要性(Importance)
专用性(Specificity)
源代码次序(Source order)

重要性

** 重要性 **
在CSS中,有一个特别的语法可以让一条规则总是优先于其他规则:!important。把它加在属性值的后面可以使这条声明有无比强大的力量。

让我们看一下这个例子:

<p class="better">This is a paragraph.</p>
<p class="better" id="winning">One selector to rule them all!</p>
#winning {
  background-color: red;
  border: 1px solid black;
}

.better {
  background-color: gray;
  border: none !important;
}

p {
  background-color: blue;
  color: white;
  padding: 5px;
}

最终的结果是:页面上面不显示边框,这就是important的作用。

相互冲突的声明将按以下顺序适用,后一种将覆盖先前的声明:

在用户代理样式表的声明 (例如:浏览器在没有其他声明的默认样式).
用户样式表中的普通声明(由用户设置的自定义样式)。
作者样式表中的普通声明(这是我们设置的样式,Web开发人员)。
作者样式表中的重要声明
用户样式表中的重要声明

专用性

专用性
基本上是衡量选择器的具体程度的一种方法——它能匹配多少元素。如上面所示的示例所示,元素选择器具有很低的专用性。类选择器具有更高的专用性,所以将战胜元素选择器。ID选择器有甚至更高的专用性, 所以将战胜类选择器. 战胜ID选择器的唯一方法是使用 !important

一个选择器具有的专用性的量是用四种不同的值(或组件)来衡量的,它们可以被认为是千位,百位,十位和个位——在四个列中的四个简单数字:

  1. 千位:如果声明是在[style](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Global_attributes#attr-style) 属性中该列加1分(这样的声明没有选择器,所以它们的专用性总是1000。)否则为0。
  2. 百位:在整个选择器中每包含一个ID选择器就在该列中加1分。
  3. 十位:在整个选择器中每包含一个类选择器、属性选择器、或者伪类就在该列中加1分。
  4. 个位:在整个选择器中每包含一个元素选择器或伪元素就在该列中加1分。

注意: 通用选择器 (*), 复合选择器 (+, >, ~, ' ') 和否定伪类 (:not) 在专用性中无影响。

下表显示了几个示例。试着通过这些,并确保你理解他们为什么具有我们给予他们的专用性。

选择器 千位 百位 十位 个位 合计值
h1 0 0 0 1 0001
#important 0 1 0 0 0100
h1 + p::first-letter 0 0 0 3 0003
li > a[href*="zh-CN"] > .inline-warning 0 0 2 2 0022
没有选择器, 规则在一个元素的 <style> 属性里 1 0 0 0 1000

注意: 如果多个选择器具有相同的重要性和专用性,则选择哪一个选择器取决于 Source order.

在我们继续之前,让我们看看一个行动中的例子。这是我们将要使用的HTML:

<div id="outer" class="container">
  <div id="inner" class="container">
    <ul>
      <li class="nav"><a href="#">One</a></li>
      <li class="nav"><a href="#">Two</a></li>
    </ul>
  </div>
</div>

下面是CSS的示例:

/* specificity: 0101 */
#outer a {
  background-color: red;
}

/* specificity: 0201 */
#outer #inner a {
  background-color: blue;
}

/* specificity: 0104 */
#outer div ul li a {
  color: yellow;
}

/* specificity: 0113 */
#outer div ul .nav a {
  color: white;
}

/* specificity: 0024 */
div div li:nth-child(2) a:hover {
  border: 10px solid black;
}

/* specificity: 0023 */
div li:nth-child(2) a:hover {
  border: 10px dashed black;
}

/* specificity: 0033 */
div div .nav:nth-child(2) a:hover {
  border: 10px double black;
}

a {
  display: inline-block;
  line-height: 40px;
  font-size: 20px;
  text-decoration: none;
  text-align: center;
  width: 200px;
  margin-bottom: 10px;
}

ul {
  padding: 0;
}

li {
  list-style-type: none;
}
源代码次序

如上所述,如果多个相互竞争的选择器具有相同的重要性和专用性,那么第三个因素将帮助决定哪一个规则获胜——后面的规则将战胜先前的规则。例如:

p {
  color: blue;
}

/* This rule will win over the first one */
p {
  color: red;
}

关于规则混合的一点注记

在考虑所有这些层叠理论和什么样式优先于其他样式被应用时,你应该记住的一件事是,所有这些都发生在属性级别上——属性覆盖其他属性,但你不会让整个规则凌驾于其他规则之上。
当多个CSS规则匹配相同的元素时,它们都被应用到该元素中。只有在这之后,任何相互冲突的属性才会被评估,以确定哪种风格会战胜其他类型。

让我们看一个例子。首先,一些HTML:

<p>I'm <strong>important</strong></p>

现在一些CSS风格与它:

/* specificity: 0002 */
p strong {
  background-color: khaki;
  color: green;
}

/* specificity: 0001 */
strong {
  text-decoration: underline;
  color: red;
}

在这个例子中,因为专用性的关系,第一条规则中的color属性覆盖掉了第二条中的颜色值。但是,对于第一条中的 background-color 的属性都在strong元素之中得到了体现。你也注意到了这个元素之中的字体是加粗的:这是浏览器默认的样式规则。

继承

CSS继承是我们需要研究的最后一部分,以获取所有信息并了解什么样式应用于元素。其思想是,应用于某个元素的一些属性值将由该元素的子元素继承,而有些则不会。

  • 例如,对 font-familycolor 进行继承是有意义的,因为这使得您可以很容易地设置一个站点范围的基本字体,方法是应用一个字体到 <html> 元素;然后,您可以在需要的地方覆盖单个元素的字体。如果要在每个元素上分别设置基本字体,那就太麻烦了。
  • 再如,让 marginpaddingborderbackground-image 不被继承是有意义的。想象一下,如果您将这些属性设置在一个容器元素上,并将它们继承到每个子元素,然后不得不将它们全部放在每个单独的元素上,那么将会出现的样式/布局混乱。
控制继承

CSS为处理继承提供了四种特殊的通用属性值:

  • inherit: 该值将应用到选定元素的属性值设置为与其父元素一样。
  • initial :该值将应用到选定元素的属性值设置为与浏览器默认样式表中该元素设置的值一样。如果浏览器默认样式表中没有设置值,并且该属性是自然继承的,那么该属性值就被设置为 inherit
  • unset :该值将属性重置为其自然值,即如果属性是自然继承的,那么它就表现得像 inherit,否则就是表现得像 initial
  • revert :如果当前的节点没有应用任何样式,则将该属性恢复到它所拥有的值。换句话说,属性值被设置成自定义样式所定义的属性(如果被设置), 否则属性值被设置成用户代理的默认样式。
重新设置所有的属性值

CSS速写属性 all 能够被应用到每一个继承属性,一次性应用所有的继承属性。这里的值可以是继承属性里的任何一个 (inherit, initial, unset, or revert)。对于撤销对样式的修改,这是非常方便的一种方式。然后你就可以在开始新的修改之前,返回到一个已知的开始点。

版权声明:本文来源简书,博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
  • 发表于 2020-01-12 14:13
  • 阅读 ( 29 )
  • 分类:前端

0 条评论

请先 登录 后评论