虽然如今 Css Module 与 Css-in-js 更流行,但使用它们会致使过度依赖 滥用 class 作惟必定位,违背了 Css 选择器的初衷。css
本期精读的文章是:attribute-selectors-splicing-html-dna-css,带你从新理解强大的 Css 选择器。html
Css Module 与 Css-in-js 大部分场景使用 className 做为选择器,那么本文以选择器为重点,看看选择器有哪些实用的用法。前端
若是你想选择包含 title
属性的 div
:git
div[title]
选择包含 title
属性的子元素,只须要加个空格:github
div [title]
选择 title
内容是 dna
的元素:npm
div[title="dna"]
选择 title
属性包含 dna
单词的元素:安全
注意 dna 须要是单词,也就是用空格分割,好比 “my beautiful dna” 或 “mutating dna is fun!”
div[title~="dna"]
和正则相似,选择 title
属性中,以 dna
结尾的元素:架构
div[title$="dna"]
以 dna
开头:dom
div[title^="dna"]
若是但愿选择 dna
或 dna-zh
,但不但愿匹配 dnaer
,能够:async
这种场景通常用在国际化,好比 en en-us 就能够用
|="en"
div[title|="dna"]
只要包含 dna
这三个字符就选中:
div[title*="dna"]
真的很像正则,你能够用 i
标识匹配时大小写不敏感:
div[title*="dna" i]
若是你想找到一个 a
标签,拥有 title
属性而且 className 以 genes
结尾,能够这样:
a[title][class$="genes"]
能够用 attr
标识符拿到当前选择器选中元素的属性,好比当 hover
状态时,在文字尾部显示其 title
属性:
.joke:hover:after { content: "Answer:" attr(title); display: block; }
本文还介绍了一些实用技巧,好比
根据输入框类型设置样式
input[type="email"] { color: papayawhip; } input[type="tel"] { color: thistle; }
改变下载标签的 icon
a[download][href$="pdf"]:after { content: url(pdf-icon.svg); }
固然也能够选中一些老代码进行样式重写,好比:
<div bgcolor="#000000" color="#FFFFFF">Old, holey genes</div>
div[bgcolor="#000000"] { /*override*/ background-color: #222222 !important; }
不过这种用法要谨慎,写的越多越难以维护。
结合一些新标签功能
好比 details
标签是 html 原生的手风琴折叠组件:
<details> <summary>List of Genes</summary> Roddenberry Hackman </details>
咱们可使用属性选择器,定义其打开时的样式:
details[open] { background-color: hotpink; }
为没有 async
标记的 script
标签着色,算是友情提示哪儿有错误:
script[src]:not([async]) { display: block; width: 100%; height: 1em; background-color: red; } script:after { content: attr(src); }
为 JS 事件着色,好比触发的鼠标事件能够做为选择器:
[OnMouseOver] { color: burlywood; } [OnMouseOver]:after { content: "JS: " attr(OnMouseOver); }
选中隐藏元素:
[hidden], [type="hidden"] { display: block; }
还有更多就不一一列举了,感兴趣的读者能够跳转到原文继续阅读。大部份内容其实都写在了 w3school 选择器参考手册,只是结合一篇文章来读,能够理解得更深入,同时文章里确实有一些新鲜的选择器,好比 JS 事件选择器,HTML5 属性标签选择器等等。
这篇文章确实说明了 Css 选择器的强大性,但回到 css module 或者 css-in-js 的工程代码里,咱们每每难以作太多的实践,有以下几个缘由:
业务开发中,大量需求涌入,也许过了一周,DOM 结构就已经面目全非了,并且就算是一个普通的圣杯布局,可能老版本用 Table 布局,后面进来一个年轻小伙子直接用 div + flex 重构了,你会担忧以前写的 table 选择器在某一天所有失效。
也许今天的 div 选择器,明天由于语义化改造就换成了 article 标签。
最大缘由是 一种视觉界面对应的实现方式太多,不只标签能够各异,css 属性还有 table、block、flex、grid 可选,同时 grid 属性还会致使视觉结构与 DOM 结构不彻底对应。
若是你今天用 css 选择器作了一套彻底贴合如今 DOM 结构的 css 文件,这个 css 文件也许是后面 dom 结构改动的噩梦。
咱们排除标签,仅对属性作全局覆盖,的确能够部分绕开 DOM 结构的限制,可是这样的全局样式覆盖,不一样的人有不一样见解。
小明的团队很是懂得 css 运用,他们天天都会花一个小时讨论项目的 css 架构,并对通用需求样式作了抽象,而且每一个人都很承认这个方案,在他们的团队,一个很是酷炫的按钮与动画效果,经过 <button animate />
就能够完成,页面间交互很是流畅,用户体验统一,前端代码也很是简洁和优雅。
小白的团队水平良莠不齐,有人永远只使用 table 布局,有人却总想将一些试验阶段 css 属性用在生产环境,小白本身抽象了一个全局样式 css 文件,可团队没什么时间沟通,甚至有人私下也注入了很多全局 css 样式,总有人抱怨本身的样式被全局覆盖了,最后小白甚至不得不在本身页面入口处写上 *: unset
清空各类奇怪的全局样式干扰,他想清空那该死的全局 css 样式文件,但他知道这样作带来的是更大的灾难。
能够看到,并非每一个团队都适合作全局样式覆盖。
为何一个项目安装了几百个 npm 三方包,却依然能够正常运行?由于好的三方包都是遵照模块化的,同时也不产生反作用,这样被使用时的效果就能够被预期,试想一下几百个 npm 包里同时定义了不一样规范的全局 css 覆盖,你的项目会成为何样。
固然 js 与 css 是不适合放在一块儿比较的,css 大可能是业务级别的,也就是能写 css 只有作业务的你,第三方包通常是不会提供 css 定义干扰你的项目的。
然而大部分 UI 组件库是自带样式的,他们有本身的设计哲学,但为何如今你会反感,而当初使用 Bootstrap 不会?
使用 Bootstrap 的时代,Bootstrap 通常是做为项目第一个依赖安装的,咱们明确知道它会注入全局样式。咱们会泡在他的官方文档目录,一条条理解他作的全局样式规则,他提供的各类 class。
然而如今是一个 Css-in-js 的时代,或者至少是 css-in-npm 的时代,什么都用 npm 装,什么都是模块化的,不少时候咱们用一个 UI 组件仅仅是为了在某一处地方使用,而不想接受他带来的全局样式污染,视觉设计哲学,更不想看他的 css 文档。因此好的组件库每每 css 使用的很收敛,尽可能不要对用户项目环境形成影响。
若是你项目的样式已经被不得不安装的第三方包全局覆盖得面目全非,每一次对全局样式修改都如履薄冰,可能你会比较反感 css 选择器,你会推崇更安全的 css modules,或甚至是 css-in-js,让每一个组件的 className 都惟一,作到标签粒度的隔离。
笔者认为,在一个肯定的环境中,好比一个组件,一个独立负责的模块,是比较适合用 css 选择器的,这样可让样式代码更易读,DOM 结构更清爽。但请必定注意做用域,若是不是你们一块儿达成的共识,最好不要放到全局样式中。
就算项目的风格很是明确,a
标签必定要用红色,在把这条规则放到全局样式以前,请思考一下,这样会不会破坏了某个用 a
标签模拟按钮的组件库的样式?
css 属性选择器的强大功能,须要有良好的项目管理作支撑,或者经过技术手段好比 shadow dom 作支撑。不过 shadow dom 的支持程度 如今仍然很低,因此使用编译工具作的隔离,在某种程度上模拟了 Css 选择器,承担了 Css 选择器 + shadow dom 的功能。
一切样式都用 className 控制,也许是 shadow dom 出来前的一种妥协方案,这篇文章更可能是在描述 Css 选择器设计之美,但须要咱们理性去使用。
讨论地址是: 精读《使用 CSS 属性选择器》 · Issue #113 · dt-fe/weekly
若是你想参与讨论,请点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。