前端二向箔07-CSS选择器

520 阅读8分钟

07 CSS选择器

上一篇

前端二向箔06-CSS语法


CSS选择器是CSS的主体内容. 选择器字如其名, 通过一些标识特征, 选中DOM中的元素( 伪元素选择器则不然, 后文会提及 ). 上一篇文章初略地列举了选择器地类型和优先级. 本文会详细整理选择器的相关核心知识.

选择器类型

更具三大优先级进行划分为特点的, 有四种. 结构特点划分, 有另外三种. 此外还有内联和!important两个属性.

特异性为我个人定义的选择器的独立优先级, 姑且分为∞,0, 1, 2, 3递减.

三大优先级

  1. id选择器

    id选择器有全局特异性, 唯一标识了网页中的一个元素; 所以在开发中, 并不是非常常用, 特别是对于需要后续覆盖和复用规则时, 会遇到困难. 如果DOM结构改变, 使用id选择器可能会是你的噩梦.

    通过#id-name进行调用, 特异性为1;

  2. class选择器和属性选择器

    • class选择器是最常用的选择器, 而且对CSS本意描述也比较符合——某个元素的样式类型. 而且可以方便开发中进行覆盖, 还能重用.

      通过.class-name调用, 特异性为2;

    • 属性选择器一定程度上可以替代class和id, 既可以通过自定义data属性来进行筛选, 也可以进行匹配查询; 更像是一个简化正则匹配的选择器. 特异性为2;

      使用:

      [data]--选定拥有data属性的元素;

      [data=val]--精确匹配属性值data为val的元素;

      [data~=val]--检查data属性值是否复合val序列中的任意一个;

      [data|=val]--匹配所有属性值为val开头的元素.

  3. 标签选择器

    标签选择器就是HTML标签进行直接选择, 一般进行页面的初试化和整体布局操作; 较常见的就是进行样式重置, 这里一般用到的是全体选择器, 即*;

    特别要注意的是, SVG命名空间和HTML命名空间不同, 需要使用@namescape进行指定, 避免元素选择器冲突:

    @namespace svg url(http://www.w3.org/2000/svg); 
    @namespace html url(http://www.w3.org/1999/xhtml);
    
    svg|a{}
    html|a{}
    

    这样, svg的a标签就不会与html中的冲突.

三大结构

  1. 复合选择器

    复合选择器是连续写在一起的简单选择器, 通过类的交集运算, 选定同一个元素的.

    通过连写.a.b调用, 即同时具备两种class的元素.

  2. 复杂选择器

    复杂选择器 复合选择器, 复杂选择器通过连接符进行逻辑上的组合. 这些连接符包括:

    • 空格: 选中符合条件的后代.

      ".x .y" 表示选中.x后代中具有.y的全部节点.

    • >--子选择器: 选中符合条件的子代节点

      ".x > .y" 表示选中.x的子代( 即第一后代 )中具有.y的节点.

    • ~--通用兄弟选择器: 选中所有符合条件的后继节点

      ".x ~ .y" 表示选中.x的后继结点中具有.y的节点.

    • +--相邻兄弟选择器: 选中所有复合条件的直接后继节点

      ".x + .y" 表示当.x的直接后继结点具有.y时选中. 相当于nextSlibling.

    • ||--列选择器: 选中对应列中的单元格.

    html body > div#pagewrap ~ ul#summer-drinks li.favorite {
      color: red;
      font-weight: bold;
    }
    

    而实际开发中并不会有这么复杂奇葩的选择器. 上面这些选择符使用最多的就是" "和">", 实际的生产环境中, 较多使用class的搭配来避免太过复杂的选择器, 也一般不会直接选择, 太过耦合会导致DOM树变化时, 页面规则错乱失效.

    ! 但是需要注意的时: 当属性为可继承时, 子选择器等同于后代选择器.

  3. 选择器列表 ,

    通过","来同时应用同一种规则, 即两个选择器的内容是一致的, 可以进行列表形式的简写, 以,分割;

    "a, b" 表示a, b两个选择器使用的规则是同一个.

两种属性

  1. style内联样式

    内联样式或内部样式表( style标签 )的优先级是最高的, 将规则直接在html中进行编写, 这在测试和临时覆盖有些用处, 但可维护性和可阅读性都不友好.

  2. !important例外规则

    !important不在优先级中, 而是直接打破规则, 直接作用在最终表达的元素上, !important 不建议使用, 可能会导致代码难以调试和维护. 特别是你想要后续覆盖某些样式时, 会遇到无法按照规则正常显示的问题.

    当然!important也有应用场景, 就是希望默写样式固定下来, 保持CSS的稳定时, 可以考虑使用. 或者在

    而不是拿来作为覆盖样式的结晶, 这样只会在后面栽跟头.

选择器优先级

选择器优先级的计算有三元组或者四元组来计算, 后者多考虑了内联的优先级.

如图, 如有三元组( a, b, c)或者四元组(x, a, b, c)

image-20210305180524759

  • 存在内联时, x为1
  • id选择器数目为a; class\伪类\属性选择器数目为b; 标签和伪元素选择器为c.

确定一个足够大的正数M, 则优先级公式为:

符合优先级 = MMa + Mb + c

这个M可以是任何值, 只要足够大( 浏览器设置为65536 ), 现在并没有多少的class覆盖id的说法, 那是IE旧时代的问题.

  • 同个类型选择器进行横向对比.
  • 同个优先级选择器顺序覆盖.
  • 针对的是单个复杂选择器, 多个选择器选中同一个不会叠加优先级, 而是由优先级最高的决定其优先级.

举个例子:

image-20210305182052440

如图, 四元组为(0, 1, 1, 3); 优先级 = M*M*1+M+3;

整体上有如下建议:

  • 使用class组合来决定元素样式,
  • 使用标签选择器来控制布局和风格.
  • 使用id等特异性强的选择器控制样式稳定.

伪类和伪元素

强烈建议配合MDN食用本小节 伪类与伪元素🔗

伪类

伪类是一系列针对特定状态而CSS规定的选择器, 形如:pesudoClass.

字面解释伪装的类, 即模仿类的行为, 产生的效果和类一致, 可以理解成其选择方式则是由其特定状态而决定的, 而非类class的属性值制定.

伪类数量众多, 大体上可以划分为用户行为伪类和元素结构伪类.

  1. 用户行为伪类--选中处于特定用户状态的元素.

    这里的用户状态指用户与网页的交互状态, 包括但不限于:

    • :hover 鼠标悬停
    • :active 激活元素, 如按下按钮但未松开时
    • :focus 页面焦点在元素上, 如选中输入框
    • :target 选中浏览器URL中hash部分( 即href="#id" )所指示的元素.
    • :link 未访问过的链接.
    • :visited 访问过的链接
    • :checked 选中状态中的单选或者复选框
    • :playing 媒体资源播放中
    • :paused 媒体资源暂停中
  2. 元素结构伪类

    有一些伪类用于在元素结点上进行选取控制的操作.

    • :root 匹配DOM树中的根节点, 即相当于html标签. 特别是在scoped css等场景, 用于选中子树.
    • :empty 没有子节点的元素
    • :first-child \ :last-child 第一个 \ 最后一个元素
    • :nth-child(n) 匹配一列兄弟元素中的元素——兄弟元素按照an+b形式的进行匹配(比如2n+1匹配元素所有的奇数个)
    • :only-child 匹配没有兄弟结点的元素.

    nth缩写: -->1st. 2nd, 3rd, 4th, ......, nth

  3. 逻辑伪类

    主要是:not()is(), 其中is()还未完全支持. 主要用于逻辑判断内部是否包含或者不包含选中部分.

伪元素

伪元素pesudo-element和伪类pesudo-class非常类似, 至少理念上, 都是为了完成一些特殊操作而制定的. 伪元素不仅是一种选择器, 相比伪元素它还能完成一些额外的操作, 如插入元素.

早期伪元素甚至使用的也是:, 后续分离, 使用::进行区别. 所以你看到一些较旧的写法:before, :after实际上是浏览器为了保持兼容, 但新的伪元素是不支持的, 所以建议保持::的风格.

用法也和伪类一致, 都是用于描述默些状态, 而伪元素在于它就如一个伪装的元素一样, 对页面DOM产生影响, 却不在DOM中, 因为它是由CSS负责的, 于HTML中的DOM实际上是两个物种.

它们主要有是针对一些特定场景时非常有用:

  • ::first-line \ -letter 第一行\第一个字, 对于一些CMS系统自动生成HTML时, 管理样式非常有用.
  • ::before 在匹配元素前插入一个可样式化的元素
  • ::after 在匹配元素前插入一个可样式化的元素
  • ::selection 文档被选中部分.

下一篇

前端二向箔08-浏览器CRP

参考引用

  1. 伪类和伪元素 - 学习 Web 开发 | MDN. (2020). Retrieved 5 March 2021, from developer.mozilla.org/zh-CN/docs/…
  2. 优先级 - CSS(层叠样式表) | MDN. (2020). Retrieved 5 March 2021, from developer.mozilla.org/zh-CN/docs/…
  3. Specifics on CSS Specificity | CSS-Tricks. (2010). Retrieved 5 March 2021, from css-tricks.com/specifics-o…

转发请附上原链接, thx~