呜啦!日常碎碎念,偶尔掉落优质前端博文推荐、学习资源等
网页:https://tg.cosine.ren
本频道的搜索Bot 来辣 👉 @cosSearchBot
私聊直接发消息就可以搜索啦~
🔖tags
#优质博文 #资源推荐 #博客更新 #碎碎念 #项目更新 #手工 #书摘 #阮一峰的科技周刊 #新动态

图频:Cosine 🎨 Gallery @CosineGallery
猫片: @cosine_cat
联系频道主:@cosine_yu
#书摘 #css #前端
《CSS 选择器世界》键盘焦点伪类 :focus-visible
:focus-visible 伪类虽然和 :focus-within 伪类看起来很相似,但两者的作用大相径庭,被浏览器开始支持的时间也有较大区别::focus-within伪类已被浏览器支持很多年了,而:focus-visible伪类则在2022年3月才被所有现代浏览器支持。
1. :focus-visible伪类的作用及背景变化
:focus-visible伪类匹配的场景是元素聚焦,同时浏览器认为聚焦轮廓应该显示。
是不是很拗口?规范就是这么定义的。:focus-visible的规范并没有强行约束匹配逻辑,而是交给了UA(也就是浏览器)
2. 在所有现代浏览器下,鼠标点击链接元素 <a> 的时候是不会出现焦点轮廓的,但是使用键盘访问的时候会出现。点击链接元素时只会触发:focus伪类,而键盘访问此链接元素时不仅会触发:focus伪类,还会触发:focus-visible伪类。

3. 这就是:focus-visible伪类的作用,可以用来区分用户的操作是鼠标点击,还是键盘访问。不过,这种判断并不完全准确,因为:focus-visible伪类匹配与否是浏览器自行决定的,没有特定的规范。目前看来,浏览器会出现默认轮廓的场景都会匹配:focus-visible伪类。

在 Chrome90 版本之前的浏览器下,有些元素的焦点轮廓就算是在点击操作下也会出现的。包括下面这些场景:
● 设置了背景的 <button> 按钮;
● HTML5 中的 <summary> 元素;
● 设置了 HTML tabindex 属性的元素。
这其实是我们不希望看到的,因为点击鼠标是目标明确的主动操作,此时出现轮廓是没有必要的,反而让操作界面变得难看了。
但是,又不能简单地通过设置 outline:none 来处理,因为这样会使使用键盘访问时应当出现的焦点轮廓被隐藏,从而带来严重的无障碍访问问题。
在这种场景下,:focus-visible伪类可谓天降神兵,只需要一条短短的CSS规则就可以兼顾视觉表现和无障碍访问:


:focus:not(:focus-visible) {

outline: 0;
}​​



此时,无论对于 <summary> 元素还是设置了 tabindex 属性的元素,在点击的时候都不会出现轮廓,同时,键盘访问时的 outline 轮廓依然保留,两全其美。
当然,由于现在的Chrome浏览器和Safari浏览器默认点击 <button> 按钮或者 <summary> 元素时都不会出现轮廓,因此,:focus-visible伪类的作用就没有以前那么明显了。准确地说是浏览器自己优化了之前的一些无障碍访问策略,使得无须使用:focus-visible伪类手动进行相关的优化了。

:focus-visible 伪类目前的作用就变成了用来区分用户行为是鼠标行为还是键盘行为。
https://memo.cosine.ren/m/336
#书摘 #css #前端
《CSS 选择器世界》7.4 非常实用的整体焦点伪类 :focus-within
整体焦点伪类 :focus-within 非常实用,且兼容性不错,目前已经可以在实际项目中使用,包括移动端项目和无须兼容IE浏览器的桌面端项目。
1. :focus-within 伪类和 :focus 伪类的区别
ChS :focus-within 伪类和 :focus 伪类有很多相似之处,那就是伪类样式的匹配离不开元素聚焦行为的触发。区别在于,:focus 伪类样式只有在当前元素处于聚焦状态的时候才匹配,而 :focus-within 伪类样式在当前元素或者当前元素的任意子元素处于聚焦状态的时候均匹配

子元素聚焦可以使父元素的样式发生变化,这是CSS选择器世界中很了不起的革新,因为 :focus-within 伪类的行为本质上是一种父选择器行为,子元素的状态会影响父元素的样式。由于这种父选择器行为需要借助用户的行为触发,属于 “后渲染”,不会与现有的渲染机制冲突,自然也不会带来性能问题,因此浏览器在规范出现后不久就快速支持了。

2. :focus-within 伪类实现无障碍访问的下拉列表
:focus-within伪类非常实用,一方面它可以用在表单控件元素上(无论是样式自定义还是交互布局),例如输入框聚焦时高亮显示前面的描述文字,我们可以不把描述文字放在输入框的后面(具体见5.4.2节中的示例),按正常的DOM顺序即可:


<div class="cs-normal">
<label class="cs-label">用户名:</label>
<input class="cs-input">
</div>
.cs-normal:focus-within .cs-label {
color: darkblue;
text-shadow: 0 0 1px;
}​​


读者可以手动输入 https://demo.cssworld.cn/selector2/7/4-1.php 体验与学习。

另一方面,它可以用于实现完全无障碍访问的下拉列表,即使下拉列表中有其他链接或按钮也能正常访问。例如,要实现一个类似图7-10所示的下拉列表效果。
HTML结构如下:
:focus 伪类的区别
ChS :focus-within 伪类和 :focus 伪类有很多相似之处,那就是伪类样式的匹配离不开元素聚焦行为的触发。区别在于,:focus 伪类样式只有在当前元素处于聚焦状态的时候才匹配,而 :focus-within 伪类样式在当前元素或者当前元素的任意子元素处于聚焦状态的时候均匹配

子元素聚焦可以使父元素的样式发生变化,这是CSS选择器世界中很了不起的革新,因为 :focus-within 伪类的行为本质上是一种父选择器行为,子元素的状态会影响父元素的样式。由于这种父选择器行为需要借助用户的
我们在父元素 .cs-details 上使用 :focus-within 伪类来控制下拉列表的显示和隐藏,如下:


.cs-datalist {

display: none;

position: absolute;

border: 1px solid #ddd;

background-color: #fff;

}
/* 下拉列表展开 */

.cs-details:focus-within .cs-datalist {

display: block;
}​​


本例中共有5个 <a> 元素,其中一个用于触发下拉显示的 .cs-summary 元素,另外4个在下拉列表中。无论点击这5个 <a> 元素中的哪一个,都会触发父元素 .cs-details 设置的 :focus-within 伪类样式,因此可以让下拉列表一直保持显示状态;点击页面任意空白处,下拉列表自动隐藏,效果非常理想。
读者可以手动输入 https://demo.cssworld.cn/selector2/7/4-2.php 体验与学习。

https://memo.cosine.ren/m/334
#书摘 #css #前端
《CSS 选择器世界》7.3 聚焦行为伪类:focus与用户体验
:focus是一个从IE8浏览器开始支持的伪类,它可以匹配当前处于聚焦状态的元素。

1. 与:active伪类不同,:focus伪类默认只能匹配特定的元素,包括:
● 非disabled状态的表单元素,如 <input> 输入框、 <select> 下拉框、`<button>` 按钮等;
● 包含href属性的 <a> 元素;
<area> 元素,不过可以生效的CSS属性有限;
● HTML5中的 <summary> 元素。

除上述特定元素之外,其他HTML元素应用:focus伪类是无效的。
如何让普通元素也能响应:focus伪类呢?设置了HTML contenteditable 属性的普通元素可以应用:focus伪类,例如:


<div contenteditable="true></div>
<div contenteditable="plaintext-only"></div>​​



因为此时 <div> 元素是一个类似 <textarea> 元素的输入框。
设置了HTML tabindex属性的普通元素也可以应用:focus伪类,例如,下面3种写法都是可以的:


<div tabindex="-1">内容</div>
<div tabindex="0">内容</div>
<div tabindex="1">内容</div>​​



如果期望 <div> 元素可以被Tab键索引,且被点击的时候可以触发:focus伪类样式,则使用tabindex="0";如果不期望 <div> 元素可以被Tab键索引,且只在它被点击的时候触发:focus伪类样式,则使用tabindex="-1"。对于普通元素,不存在使用自然数作为tabindex属性值的场景。

2. 模拟表单元素的键盘可访问性 [type="radio"]`、 `[type="checkbox"]`、`[type="range"] 类型的`<input>`元素的UI往往不符合网站的设计风格,需要自定义样式,常规实现一般都没问题,关键是很多开发人员会忘了键盘的无障碍访问。
[type="checkbox"] 复选框为例,我们需要隐藏原生的`[type="checkbox"]` 复选框,使用关联的 <label> 元素自定义的复选框样式(如果不需要兼容IE和IE Edge浏览器,则无须 <label> 元素模拟)。

● 对于原生复选框元素的隐藏,要么设置透明度opacity:0,要么剪裁,千万不要使用visibility:hidden或者display:none进行隐藏,虽然IE9及以上版本的浏览器的功能是正常的,但是这两种隐藏是无法被键盘聚焦,键盘不可访问。
● 不要忘记在原生复选框聚焦的时候高亮显示自定义的输入框元素,可以是边框高亮,或者外发光,通常都使用相邻兄弟选择符(+)实现,特殊情况下也可以使用兄弟选择符(~),如高亮多个元素时。

市面上有不少UI框架,如何区分品质?很简单,使用Tab键索引页面元素,如果输入框有高亮显示,则这个UI框架比较专业,如果什么反应都没有,建议换一种UI框架。

https://memo.cosine.ren/m/334
#Web

👻 用新的 Emoji 来聊天吧 —— Emoji Kitchen

👉 Google 此前在自家的 Android 键盘中加入名为 Emoji Kitchen 的功能,可以让两个不同的 emoji 表情组合成一个新的表情。

💻 如今这一项功能已被下放到网页版,在 Google 搜索框中键入 “Emoji Kitchen” 就可以直接使用网页版,生成结果还是比较有趣的和细致的,这个结果并不是生硬的进行拼凑,而是考虑到了很多场景(例如高楼大厦的黑夜+钻石,得到的是大厦中升起一颗钻石,而大厦的黑夜+蝎子,得到的就是一个哥斯拉级别的蝎子在拆楼,而不是楼中升起一只蝎子)

🌐 之前还在 Figma 上看到也有人只做了类似 Emoji Kitchen 的插件 —— Emoji Kitchen Browser,可以实现 emoji 表情拼接,从而得到一个矢量图的效果,但是我个人感觉这个生成的效果并没有 Google 这个版本的更注重 A+B 两个表情生成 C 的场景合理性。
#书摘 #css #前端
《CSS 选择器世界》使用 :active 伪类实现点击反馈
:active 伪类可以用于设置元素激活状态的样式,可以通过点击鼠标主键或者用手指或者触控笔点击触摸屏触发激活状态。具体表现如下,按下触发:active伪类样式,抬起取消:active伪类样式的应用。:active伪类支持任意HTML元素,例如 <div>`、`<span> 等非控件元素,甚至是自定义元素。
然而,落地实现时:active伪类并没有理论上那么完美,表现为以下3点。
1. IE浏览器下:active样式的应用是无法冒泡的

img:active {
outline: 30px solid #ccc;
}
p:active {
background-color: teal;
}

<p><img src="1.jpg"></p>​​


此时,点击 <img> 元素的时候,在IE浏览器下,`<p>` 元素是不会触发:active伪类样式的,实际上祖先元素的:active样式也应当被应用;在Chrome和Firefox等浏览器下,其表现符合预期。

2. IE浏览器下,`<html>`、`<body>` 元素应用:active伪类设置背景色后,背景色是无法还原的。
具体来说,鼠标键按下时确实应用了:active设置的背景色,但是抬起后背景色没有还原,而且此时无论怎么点击鼠标,背景色都无法还原。这是一个很奇怪的bug,普通元素不会有此问题,这个问题甚至比在IE7浏览器下链接元素必须失焦才能取消:active样式还要糟糕。

3. 键盘访问无法触发:active伪类。例如,`<a>` 元素在focus状态下按下Enter键的事件行为与点击一致,但是,不会触发:active伪类。

4. 最后,:active伪类的主要作用是反馈点击交互,让用户知道他的点击行为已经成功触发,这对于按钮和链接元素是必不可少的,否则会有体验问题。由于:active伪类作用在按下的那一段时间,因此不适合用来实现复杂交互。

https://memo.cosine.ren/m/330
#书摘 #css #前端
《CSS 选择器世界》:hover伪类与悬停交互开发
:hover 是各大浏览器最早支持的伪类之一,最早只能用在`<a>`元素上,其设计的初衷是改变链接元素的颜色:


a { color: blue; }
a:hover { color: darkblue; }​​


由于 :hover 实现浮层元素的显示与隐藏效果非常方便,于是当时出现了很怪异的现象:`<a>`元素满天飞,甚至`<a>`元素里面嵌套`<div>`元素以实现悬停交互效果,完全不符合HTML元素原本语义。例如:


<a href="javascript:void(0)">

菜单

<div class="list">列表</div>
<a>

list {
display: none;
position:absolute;
}

a:hover .list {
display: block;
}​​


CSS所有新特性的出现都源自用户需求和开发需求。同样,当意识到仅`<a>`元素支持:hover伪类非常影响开发效率之后,浏览器迅速跟进升级。目前,所有主流浏览器中,:hover伪类已经可以在任意HTML元素中使用了,其中包括自定义元素:


x-element:hover {}​​


需要注意的有如下几点,
- 如果是移动端开发,强烈建议不要使用:hover伪类实现交互效果,因为对于手机和iPad这类移动设备,常见的交互操作都通过触屏,而不是鼠标。虽然在这些设备上,:hover也能触发,但消失并不敏捷,体验反而不佳。
- 对于带有交互的行为,一定不能只使用:hover伪类,而需要额外的处理,可以通过增加:focus伪类来优化体验
- 但对于本身就带有链接或按钮的浮层元素,使用:focus伪类是不可行的,因为虽然可以触发浮层的显示,但是浮层内部的链接和按钮无法被点击,这是由于通过键盘切换焦点元素时浮层会因失焦而迅速隐藏。不过这是有其他解决方法的,那就是使用整体焦点伪类 :focus-within

https://memo.cosine.ren/m/329
#书摘 #css #前端
《CSS 选择器世界》 忽略属性值大小写的正则匹配运算符
正则匹配运算符是属性选择器中新增的运算符,它可以忽略属性值的大小写,使用字符i或者I作为运算符值,但约定俗成都以小写字母i作为运算符。语法如下:

[attr~="val" i] {}
[attr*="val" i] {}​​



作为对比示意,假设有选择器`[attr*="val"]`,则:

<!-- 不匹配 -->

<div attr="VAL"></div>

<!-- 匹配 -->
<div attr="Text val"></div>
<!-- 不匹配 -->
<div attr="Value"></div>

<!-- 不匹配 -->
<div attr="Val-ue"></div>​​



如果选择器是 `[attr*="val" i]`,则:

<!-- 匹配 -->

<div attr="VAL"></div>

<!-- 匹配 -->

<div attr="Text val"></div>
<!-- 匹配 -->
<div attr="Value"></div>
<!-- 匹配 -->
<div attr="Val-ue"></div>​​



可以看到,属性值的大小写被忽略了。

https://memo.cosine.ren/m/328
#书摘 #css #前端
《CSS 选择器世界》CSS属性选择器搜索过滤技术
我们可以借助属性选择器来辅助实现搜索过滤效果,如搜索通讯录、城市列表,这样做性能高,代码少。
HTML结构如下:

<input type="search" placeholder="输入城市名称或拼音" />
<ul>
<li data-search="重庆市chongqing">重庆市</li>
<li data-search="哈尔滨市haerbin">哈尔滨市</li>

<li data-search="长春市changchun">长春市</li>

...
</ul>​​


此时,当我们在输入框中输入内容的时候,只要根据输入内容动态创建如下CSS代码就可以实现搜索匹配效果了,无须自己写代码进行匹配验证。

var eleStyle = document.createElement('style');
document.head.appendChild(eleStyle);
// 文本框输入

input.addEventListener("input", function() {

var value = this.value.trim();

eleStyle.innerHTML = value ? '[data-search]:not([data-search*="'+ value +'"])
{ display: none; }' : '';

});​​


https://memo.cosine.ren/m/327
#书摘 #css #前端
《CSS 选择器世界》6.3 属性值正则匹配选择器
属性值正则匹配选择器包括下面3种:

[attr^="val"]

[attr$="val"]

[attr*="val"]​​


这3种属性选择器就完全是字符匹配了,而非单词匹配。其中,尖角符号`^`、美元符号`$`以及星号`*`都是正则表达式中的特殊标识符,分别表示**前匹配、后匹配和任意匹配**。

1. [attr^="val"]
[attr^="val"]
表示**匹配attr属性值以字符val开头的元素**。例如:

<!-- 匹配 -->
<div attr="val"></div>

<!-- 不匹配 -->

<div attr="text val"></div>
<!-- 匹配 -->

<div attr="value"></div>

<!-- 匹配 -->

<div attr="val-ue"></div>​​


- 这种选择器可以匹配中文,如果匹配的中文不包含特殊字符(如空格等),则引用中文的引号是可以省略的,例如:

[title^=我] {}​​


- 理论上可以匹配空格,但由于IE浏览器会自动移除属性值首尾的空格,因此会有兼容性问题
例如,下面的样式可以对HTML格式进行验证:

/*高亮类属性值包含多余空格的元素*/

[class^=" "] {
outline: 1px solid red;
}​​



实际开发中,开头正则匹配属性选择器用得比较多的地方是**判断`<a>`元素的链接地址类型**,也可以用来显示对应的小图标,例如:

/* 链接地址 */

[href^="http"],
[href^="ftp"],
[href^="//"] {

background: url(./icon-link.svg) no-repeat left;
}
/* 网页内锚链 */

[href^="#"] {

background: url(./icon-anchor.svg) no-repeat left;

}


/* 手机和邮箱 */


[href^="tel:"] {


background: url(./icon-tel.svg) no-repeat left;


}


[href^="mailto:"] {


background: url(./icon-email.svg) no-repeat left;


}​​



2. [attr$="val"]
[attr$="val"]
表示**匹配attr属性值以字符val结尾的元素**。例如:

<!-- 匹配 -->
<div attr="val"></div>
<!-- 匹配 -->
<div attr="text val"></div>
<!-- 不匹配 -->

<div attr="value"></div>
<!-- 不匹配 -->
<div attr="val-ue"></div>​​



该选择器的使用细节和 [attr^="val"] 的一致,这里不再赘述。
**在实际开发中,结尾正则匹配属性选择器用得比较多的地方是判断`<a>`元素的链接的文件类型**,也可以用来显示对应的小图标。例如:

/* 指向PDF文件 */
[href$=".pdf"] {

background: url(./icon-pdf.svg) no-repeat left;
}

/* 下载zip压缩文件 */

[href$=".zip"] {

background: url(./icon-zip.svg) no-repeat left;
}
/* 图片链接 */
[href$=".png"],
[href$=".gif"],
[href$=".jpg"],
[href$=".jpeg"],
[href$=".webp"] {

background: url(./icon-image.svg) no-repeat left;
}​​



3. [attr*="val"]
[attr*="val"]
表示**匹配attr属性值包含字符val的元素**。例如:

<!-- 匹配 -->
<div attr="val"></div>

<!-- 匹配 -->

<div attr="text val"></div>

<!-- 匹配 -->
<div attr="value"></div>

<!-- 匹配 -->
<div attr="val-ue"></div>​​



它也可以用来匹配链接元素是否是外网地址,例如:

a[href*="//""]:not([href*="example.com"]) {}​​


https://memo.cosine.ren/m/326
#书摘 #css #前端
《CSS 选择器世界》属性值直接匹配选择器
属性值直接匹配选择器包括下面4种:


[attr]
[attr="val"]
[attr~="val"]

[attr|="val"]​​



这4种选择器的兼容性不错,IE8及以上版本的浏览器完全支持,IE7浏览器也支持,不过不完全,在极个别场景中有瑕疵。

1. [attr]
[attr]
表示只要包含指定的属性就匹配,尤其适用于一些HTML布尔属性,这些布尔属性只要有属性值,无论值的内容是什么,就认为这些属性值为 true。例如,下面所有的输入框的写法都是禁用的:


<input disabled>

<input disabled="">
<input disabled="disabled">

<input disabled="true">
<input disabled="false">​​



此时,如果想用属性选择器判断输入框是否禁用,可以直接使用下面的选择器,无须关心具体的属性值究竟是什么:


[disabled] {}​​



2. [attr="val"]
[attr="val"]
属性值完全匹配选择器,例如:

[type="radio"] {}

[type="checkbox"] {}​​



(1) 不区分单引号和双引号,单引号和双引号都是合法的引号:

[type="radio"] {}



(2) 引号是可以省略的。例如:

[type=radio] {}

[type=checkbox] {}​​


如果属性值包含空格,则需要转义

3. [attr~="val"]
[attr~="val"]
属性值单词完全匹配选择器,专门用来匹配属性中的单词,其中,`~=` 用来连接属性和属性值。
- 有些属性值(如class属性、rel属性或者一些自定义属性)包含多个关键词,这时可以使用空格分隔这些关键词,例如:

<a href rel="nofollow noopener">链接</a>​​



此时就可以借助该选择器实现匹配,例如:

[rel~="noopener"] {}
[rel~="nofollow"] {}​​


匹配的属性值不能是空字符串。

- 如果匹配的属性值只是部分字符串,那么也是无效的。例如,有选择器 `[attr~="val"]`,则下面两段HTML都不匹配:

<!-- 不匹配 -->

<div attr="value"></div>
<!-- 不匹配 -->
<div attr="val-ue"></div>​​




但是,如果字符串前后有一个或者连续多个空格分隔,则可以匹配:

<!-- 匹配 -->
<div attr=" val "></div>

<!-- 匹配 -->

<div attr="val ue"></div>​​



4. [attr|="val"]
[attr|="val"]
属性值起始片段完全匹配选择器,表示对于具有attr属性的元素,**其值要么正好是val,要么以val加短横线-(U+002D)开头**,|=用于连接需要匹配的属性和属性内容。

<!-- 匹配 -->
<div attr="val"></div>
<!-- 匹配 -->
<div attr="val-ue"></div>
<!-- 匹配 -->

<div attr="val-ue bar"></div>

<!-- 不匹配 -->

<div attr="value"></div>
<!-- 不匹配 -->
<div attr="val bar"></div>
<!-- 不匹配 -->

<div attr="bar val-ue"></div>​​


可以看到,这个选择器严格遵循属性值起始片段匹配的规则。

https://memo.cosine.ren/m/325
#优质博文 #前端 #组件库 #tailwind
2023 年前端 UI 组件库概述,百花齐放!
感觉不少 tailwind 组件库冒出来了mark 一下这个组件库
1. ShadCN/UI,跟我思想很接近。它提供了一种不同于其他库的开发方法。不需要通过npm安装组件或整个库,而是将代码直接复制粘贴到自己的代码库中。这样做的目的是让开发者完全拥有组件,并将设计和实现分离。它使用 Tailwind 进行构建,并提供了一个CLI工具,可以生成组件代码并调整tailwind.config.js文件。
2. NextUI:不要与 React 元框架 Next.js 混淆,这个库是使用 Tailwind CSS 构建的。它声称学习曲线很小。主题由tailwind.config.js文件处理,具备良好的可访问性,并且所有组件都支持暗黑主题。只需使用不同的 Tailwind 类名即可覆盖样式。
#书摘 #css #前端
《CSS 选择器世界》第6章 被低估的属性选择器
前几章讲述了几个常用的、必须掌握的选择器,以及可以将选择器威力放大数倍的选择符,对新手而言,只要掌握前面这几章的内容,就能实现完全静态的网页布局效果,足以在生产环境中进行开发,再掌握一些基础且常用的CSS属性,就可以算是前端入门了。

但CSS这门语言入门简单,精深却不容易。以本书为例,从本章开始的所有内容都可以看作CSS选择器功能的增强,占据的篇幅达到60%~70%之大,但是覆盖的只是实际开发场景中的30%。

所有设计出的CSS选择器都是有针对性和应对场景的,其中可能有些场景不太常见,但是随着开发的不断深入,早晚会在实践中遇到,此时,如果能够使用对应的CSS选择器,则开发效率和实现效果都会很惊人。

举个例子,我们进行Web Components组件化开发的时候,要想知道组件是否已经被定义,如果你没有学习后面的内容,就要在JavaScript代码中埋一些标记量给CSS使用,其实,是有专门的名为:defined的伪类匹配这种场景的。

从本章开始,对内容的掌握程度决定了读者是普通的还是资深的CSS开发人员。

先介绍一个被大家低估的选择器——属性值匹配选择器。我们平常提到的属性选择器指的是[type="radio"]这类选择器,实际上,属性选择器是简称,其全称为“属性值匹配选择器”。 在正式文档中,类选择器和ID选择器都属于属性选择器,因为本质上类选择器是HTML元素中class的属性值,ID选择器是HTML元素中id的属性值。

(睡觉!下次再读)
#书摘 #css #前端
《CSS 选择器世界》第5章 精通CSS选择符
5. 快速了解列选择符——双管道(||)
列选择符是规范中刚出现不久的新选择符
Table布局和Grid布局中都有列的概念。有时候我们希望控制整列的样式,有两种方法:一种是借助 :nth-col() 或者 :nth-last-col() 伪类,不过目前浏览器尚未支持这两个伪类;另一种是借助原生 Table 布局中的 <colgroup> <col> 元素实现,这个方法的兼容性非常好。
很多时候,我们需要G单元格也有背景色,即只要包含目标列,就认为是目标对象。为了应对这种需求,列选择符应运而生。
列选择符写作双管道(||),但是在CSS中不是“或”的意思,用“属于”来解释更为恰当。

<table border="1" width="600">
<colgroup>
<col>
<col span="2" class="ancestor">
<col span="2" class="brother">
</colgroup>
<tr>
<td></td>
<th scope="col">后代选择符</th>
<th scope="col">子选择符</th>
<th scope="col">相邻兄弟选择符</th>
<th scope="col">随后兄弟选择符</th>
</tr>
<tr>
<th scope="row">示例</th>
<td>.foo .bar {}</td>
<td>.foo > .bar {}</td>
<td>.foo + .bar {}</td>
<td>.foo ~ .bar {}</td>
</tr>
</table>​​




通过如下CSS选择器,可以使G单元格也有背景色:


col.selected || td {
background-color: skyblue;
}​​




col.selected || td
的含义就是,选择所有属于col.selected的 <td> 元素,哪怕这个 <td> 元素横跨多个列。
#书摘 #css #前端
《CSS 选择器世界》第5章 精通CSS选择符
2. 子选择符——箭头(>)
子选择符也是非常常用、重要的一个选择符,IE7浏览器开始支持,它和后代选择符有类似于“远房亲戚”的关系。子选择符只匹配第一代子元素,而后代选择符会匹配所有子元素。
子选择符是一把双刃剑,它通过限定关系使结构更加稳固,但同时失去了弹性和变化,需要审慎使用。
3. 相邻兄弟选择符——加号(+)
相邻兄弟选择符也是非常实用的选择符,它被IE7及以上版本的浏览器支持。它
可以用于选择相邻的兄弟元素,但只能选择后面一个兄弟元素。相邻兄弟选择符会忽略文本节点和注释节点,只认元素节点。
相邻兄弟选择符最有价值的应用还是配合诸多伪类以低成本实现很多实用的交互效果,它是众多高级选择器技术的核心。
- 场景1:用来实现类似:first-child伪类的效果。例如,我们希望除第一个列表以外的其他列表都有margin-top属性值,首先可以想到的就是:first-child,下面介绍另一种方法,那就是借助相邻兄弟选择符,如下:

.cs-li + .cs-li { margin-top: 1em; }​​



由于相邻兄弟选择符只能匹配后一个元素,因此第一个元素不会被匹配,于是自然而然实现了非首列表元素的匹配。
实际上,此方法的适用范围比:first-child更广一些,例如,当容器的第一个子元素并非.cs-li的时候,相邻兄弟选择符这个方法依然有效,而:first-child此时却无效了,因为没有任何.cs-li元素是第一个子元素了,也就无法匹配:first-child。

- 场景2:当我们聚焦输入框的时候,如果希望显示后面的提示文字,可以借助相邻兄弟选择符轻松实现 —— 把提示文字预先埋在输入框的后面,当触发focus行为时,提示文字即可显示。HTML和CSS代码分别如下:


用户名:<input><span class="cs-tips">不超过10个字符</span>

.cs-tips {
color: gray;

margin-left: 15px;

position: absolute;

visibility: hidden;
}
:focus + .cs-tips {

visibility: visible;
}​​



4. 随后兄弟选择符——波浪线(~)
随后兄弟选择符和相邻兄弟选择符的兼容性一致,都是从IE7浏览器开始支持的,可以放心使用。两者的实用性和重要程度也是类似的,它们的关系较近。
相邻兄弟选择符只会匹配它后面的第一个兄弟元素,而随后兄弟选择符会匹配它后面的所有兄弟元素。至于其他细节,两者是类似的,例如,随后兄弟选择符也会忽略文本节点和注释节点。
在CSS选择器世界中,并不存在前面兄弟选择符,但是我们在实际开发的时候,确实存在很多场景需要控制前面的兄弟元素,此时又该怎么办呢?

<h4 class="cs-h">标题</h4>
<p class="cs-li">列表内容</p>
.cs-h:has( + .cs-li) {
color: deepskyblue;
}​​



此时标题元素就是深天蓝色,虽然伪类的参数是相邻兄弟选择符,但是匹配的是前面的元素,详见9.4节。
#书摘 #css #前端
《CSS 选择器世界》第5章 精通CSS选择符
CSS选择符可以让选择器有更丰富的层级关系,使我们从容应对各种相对复杂的样式布局。
CSS选择符目前有下面这几个:后代选择符——空格( )、子选择符——箭头(>)、相邻兄弟选择符——加号(+)、随后兄弟选择符——波浪线(~)和列选择符——双管道(||)。其中对于前4个选择符,浏览器开始支持的时间较早,非常实用,是本章的重点。最后的列选择符算是“新贵”,与Table等布局密切相关,但目前浏览器的兼容性还不足以使它被实际应用,因此只简单介绍。
1. 后代选择符——空格( )
后代选择符是非常常用的选择符,随手抓取一个线上的CSS文件就可以看到这个选择符,它从IE6时代就开始被支持了。
后代选择符以空格作为分隔符,从前往后的选择器,只要匹配DOM由外而内的层级关系,就会匹配最后一个选择器对应的元素。

> 早些年我拿这道题做测试,结果全军覆没,无人答对,大家都认为1和2的颜色分别为深蓝色和浅蓝色。实际上正确答案是,1和2全部都是深蓝色

<div class="lightblue">
<div class="darkblue">
<p>1. 颜色是?</p>
</div>
</div>
<div class="darkblue">
<div class="lightblue">
<p>2. 颜色是?</p>
</div>
</div>

.lightblue p {
color: lightblue;
}
.darkblue p {
color: darkblue;
}​​


当包含后代选择符的时候,整个选择器的优先级与祖先元素的DOM层级没有任何关系,这时要看落地元素的优先级。在本例中,落地元素就是最后的<p>元素。两个<p>元素彼此分离,非嵌套,因此DOM层级平行,没有先后之分。再看选择器的优先级,.lightblue p和.darkblue p出现了一个类选择器(数值10)和一个标签选择器(数值1),选择器优先级数值一样。此时就要看它们在CSS文件中的位置,遵循“后来居上”的规则,由于.darkblue p位置靠后,因此<p>都是按照color:darkblue进行颜色渲染的,于是,最终1和2的文字颜色都是深蓝色。
Back to Top