CSS 选择器的分类与优先级
CSS 选择器分为四类: 选择器, 选择符(后代关系的空格,>,+,~,||), 伪类, 伪元素(::before,::after,::first-letter 等).
CSS 的优先级:
CSS 的优先级有很多划分方法, 所有的方法其实都大同小异. 这里将 CSS 优先级划分为 6 个等级:
0 级: 通配选择器 (*), 选择符(+,>,~, 空格,||), 逻辑组合伪类(:not(),:is() 等)
1 级: 标签选择器
2 级: 类选择器, 属性选择器, 伪类
3 级: ID 选择器
4 级: style 内联属性
5 级:!important
CSS 优先级的计算规则: 0 级选择器优先级数值 + 0,1 级选择器 + 1,2 级选择器 + 10, 三级选择器 + 100
#foo a:not([ref=nofollow]){} 优先级数值: 100+1+0+10 = 111
tips1: 增加 CSS 优先级的小技巧
重复自身选择器, 如以下选择器即提高了优先级, 又不会增加耦合:
.foo.foo
或者如下写法:
.foo[class] , #foo[id]
tips2: 实现类似: first-child 的效果
有如下场景, 我们希望列表除了第一个第一个以外其他的都有 margin-top, 一般我们会这样写:
- 1:.cs:not(:first-child){
- margin-top:1em;
- }
- 2:.cs{
- margin-top:1em
- };
- .cs:first-child{
- margin-top:0
- }
下面我们利用兄弟选择器:
.cs+.cs{margin-top: 1em}
tips3: 实现前面兄弟选择符的效果
如下场景: 输入框聚焦时, 前面文字高亮显示
1:flex 布局;
2:float 浮动;
3:absolute 绝对定位;
4:direction 属性实现, 代码如下:
- <div class="cs-direction">
- <input class="cs-input"><label class="cs-label">用户名:</label>
- </div>
- .cs-direction{
- direction: rtl
- }
- .cs-direction .cs-input,.cs-direction .cs-label{
- direction: ltr;
- }
- .cs-label{
- display:inline-block;
- }
- :focus + .cs-label{
- color: darkblue;
- text-shadow: 0 0 1px;
- }
注意: 使用 direction 属性时, 针对的必须为内联元素, 因此, 对于块级元素需进行转化为内联
属性选择器
- [attr]
- [attr = ''val']
- [attr ~= 'val']
- [attr ^= 'val']
- [attr $= 'val']
- [attr *= 'val']
用户行为伪类
1: 手型经过伪类: hover(支持所有 html 元素)
一个简单的应用场景: 当鼠标经过 a 标签时,'显示' 文字显示, 因为: hover 是即时的, 所以通过 transition 对 visibility 进行过渡 (trantion 对 display 不起作用) 起到时延作用.
- <a href class="icon-delete" data-title="显示">删除</a>
- .icon-delete{
- display: inline-block;
- height: 20px;
- position: relative;
- }
- .icon-delete::before{
- content: attr(data-title);
- position: absolute;
- bottom: 30px;
- left: 0;
- }
- .icon-delete::before,
- .icon-delete::after {
- transition: visibility 0s 0.2s;
- visibility: hidden;
- }
- .icon-delete:hover::before,
- .icon-delete:hover::after {
- visibility: visible;
- }
纯 hover 显示浮层的体验问题: 纯 hover 显示浮层确实很方便, 但是如果鼠标坏了, 或者是触屏设备通过 Tab 来切换, 如果是一个下拉列表, 那么久完全瘫痪了, 我们可以通过增加: focus 来优化 CSS, 上述代码可以优化为:
- <a href class="icon-delete" data-title="删除">删除</a>
- .icon-delete{
- display: inline-block;
- height: 20px;
- position: relative;
- }
- .icon-delete::before{
- content: attr(data-title);
- position: absolute;
- bottom: 30px;
- left: 0;
- }
- .icon-delete::before,
- .icon-delete::after {
- transition: visibility 0s 0.2s;
- visibility: hidden;
- }
- .icon-delete:hover::before,
- .icon-delete:hover::after {
- visibility: visible;
- }
- .icon-delete:focus::before,
- .icon-delete:focus::after {
- visibility: visible;
- transition: none;
- }
但是, 上述并没有解决所有的问题, 如果浮层的内部有链接或者按钮的话, 使用: focus 浮层内的连接或者按钮是无法被点击的, 因为 Tab 在切换焦点元素的时候, 浮层会失焦而迅速隐藏. 这时需要另外一个伪类: focus-within 来解决, 详细我们在下面讨论.
2: 激活伪类: active
:active 可以用于设置元素激活状态的样式, 可通过点击鼠标主键, 也可以通过手指或者触控笔点击触摸屏触发激活状态. 具体表现为 点击按下触发, 点击抬起取消.:active 支持所有 HTML 元素
:active 的不足之处:
IE 浏览器下,:active 无法冒泡. 即当一个元素与父级都设置: active 样式时, 点击子元素, 父元素的: active 不会被触发
IE 浏览器, HTML,body 用: active 设置背景后, 背景色无法还原;
移动端 Safari 浏览器下,:active 伪类默认无效
按钮的通用: active 样式技巧(主要应用移动端)
在桌面端可以通过: hover 来反馈状态变化, 移动端只能通过: active 来反馈, 移动端有很多需求点击反馈链接跟按钮, 有如下通用技巧:
使用 box-shadow(兼容 IE9, 该方法对非对称闭合标签无效)
- [href]:active,button:active{
- box-shadow: 0 0 0 999px rgba(0,0,0,.05);
- }
使用 linear-gradient 线性渐变(兼容 IE10 以上)
- [href]:active,button:active,[type=reset]:active,[type=button]:active,[type=submit]:active{
- background-image: linear-gradient(rgba(0,0,0,.05),rgba(0,0,0,.05));
- }
3: 焦点伪类: focus(支持 IE8+)
:focus 只能匹配特定的元素, 包括:
非 disabled 状态的表单元素;
包含 href 的 < a > 元素
<area>,<summary>
那么如何让普通的元素也可以用: focus 伪类呢?
设置 HTML tabindex 属性, 如下写法:
- <div tabindex='-1'>内容</div>
- <div tabindex='0'>内容</div>
- <div tabindex='1'>内容</div>
如果期望 < div > 元素被 Tab 索引, 且被点击的时候触发: focus 伪类样式, 设置 tabindex='0'; 如果期望不希望被索引, 只在点击的时候触发: focus, 则设置为 - 1.
如下, 实现点击一个图标显示大图的交互:
- <span class="cs-small" tabindex='0'></span><span class="cs-big"></span>
- .cs-small{
- display: inline-block;
- width: 10px;
- height: 10px;
- background: green;
- };
- .cs-big{
- display: inline-block;
- width: 50px;
- height: 50px;
- background: green;
- margin-left: 10px;
- display: none;
- };
- :focus + .cs-big{
- display: inline-block;
- }
实际上, 使用 tabindex 也并不是那么完美, 在 iOS Safari 浏览器下, 元素处于 focus 状态后, 除非有其他可聚焦的元素转移焦点, 否则会一直保持聚焦状态. 解决方法只需要再套个父盒子, 设置 tabindex='-1', 同时该复盒子需要取消 outline 样式(outline:0 none;)
4: 整体焦点伪类: focus-within(移动端以及非 IE 浏览器)
:focus-within 功能通: focus 类似, 但是: focus 是对当前元素而言,:focus-within 在当前元素或者当前元素的子元素处于聚焦状态都会匹配.
例::focus-within 实现无障碍访问的下拉列表, 解决上面: focus 在浮层里也有链接无法 Tab 切换的问题:
- <div class="cs-bar">
- <div class="cs-details">
- <a href='javascript:void(0)' class="cs-summary">我的消息</a >
- <div class="cs-datalist">
- <a href class="cs-datalist-a">我的回答 < sup class="cs-datalist-sup">12</sup>
- </a >
- <a href class="cs-datalist-a">我的私信</a >
- </div>
- </div>
- </div>
- cs-bar {
- background-color: #e3e4e5;
- color: #888;
- padding-left: 40px;
- margin-bottom: 200px;
- }
- .cs-details {
- display: inline-block;
- text-align: left;
- }
- .cs-summary {
- display: inline-block;
- padding: 5px 28px;
- text-indent: -15px;
- user-select: none;
- position: relative;
- z-index: 1;
- }
- .cs-datalist {
- display: none;
- position: absolute;
- min-width: 100px;
- border: 1px solid #ddd;
- background-color: #fff;
- margin-top: -1px;
- }
- .cs-datalist-a {
- display: block;
- padding: 5px 10px;
- transition: background-color 0.2s, color 0.2s;
- color: inherit;
- }
- .cs-datalist-a:hover {
- background-color: #f5f5f5;
- }
- .cs-datalist-a:active {
- background-color: #f0f0f0;
- color: #555;
- }
- .cs-datalist-sup {
- position: absolute;
- color: #cd0000;
- font-size: 12px;
- margin-top: -0.25em;
- margin-left: 2px;
- }
- .cs-details:focus-within .cs-summary,
- .cs-summary:hover {
- background-color: #fff;
- }
- .cs-details:focus-within .cs-datalist {
- display: block;
- }
URL 定位伪类
:link 伪类(基本被 a 标签取代, 不做讨论)
:visited 伪类(怪癖最多的 CSS 伪类)
1: 支持: visited 的 CSS 属性有限
目前仅支持以下 CSS: color,background-color,border-color,border-bottom-color,border-top-color,border-left-color,border-right-color,column-rule-color,outline-color. 类似::before 跟::after 也不支持.
例: 实现访问过的连接文字后面加上一个 visited 的字样
- <a href=''>文字 < small></small></a>
- small{
- color: white;
- }
- small:after{
- content: 'visited';
- }
- a:visited small{
- color: lightskyblue;
- }
2: 没有半透明, 该伪类控制颜色时, 加透明度无效
3: 只能重置, 不能凭空设置
如下:
- a{
- color: blue;
- }
- a:visited{
- color: red;
- background-color: gray;
- }
以上代码设置只会使 color 生效.
4: 无法获取: visited 设置和呈现的色值
该伪类设置的色值, 用 JS 的 getComputedStyle()无法获取.
:any-link 伪类(IE9+)
两大特性:
1. 匹配所有设置了 href 的连接元素, 包括 < a>,<link>,<area>
2. 匹配所有匹配: link 伪类或者: visited 伪类的元素(:link 只匹配没有访问过的连接)
目标伪类: target
URL 锚点可以跟页面中元素的 id 匹配进行锚定, 例:
- <div>
- <p id='cs-first'>第一行, id:cs-first</p>
- <p id='cs-second'>第二行, id:cs-second</p>
- <p id='cs-last'>第三行, id:cs-last</p>
- </div>
- p:target{
- font-size: bold;
- color: skyblue;
- }
通过链接的 hash 值就可以匹配到对应的元素
树结构伪类
:root 伪类
在 HTML 中: root 等同于 HTML 元素;
:empty 伪类
:empty 用来匹配空标签元素
:empty 伪类可以匹配前后闭合的替换元素(button,textarea 等);
:empty 伪类匹配非闭合的元素(input,img 等)
若元素有注释或者空格, 换行等都是不能匹配到的
::before,::after 都可以插入内容, 但是不会影响: empty 的匹配
:empty 的实际应用
隐藏空元素.
比如像一个动态列表有内容的时候可能会加 margin,padding 等布局, 但是没有内容的时候就会空出一大块, 这时候就可以用: empty 伪类在匹配到空的时候隐藏掉.
字段缺失只能提示
如在一个动态详情列表中, 如果对应的字段没有内容, 则在后面显示 '暂无'的字样, 代码如下:
- <dl>
- <dt > 姓名:</dt><dd > 张三</dd><br/>
- <dt > 年龄:</dt><dd></dd><br/>
- <dt > 身高:</dt><dd>178cm</dd>
- <dl>
- dt,dd{
- display: inline-block;
- }
- dd:empty:before{
- content: '暂无';
- }
子索引伪类
- :first-child,:last-child
- :only-child
:nth-child()伪类和: nth-last-child()伪类
适用于动态匹配场景, 可以匹配制定索引序号的元素. 参数可以是关键字(odd/even), 也可以是函数符号.
函数符号形式如下:
An+B: A,B 必须为整数, n 前面可以有负数, n 为从 1 开始的自然序列(0,1,2.....), 第一个子元素匹配序号为 1.
一些示例:
tr:nth-child(odd), 匹配 1,3,5..... 行;
tr:nth-child(even), 匹配 2,4,6.....;
li:nth-child(1), 匹配第一个;
li:nth-child(n+4):nth-child(-n+10): 匹配 4-10 个 li
:first-of-type 伪类和: last-of-type 伪类
表示当前标签类型元素第一个和最后一个
:only-of-type
:nth-of-type()伪类和: nth-last-of-type 伪类
:nth-of-type 与: nth-child 的不同之处::nth-of-type 匹配的是所有相同标签的兄弟元素, 而另一个无视标签类型.
- <div>
- <h3 > 标题一</h3>
- <p > 段落一</p>
- <p > 段落二</p>
- <h3 > 标题二</h3>
- <p > 段落三</p>
- <p > 段落四</p>
- </div>
- p:nth-child(2n+1){
- color: red;
- }
- p:nth-child(4n){
- color: darkblue;
- }
- p:nth-of-type(2n+1){
- color: skyblue;
- }
图中, 第 2,5 行为浅蓝色, 第三行为红色.
逻辑组合伪类
否定伪类: not()
:not()主要的应用场景为重置 CSS
例: input:not(:disabled):not(:read-only)()
表示匹配所有不处于禁用, 也不是只读状态的 input
例: 列表一行 5 个, 每个都向右有空隙, 每一行的最后一个没有空隙;
- li:not(:nth-of-type(5n+1)){
- margin-right: 10px;
- }
任意匹配伪类: is()
例:
- .cs-a img,.cs-b img,.cs-c img,.cs-d img{
- border: 1px solid skyblue;
- }
可以简化为如下:
- :is(.cs-a,.cs-b,.cs-c,.cs-d) img{
- border: 1px solid skyblue;
- }
- :where(),:has()
输入伪类
输入控件状态:
可用状态与禁用状态伪类 :enabled 和: disabled (IE9+)
对于表单元素来说,:enable 跟: disabled 是完全对立的. 但是有一个例外 < a > 元素, 在 Chrome 浏览器下, 带 href 的 a 元素是可以匹配: enabled 伪类的, 但是却无法匹配: disabled 伪类, 其他浏览器也有各种各样的问题, 不展开讨论.
设置 tabindex 属性的元素不能匹配: enabled 伪类;
元素设置 visibility:hidden 跟 display:none 的能够匹配: enabled 伪类跟: disabled 伪类.
读写特性伪类: read-only 和: read-write
readonly 与 disabled 的区别:
设置 readonly 的输入框不能输入内容, 但是可以被表单提交;
设置 disabled 的输入框不能输入内容美也不能被表单提交.
占位符显示伪类: placeholder-shown(除 IE)
表示当输入框的 placeholder 内容显示的时候, 匹配输入框
由于其只在内容为空值状态的时候才显示, 所以我们可以借助 placeholder-shown 伪类来判断一个输入框是否有值.
例: 输入框没有值得时候显示空值提示
- input:placeholder-shown + small:before{
- content: '尚未输入验证码';
- color: red;
- }
默认选项伪类 default
输入值状态:
选中选项伪类: checked
:checked 与 [checked] 的比较:
:checked 只能匹配标准的表单控件元素,[checked]可以与任意元素匹配;
[checked]是非实时的, 因此不建议用此属性选择器;
伪类可以从祖先元素继承;
不确定值伪类: indeterminate
输入值验证:
有效验证伪类: valid 和: invalid
范围验证伪类: in-range 和: out-of-range
可选性伪类: required 和: optional
参考资料:
来源: https://www.cnblogs.com/ylweb/p/12348605.html