学习 CSS Nesting 原生嵌套语法 🥳

CSS 预处理器

概述/简介

CSS Houdini 提案之前,CSS 本身不属于可编程语言。当前端项目逐渐庞大之后,CSS 的维护也越来越困难,这时我们就需要 CSS 预处理器通过 工程化 的手段让 CSS 更易维护,提升开发效率。CSS 预处理器本质上是通过 变量嵌套语法逻辑函数 等为 CSS 增加一些可编程的特性。

目前主流的 CSS 预处理器主要有

  • Sass
  • Less
  • Stylus
  • PostCSS

调研/统计

据统计过使用 CSS 预处理器首要原因:

  • 嵌套语法: 35%
  • 变量: 35%
  • 函数: 25%
  • 其他: 5%
pie title "嵌套语法" : 35 "变量" : 35 "函数" : 25 "其他" : 5

如果不使用 CSS 预处理器,如何精简 CSS 样式定义?

  • :is()
  • :where()
css 复制代码
  /* Normal 样式 */
  #card img
  #footer img {
    /* 优先级权重 = (1,0,1) */
  }


  /* 使用 :is() 样式 */
  :is(#card, #footer) img {
    /* 优先级权重 = (1,0,1) */
  }


  /* 使用 :where() 样式 */
  :where(#card, #footer) img {
    /* 优先级权重 = (0,0,1) */
  }

注意 :is():where() 的 CSS 优先级权重!

CSS 原生嵌套语法

就如上个小节所述,嵌套语法是使用 Sass/Less 等 CSS 预处理器的核心原因之一。但在小型项目(HTML + CSS + JS)开发中,使用 CSS 预处理器却有些不便且过于厚重,虽然可以通过 :is():where() 进行简化,但始终无法做到嵌套语法开发时体验和效率。不过现在有了 CSS 原生嵌套语法的支持,一切都迎刃而解。

兼容性

目前主流浏览器都已支持 CSS Nesting 这个特性。查看最新

注意: 该规范的早期版本不允许在没有 &@:.>~+#[* 等选择器的情况下嵌套类型选择器。新版已更新,不再需要嵌套选择器。但是支持度如下:

  • 目前 Firefox 支持新版本的规范
  • 目前 Chrome 和 Safari 支持旧版本的规范,必须使用嵌套选择器进行类型选择器嵌套,具体后面会进行讲解

基本概念

CSS 嵌套语法

定义了嵌套选择器的语法,提供了将一个样式规则嵌套在另一个样式规则中的功能,子规则的选择器相对于父规则的选择器。

css 复制代码
  /* 使用嵌套语法,但不使用嵌套选择器,根据兼容性情况,目前只有 Firefox 支持 */
  parent {
    /* parent styles */
    
    child {
      /* child of parent styles */
    }
  }


  /* 使用嵌套语法,且使用嵌套选择器,主流浏览器都支持 */
  parent {
    /* parent styles */
    
    & child {
      /* child of parent styles */
    }
  }
  

与预处理器区别

  • CSS 嵌套语法是由浏览器解析识别
  • CSS 预处理器是前端项目在构建期间进行预编译成css

嵌套规则

  • CSS选择器
  • @media
  • @layer
  • @scope (暂不提供范例)
  • @supports (暂不提供范例)
  • @container (暂不提供范例)

范例 - CSS选择器

css 复制代码
  /* 例 1 */
  h2 {
    & p {
      /* h2 p 样式 */
    }
  }
  
  /* 例 2 */
  h2 {
    &.p {
      /* h2.p 样式 */
    }
  }
  
  /* 例 3 */
  .card { 
    & h2 {
      .featured & {
        /* .featured .card h2 */
      }
    }
  }
  

范例 - media

css 复制代码
  /* 使用嵌套语法 */
  .foo {
    display: grid;
    
    @media (orientation: landscape) {
      grid-auto-flow: column;
      
      @media (min-width > 1024px) {
        max-inline-size: 1024px;
      }
    }
  }
  
  
  /* 等效于下面的语法 */
  
  
  .foo {
    display: grid;
  }
  
  @media (orientation: landscape) {
    .foo {
      grid-auto-flow: column;
    }
  }
  
  @media (orientation: landscape) and (min-width > 1024px) {
    .foo {
      max-inline-size: 1024px;
    }
  }
  

范例 - layer

css 复制代码
  .foo {
    @layer base {
      block-size: 100%;
      
      @layer support {
        & .bar {
          min-block-size: 100%;
        }
      }
    }
  }
  
  
  /* 等效于下面的语法 */
  


  @layer base {
    .foo {
      block-size: 100%;
    }
  }
  
  @layer base.support {
    .foo .bar {
      min-block-size: 100%;
    }
  }

特异性权重

嵌套选择器的特异性是使用关联选择器列表中的最大特异性计算的。这与使用 :is() 函数时计算特异性的方式相同。

html 复制代码
  <!DOCTYPE html>
  <html lang="en">
    <head>
      <style type="text/css">
        #a,b {
          & c {
            /* 优先级权重 = (1,0,1) */
          }
        }

        .foo c {
          /* 优先级权重 = (0,1,1) */
        }
  
        /* 等效于下面的语法 */
  
        :is(#a, b) {
          & c {
            /* 优先级权重 = (1,0,1) */
          }
        }

        .foo c {
          /* 优先级权重 = (0,1,1) */
        }
      </style>
    </head>
    
    <body>
      <b class="foo">
        <c>Blue text</c>
      </b>
    </body>
  </html>

CSS 预处理器的优势还在吗?

  • CSS Nesting 原生嵌套语法,主流浏览器均已支持
  • CSS 自定义属性/变量,主流浏览器均已支持,详情
  • CSS Houdini 公开了 CSS 引擎的各个部分,允许通过JS编程,相比 CSS-In-JS 更加出色,不过目前兼容性有待提高
  • CSS 原生函数众多(如 clamp()color-mix()color-contrast() 等)。虽然离 CSS 预处理器有段距离,但是越来越稳健。

也许不久的将来,我们可以完全不再依赖 CSS 预处理器,做到更好开发体验和效率。

相关推荐
万叶学编程2 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js
前端李易安4 小时前
Web常见的攻击方式及防御方法
前端
PythonFun4 小时前
Python技巧:如何避免数据输入类型错误
前端·python
知否技术4 小时前
为什么nodejs成为后端开发者的新宠?
前端·后端·node.js
hakesashou4 小时前
python交互式命令时如何清除
java·前端·python
天涯学馆4 小时前
Next.js与NextAuth:身份验证实践
前端·javascript·next.js
HEX9CF5 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
ConardLi5 小时前
Chrome:新的滚动捕捉事件助你实现更丝滑的动画效果!
前端·javascript·浏览器
ConardLi5 小时前
安全赋值运算符,新的 JavaScript 提案让你告别 trycatch !
前端·javascript