CSS3选择器模块

CSS3于2010年推出,在CSS3中,将整体的结构划分为小的模块。
模块主要有选择器、盒模型、背景和边框、文字特效、2D/3D转换、动画、多列布局、用户界面等。
下面通过不同的分类介绍一下CSS3的选择器模块。

1. 属性选择器

(1) 传统属性选择器

E[attr = ""]

(2) 匹配以提供的值开头

E[attr ^= ""]

(3) 匹配以提供的值结尾

E[attr $= ""]

(4) 匹配包含的字符串

匹配的属性可以是自定义属性。

E[attr *= ""] 
input[textInex *= "nor"] { }
input type="text" textIndex="normal" /> username

(5) 以单词(空格)作为选择元素

以空格区分的元素都可以识别。

E[attr ~= ""]
input[type~="irst"] { }
<input type="text" textIndex="normal irst" /> username
<input type="passworld" textIndex="normal second" /> password

(6) 匹配以提供的值(value)为开头,或以提供的值(value-)

E[attr |= ""]

目前这种选择器,只有匹配语言简写代码的场景才会使用。

p[lang |= 'en'] {}
<p lang="en-us" />

2. 结构伪类选择器

(1) :root

:root 相当于HTML根节点,可以使用这种方式匹配HTML节点。
:root的权重(优先级)比直接定义属性样式高。

:root {}

(2) E:not

寻找不是指定匹配规则的元素。
:not 的权重根据参数来计算的,本身的优先级是根据属性的优先级来判断的。
:not 无法排除父级元素,只应用在选择同级元素上。

input:not ([textInent$="first"]) { }

:not 使用时存在一个小问题,就像下面这样。

:not(table) a {
  color: red;
}
<div>
  <a href="">这是div的a标签</a>
</div>
<table>
  <a href="">这是table中的a标签</a>
</table>

如果不指定 :not 的范围,会导致选择器失效,所有a标签颜色都为红色。
解决方案是给定选择器范围,就可以正常选择。

// 1. 第一种
body :not(table) a {
  color: red;
}

// 2. 第二种 
div:not(table) a {
  color: red;
}

(3) E:empty

选择子元素的元素节点或文本节点为空。
不包括换行和空格, HTML在解析换行和空格时,会将其解析成文本。

div {
  width: 100px;
  height: 100px;
  border: 1px solid #000;
}

.box:empty {
  border: 1px solid orange;
}
<div class="box"><!-- 有注释的空元素 --></div>
<div class="box">这是空的元素</div>
<div class="box">
  <!-- 有换行的空元素 -->
</div>

通过示例代码来看,只有第一个盒子才会被选中。

(4) :target

选择a标签的锚点,用户选择到指定的元素之后,指定的target就会生效。

:target {
  background-color: black;
}
<h4 id="one">这是h4标签</h4>
<p id="two">这是p标签</p>
<div id="three">这是div标签</div>
<a id="four" href="/">这是a标签</a>
<em id="five">这是em标签</em>

<a href="#one">First</a>
<a href="#two">Second</a>
<a href="#three">Third</a>
<a href="#four">Fouth</a>
<a href="#five">Fifth/a>

(5) :first-child、:last-child、:nth-child、 :nth-last-child

:first-child:选择第一个元素
:last-child:选择最后一个元素
:nth-child:选择指定下标的元素(下标从1开始)
:nth-last-child:倒数选择指定下标的元素(下标从1开始)

:nth-child 和 nth-last-child 会寻找相邻的兄弟元素的匹配项,不会查看类型,嵌套的符合条件也会被选择。
参数可以为odd(奇数),even(偶数),2n(偶数),2n+1(奇数),参数可以是 αn + β 的形式。
α 表示指定循环的个数,β 指定具体出现的位置。

p:nth-child(4n + 1) { }

(6) :first-of-type、last-of-type、nth-of-type

与前一种相比,可以指定选择类型,会限制元素出现的类型。
不指定类型时,会选择多个符合条件的元素,嵌套的符合条件也会被选择。

div span:first-of-type { }

(7) only-child

寻找某一个父级下唯一的子元素。

.box :only-child {
  color: red;
}
<div class="box">
  <div>
    <i>只有一个子元素</i>
  </div>
  <div>
    <i>我是i标签</i>
    <em>我是em标签</em>
    <span>
      我有一个<span>嵌套span</span>标签
    </span>
  </div>
</div>

3. UI元素状态伪类选择器

UI元素状态伪类选择器,即当元素处于某种状态下,才会生效的选择器。

(1) :hover

鼠标移入的状态。

(2) :focus

鼠标聚焦时的状态,常被应用于 input 标签。

(3) :active

元素被激活的状态(鼠标按下未松开)。

(4) :enabled、:disabled、:read-only、:read-write

能够被激活的元素才有这个状态。

:enabled 表单可用的状态
:disabled 表单禁用用的状态
:read-only 表单只读的状态
:read-write 表单可读写
关于只读属性和禁用属性
只读属性和禁用属性都是不可输入,两者作为表单元素唯一的区别在于,
readonly的数据是可以被提交的,disabled的数据不会被提交。

disabled、enabled

input[type = "text"]:disabled {
  background-color: orange;
}

input[type = "password"]:enabled {
  background-color: red;
}
<input type="text" disabled /> username
<input type="password" /> password

readonly、read-write

input[type = "text"]:read-only {
  background-color: orange;
}

input[type = "password"]:read-write {
  background-color: red;
}
<input type="text" readonly /> username
<input type="password" /> password

注意:disabled依然是可读可写的状态,禁用不代表元素不可写。两者并不任何关系。

(5) :checked、:default、:indeterminate

:checked 被选中状态
:default 默认状态(默认选项),默认被选中
:indeterminate 页面打开时,没有被选中的状态,不确定的状态。

:checked,表单中仅限于单选框和复选框中被选中的状态,自定义radio的时候,可以使用这个状态。

:checked :default

input[type = "radio"]:checked {
  outline: 2px solid #000;
}

input[type = "checkbox"]:checked {
  outline: 2px solid #000;
}

input[type = "checkbox"] {
  outline: 2px solid orange;
}
<input type="radio" />
<input type="checkbox" />
<input type="checkbox" />

:defualt 指页面打开时,处于选中状态的单选框和复选框的样式。

input[type = "radio"]:default {
  outline: 2px solid orange;
}

input[type = "checkbox"]:checked {
  outline: 2px solid #000;
}

input[type = "checkbox"]:default {
  outline: 2px solid orange;
}
<input type="radio" checked />

<input type="checkbox" id="read" checked />
<label for="read">阅读</label>
<input type="checkbox" id="tourist" />
<label for="tourist">旅游</label>
<input type="checkbox" id="playing" />
<label for="playing">打球</label>
单选框的默认选中状态,:default状态存在兼容性问题,IE没有实现:default属性。

:indeterminate

:indeterminate, :indeterminate + label {
  background-color: blue;
}
<div>
  <input type="radio" id="checkbox" />
  <label for="checkbox">这是input1</label>
</div>

<div>
  <input type="radio" id="radio" checked />
  <label for="radio">这是input1</label>
</div>

radio单选标签的效果并不理想,点击时背景颜色并不会消失。存在兼容性问题。

<div>
  <input type="checkbox" id="checkbox" />
  <label for="checkbox">这是input1</label>
</div>

<div>
  <input type="checkbox" id="radio" />
  <label for="radio">这是input1</label>
</div>
<script type="text/javascript">
  var inputs = document.getElementsByTagName('input');
  Array.from(inputs).forEach(item => (item.indeterminate = true));
</script>

checkbox的效果比较好,需要配合JS一起使用。

4. 伪元素选择器

(1) ::before、::after

(2) ::first-letter、::first-line、::selection

::first-letter 选择第一个字母(字)
::first-line 选择第一行的字
::selection 文本被选中时的状态

::first-letter, ::first-line, 在块级元素中才会生效,也不支持荷兰文字。
这几个选择器并不是所有的样式都可以指定,比如background-color属性等,会被忽略掉。

.box {
  width: 200px;
  height: 200px;
  border: 1px solid #000;
}

.box p::first-line {
  color: orange;
}
.box p::first-letter {
  color: red;
}
.box p::selection {
  color: aquamarine;
}
<div class="box">
  <p class="text">
    测试测试测试测试测试测试测试测试
    测试测试测试测试测试测试测试测试
  </p>
</div>
user-select属性
可以设置文本不可选中,不过仅限于测试使用,生产环境不要使用,需要使用JS来限制。
user-select: none;

5. 关系选择器

(1) E F

后代选择器。

(2) E > F

直接子元素选择器,选择自己的下一代。

div span {
  background-color: orange;
}

div > span {
  background-color: blue;
}
<div>
  <span>
    这是span1
    <span>这是span2</span>
  </span>
</div>

(3) E + F

相邻兄弟选择器,只能寻找相邻的兄弟元素,不包括本身。

.text1 + p {
  background-color: orange;
}
<p class="text1">这是第1个p元素</p>
<p class="text2">这是第2个p元素</p>
<p class="text3">这是第3个p元素</p>
<p class="text4">这是第4个p元素</p>
<p class="text5">这是第5个p元素</p>

(4) E ~ F

一般兄弟选择器,可以寻找多个兄弟元素,往下(后)寻找,包括嵌套的p元素。

.text1 ~ p {
  background-color: orange;
}
<p class="text1">这是第1个p元素</p>
<p class="text2">这是第2个p元素</p>
<p class="text3">
  这是第3个p元素
  <p>这是里面的p元素</p>
</p>
<p class="text4">
  这是第4个p元素
  <p>这是里面的p元素</p>
</p>
<p class="text5">这是第5个p元素</p>

6. 总结

本篇文章介绍了CSS3的选择器模块,具体的细节还需要继续深究。
通过介绍,可以看到CSS3在CSS2.1之上,新增了很多功能。除此之外,
CSS3的兼容性是非常好的,IE10也全面支持CSS3,手机端的浏览器基本都使用响应式布局。
所以我们的原则是能用CSS3解决的问题,绝对不用JS,当前原则是原则,具体场景还需慎重考虑。