TanXinNiao / blog

贪心鸟的博客
0 stars 0 forks source link

CSS权威指南(第4版)第二章 选择符 #12

Open TanXinNiao opened 3 years ago

TanXinNiao commented 3 years ago

声明和关键字

可以看出,CSS关键字通常以空格分隔。在CSS2.1中,有个特例:font属性的值有一 处要使用斜线(/)把两个关键字隔开。下面举个例子: h2 {font: large/150% sans-serif;} 这个斜线把设定元素字号和行高的两个关键字分开。font声明只有这一个地方允许出现 斜线,其他关键字都以空格分隔 除此之外,其他一些属性的值中也可以使用斜线,比如说(不完整): • background • border-image • border-radius • grid • grid-area • grid-column • grid-row • grid-template • mask-border 还有一些关键字以逗号分隔。声明多个背景图像、过渡属性和阴影时,相互之间以逗号 分隔。此外,函数的参数,例如线性渐变和变形函数,以逗号分隔,如下例所示:

.box {
  box-shadow: inset -ipx -ipx white,
  3px 3px 3px rgba(0,0,0,0.2);
  background-image: url(myimage・png),
  linear-gradient(18Odeg, #FFF 0%, #000 100%);
  transform: translate(100px, 200px);
}
a:hover (transition: color, background-color 200ms ease-in 50ms;}
TanXinNiao commented 3 years ago

类选择符和ID选择符

实际上,浏览器不一定总会检査HTML中的ID是不是唯一的。也就是说,如果 HTML文档中的多个元素具有相同的1D属性,相同的样式可能会应用到每个元 素上。这是不正确的行为,但却可能发生。文档中出现多个相同的ID值还不利于 DOM脚本编程,因为getElementById()等函数预期只有一个ID属性为指定值的 元素。

与类选择符不同,ID选择符不能串在一起使用,因为ID属性的值不能是以空格分隔的 列表

TanXinNiao commented 3 years ago

根据部分属性值选择

形式 | 说明 [foo|="bar"] | 选择的元素有foo属性,且其值以bar和一个英文破折号(U+002D)开头,或者 值就是bar本身 [foo~="bar"] | 选择的元素有foo属性,且其值是包含bai这个词的一组词 [foo*="bar"] | 选择的元素有foo属性,且其值包含子串bar [foo^="bar"] | 选择的元素有foo属性,且其值以bar开头 [foo$="bar"] | 选择的元素有foo属性,且其值以bar结尾

TanXinNiao commented 3 years ago

伪类

开始之前,先说一下串联。CSS允许把伪类拼接(串联)在一起。例如,可以把有鼠标 悬停其上的未访问链接显示为红色,把有鼠标悬停其上的已访问链接显示为红褐色: a:link:hover {color: red;} a:visited:hover {color: maroon;}

拼接伪类的顺序其实没什么关系,也可以写成a:hover:link,它的效果与a:link:hover 一样。此外,还可以分别为其他语言(例如德语)下的未访问链接和已访问链接指定悬 停样式: a:link:hover:lang(de) {color: gray;} a:visited:hover:lang(de) (color: silver;}

在HTML文档中可以直接选择html元素,而不使用:root伪类。然而这两个选择符的 特指度不同

选择空元素 使用:empty伪类可以选择没有任何子代的元素,甚至连文本节点都没有(包括文本和 空白)CMS经常生成没有任何内容的空元素,此时便可以使用这个伪类。例如,p:empty {display: none;}能禁止显示空段落。

注意,为了能正确匹配,从解析的角度来看,元素必须真的为空,没有有空白、可见内容或后代元素。对下面几个元素来说,只有第一个和最后一个能被p:empty匹配:

<p></p>
<p> </p>
<P>
</p>
<p><!--注释--></p>

第二个和第三个段落不能被:empty匹配,因为它们不是空的,而是分别有一个空格和 一个换行符。这两种空白都算文本节点,因此也就不是空的。最后一个段落之所以能匹配, 是因为注释不是内容,也不是空白。然而,如果在注释的某一边加上一个空格或一个换 行符,p:empty就无法匹配了。

你可能想使用*:empty (display: none;}装饰所有空元素,但是这里有一个陷阱,:empty 是能匹配HTML文档中的空元素,例如img和input,但是还能匹配里面没有内容的 textareao就匹配元素的效果而言,img和img:empty其实是一样的(不过二者在特指 度上有区别,详情参见下一章)。

选择唯一的子代 如果想选择带超链接的图像,可以使用:only-child伪类。它选择的元素是另一个元素的 唯一子元素。假设你想为作为另一个元素唯一子元素的图像加上边框,可以使用: img:only-child {border: Ipx solid black;} 这个规则会应用到符合条件的每一个图像上。因此,如果一个段落中只有一个图像,没 有其他子元素,那个图像就会独立于周围的文本被选中。如果想选择作为超链接唯一子 代的图像,只需把选择符改为 a[href] img:only-child (border: 2px solid black;}

关于:only-child伪类,有两点要注意。首先,前文说过,它始终依附在希望是唯一子 元素的那个元素上,而不是父元素。由此引出第二点,即在后代选择符上使用:only-child伪类时,列出的元素不一定是父子关系。

对前面超链接中的图像示例来说,a[href] img:only-child匹配的图像是唯一的子元素, 而且是a元素的后代,而不是a元素的子元素。匹配时,那个元素必须是其直接父元素 的唯一子元素,而且是链接的后代,但是图像的父元素自身也可以是链接的后代。因此, 下面三个图像都能匹配

a[href] img:only-child (border: 5px solid black;}
<a href="http://w3.org/"ximg src="w3.png" alt="W3C"x/a>
<a href = "http://w3.org/"><spanximg src="w3.pngM alt="W3C></spanx/a>
<a href="http://w3.org/">A link to <span>the <img src="w3.png" alt='"*>
web</span> site</a> 

:only-of-type 这两个伪类之间的区别是,:only-of-type匹配同胞中唯一的那种元素,而:only-child 只匹配完全没有同胞的元素。

TanXinNiao commented 3 years ago

选择第一个和最后一个子代

人们对p:first-child这样的选择符最大的误解是,认为它选择的是p元素的第 一个子元素。还记得伪类的特点吗?它为所依附的元素设定某种幽灵类。如果添加真正 的类,标记将变成:

<div>
    <p class=,,first-child,,>These are the necessary steps:</p>
    <ul>
      <li class="first-child">Insert key</li>
      <li>Turn key <strong class="first-child">clockwise</strong></li>
      <li>Push accelerator</li>
    </ul>
    <P>
      Do <em class="first-child">not</em> push the brake at the same time as the accelerator.
    </p>
  </div>
TanXinNiao commented 3 years ago

选择每第n个子元素

nth-child伪类 假设我们想从一个无序列表的第一个列表项目开始,选择每第三个列表项目。此时,可 以使用下述选择符,选择第一个和第四个列表项目 ul > li:nth-child(3n + 1){text-transform: uppercase;} 这里的n表示0、1、2、3、4, 一直到无穷大。浏览器求解3n + 1时,得到的结果为1、 4、7、10、13等。如果没有+ 1那部分,只剩下3n,得到的结果是0、3、6、9、12等。 因为没有第0个列表项目(与数组不同,HTML元素从第一个数起),所以这个表达式 选中的第一个元素是第三个列表项目。

(2n)选择的是偶数位的子代, 而:nth-child(2n+l)或:nth-child(2n-l)选择的是奇数位的子代。也可以使用两个特殊的关键字:even和odd。想从表格的第一行起每隔一行突出显示? 可以这么做 tr:nth-child(odd) {background: silver;}

装饰表格中间隔的行 比间隔元素复杂的情况都要使用代数式an + bo 注意,如果想让b使用负数,要把前面的+号删掉,否则选择符无效。对下面两个规则 来说,只有第一个会起作用。解析器不解析第二个规则,而是将其忽略。

tr:nth-child(4n - 2) {background: silver;}
tr:nth-child(3n + 2) {background: red;}

如果想选择从第9行起的每一行,可以使用下面两个规则中的一个。二者的共同点是都 会选择第9行起的每一行,不过后者的特指度更高

tr:nth-child(n + 9) (background: silver;}
 tr:nth-child(8) ~ tr {background: silver;}

你可能猜到了,有个与之对应的伪类:nth-last-child()它的作用与:nth-child() 一 样,只不过是从一组同胞的最后一个元素开始

选择每第n个某种元素

:nth-child()和:nth・last・child()伪类有对应的 :nth-of-type()和:nth-last-of-type()

TanXinNiao commented 3 years ago

动态伪类

除了结构伪类之外,还有一些与结构有关的伪类,不过它们在页面渲染之后根据页面的 变化而变化。也就是说,为了把这些伪类定义的样式应用到文档中的某一部分上,除了 文档的结构,还要考虑其他事情,而且通过文档的标记很难准确推出应用样式的方式。

拿锚记元素(a)来说,(在HTML及相关的语言中)它的作用是从一个文档链接到另 一个文档。锚记始终是锚记,但是有些锚记指向的页面已经访问过,而有些尚未访问。 从HTML标记中是看不出这一区别的,因为所有锚记的句法都是一样的。若想知道链接 到底有没有访问,只能与用户的浏览器历史记录比较。因此,链接基本上有两种状态: 已访问和未访问。

:link 指代用作超链接的锚记(即具有href属性),而且指向尚未访问的地址 :visited 指代指向已访问地址的超链接。出于安全考虑,能应用到已访问链接上的样式十分有 限。

TanXinNiao commented 3 years ago

UI状态伪类

伪类 | 说明 :enabled 指代启用的用户界面元素(例如表单元素),即接受输入的元素 :disabled 指代禁用的用户界面元素(例如表单元素),即不接受输入的元素 :checked 指代由用户或文档默认选中的单选按钮或复选框 :indeterminate 指代既未选中也没有未选中的单选按钮或复选框:这个状态只能由D0M脚本 设定,不能由用户设定 :default 指代默认选中的单选按钮、复选框或选项 :valid 指代满足所有数据有效性语义的输入框 :invalid 指代不满足所有数据有效性语义的输入框 :in-range 指代输入的值在最小值和最大值之间的输入框 :out-of-range 指代输入的值小于控件允许的最小值或大于控件允许的最大值的输入框 :required 指代必须输入值的输入框 :optional 指代无需一定输入值的输入框 :read-write 指代可由用户编辑的输入框 :read-only 指代不能由用户编辑的输入框

虽然UI元素的状态能被用户操作改变,例如用户勾选或不选一个复选框,但是UI状态 伪类不是单纯动态的,因为它们还受文档结构或DOM脚本的影响。

TanXinNiao commented 3 years ago

target 伪类

URL中有个片段标识符(fragment identifier),它所指向的文档片段(在CSS中)称为 目标(targei)。URL片段标识符指向的目标元素可以使用:target伪类特别装饰。

即便不知道“片段标识符”这个术语,你肯定也见过。比如下面这个URL: http://www.w3.org/TR/css3-selectors/#target-pseudo

这个URL中的target-pseudo部分就是片段标识符,由#符号标记。如果对应的页面 (http://www.w3.org/TR/css3-selectors/)中有 ID 为 target-pseudo 的元素,那个元素就 是片段标识符的目标。

借助:target伪类,我们可以突出显示文档中的任何目标元素,或者为不同的目标元素 定义不同的样式

:target伪类定义的样式在两种情况下不会应用:

  1. 页面的URL中没有片段标识符。
  2. 页面的URL中有片段标识符.但是文档中没有与之匹配的元素。
TanXinNiao commented 3 years ago

:lang 伪类

如果想根据文本使用的语言选择元素,可以使用:lang()伪类。在匹配方式上,:lang() 伪类与|=属性选择符类似。假设想让使用法语编写的元素倾斜显示,可以编写下述规 则中的任何一个 :lang(fr) (font-style: italic;} [lang|="fr"]{font-style: italic;}

TanXinNiao commented 3 years ago

否定伪类

目前介绍的所有选择符有个共同点:都是肯定选择符。也就是说,这些选择符用于指定 应该选择的东西,排除不匹配(即不选择)的东西。 如果想反过来,选择不满足条件的元素,可以使用Selectors Level 3引入的否定伪类 :not()0这个伪类与其他选择符不太一样,而且自身有一些限制。暂不讨论细节,先看 一个例子。

假设你想装饰class属性不是moreinfo的列表项目,如图2-42所示。以前,这个需求 很难实现,而且某些情况下根本实现不了。如果想让除了类为.moreinf。之外的列表项 目倾斜显示,过去我们要先让所有列表项目都倾斜(一般是通过类选择ul),然后再通 过.moreinfo类把特定的列表项目还原。这么做要确保.moreinfo样式在源码中的位置 靠后,而且要具有相同或更高的特指度。现在,我们可以像这样声明样式: li:not(.moreinfo){font-style: italic;}

:not()伪类依附在元素上,括号中是简单的选择符。根据W3C的定义,简单的选择符指: 一个类型选择符、通用选择符、属性选择符、类选择符、ID选择符或伪类。

基本上,简单选择符是指没有祖辈-后代关系的选择符。

注意定义中的“或”,它的意思是:not()伪类中只能使用其中一个选择符。不能使用 群组选择符,也不能使用连结符,因此不能使用后代选择符,因为后代选择符中分隔元 素的空格是连结符。这些限制在未来可能撤销(极有可能),不过就算有这些限制,我 们仍然可以通过它做很多事情。

TanXinNiao commented 3 years ago

伪元素选择符

伪元素与伪类很像,为了实现特定的效果,它在文档中插入虚构的元素。CSS2定义了 四个基本的伪元素,分别用于装饰元素的首字母、首行,以及创建和装饰“前置”和“后 置”内容。CSS2之后的规范又定义了其他伪元素(例如::marker)

伪类使用一个冒号,而伪元素使用一对冒号,例如::first-lineo这么做是为了把伪元 素与伪类区分开。一开始并不是这样的,在CSS2中,这两种选择符都使用一个冒号。 因此,为了向后兼容,浏览器也接受使用单个冒号的伪元素选择符。但是,不要因为这
样就懈怠。为了确保你编写的css在未来还能继续使用,应该使用正确的冒号个数,毕 竟我们无法预知浏览器什么时候不再接受单个冒号的伪元素选择符。

所有伪元素只能出现在选择符的最后。p::first-line em是无效的,因为伪元素 在选择符的主词前面(主词是选择符中的最后一个元素)这也表明一个选择符中只能 有一个伪元素,不过在CSS以后的版本中可能会取消这一限制。

TanXinNiao commented 3 years ago

装饰首字母

p:first-of-type::first-letter {font-size: 200%;} 这个规则其实相当于让用户代理装饰每个p元素中包围首字母的一个虚构元素。比如 这样: <pxp-first-letter>T</p-first-letter>his is a p element, with a styled first letter</h2> ::first-letter样式只应用于上例中虚构的那个元素里的内容。元素不 会出现在文档的源码中,也不会出现在DOM树中,而是由用户代理动态构建,目的是 把::fiist-letter样式应用到相应的文本上。也就是说,叩(first-letter)是个伪元素。 注意,你无需添加任何新标签。用户代理会代为装饰首字母,就像把首字母放到一个元 素中一样。

::first-letter 和::first-line 的限制

::first-letter 和::first-line伪元素只能应用到块级元素上,例如标题或段落, 不能应用到行内元素上,例如超链接。 样式中可以使用 的CSS属性也有限制 ::first-letter ::first-line 所有字体属性 | 所有字体属性 所有背景属性 | 所有背景属性 所有文本装饰属性 | 所有外边距属性 所有行内排版属性 | 所有内边距属性 所有行内布局属性 | 所有边框属性 所有边框属性 | 所有文本装饰属性 box-shadow | 所有行内排版属性 color | color opacity | opacity

TanXinNiao commented 3 years ago

装饰(或创建)前置和后置内容元素

假设根据排版效果,需要在h2元素前面加上两个银色的方括号: h2::before {content: **]]"; color: silver;} 生成的内容是一个单独的话题,第15章将对此进行更为深入的介绍(还包括::before 和::after的详细说明)