IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    CSS Nesting嵌套与@scope规则也太雷同了吧?

    张 鑫旭发表于 2024-03-31 12:06:28
    love 0

    by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11144 鑫空间-鑫生活
    本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

    封面占位图

    一、居然还有个CSS嵌套

    年前有介绍CSS @scope规则,可以实现CSS的选择器内外嵌套,简化选择器的书写:

    @scope(nav) {
      ul {
        list-style: none;
        padding: 0;margin: 0;
      }
      li {
        display: inline-block;
      }
      a {
        display: block;
        padding: 6px 12px;
        text-decoration: none;
        background: skyblue;
      }
    }

    最近发现,几乎同一时间,现代浏览器还支持了专门用来嵌套书写的CSS Nesting语法,借鉴自Sass/Less/Stylus等预编译语言。

    使用示意:

    nav {
      ul {
        list-style: none;
        padding: 0; margin: 0;
      }
      li {
        display: inline-block;
      }
      a {
        display: block;
        padding: 6px 12px;
        text-decoration: none;
        background: skyblue;
      }
    }

    可以看到和@scope(nav)的语法极为相似,所实现的效果也是一样的,假设有如下所示的HTML代码:

    <nav>
      <ul>
        <li><a href="">链接1</a></li>
        <li><a href="">链接2</a></li>
        <li><a href="">链接3</a></li>
      </ul>
    </nav>
    <p><a>我呢?</a></p>

    可以看到,nav元素内的链接有背景色等样式,外部的a元素则依然是默认样式。

    嵌套样式渲染效果

    并且两种写法的选择器的优先级也是一样的。

    以a元素为说明对象,两种写法的选择器优先级均等同于 nav a。

    这就让我陷入了深深的沉思……为什么要弄两套规则如此相似的东西呢?

    二、@scope和Nesting的不同

    在我看来,CSS Nesting就是纯粹的语法糖,也就是就是纯粹的语法上的变化,本身并不具备任何新的特性。

    @scope则不一样,@scope规则中想要生效的选择器,一定属于@scope的子元素,带有“局部上下文”的性质在里面。

    我们可以通过一个例子感受下两者的不同。

    假设有两个无需列表<ul>元素:

    <ul>
      <li>列表1</li>
      <li>列表2</li>
      <li>列表3</li>
    </ul>
    <ul>
      <li>列表2-1</li>
      <li>列表2-2</li>
      <li>列表2-3</li>
    </ul>

    那么,@scope规则中使用:scope伪类(表示ul元素自身)和兄弟选择器,是无法匹配后面的ul元素的。

    @scope(ul) {
      :scope + ul {
        color: red;
        font-weight: bold;
      }
    }

    此时,所有的列表文字样式都是默认状态,如下图所示:

    列表样式效果

    但若是换成CSS嵌套写法(使用&符号表示祖先选择器):

    ul {
      & + ul {
        color: red;
        font-weight: bold;
      }
    }

    则可以看到后面一个<ul>列表的文字均是红色加粗:

    红色加粗

    由于CSS Nesting语法中的&符号就是纯粹的选择器替代,因此,上面的CSS写作这样效果也是一样的:

    ul {
      & + & {
        color: red;
        font-weight: bold;
      }
    }

    区别2:完整CSS规则和随意嵌套

    如果使用@scope语法,那么,规则中的每一行代码,都应该属于一个完整的规则,而不能是某一条单独的CSS声明。

    例如,下面的写法会让整段CSS规则无效:

    @scope(ul) {
      border: 1px solid;  
    
      li {
        color: red;
        font-weight: bold;
      }
    }

    但是CSS原生的嵌套语法都没有此顾虑,直接上:

    ul {
      border: 1px solid;  
    
      li {
        color: red;
      }
    }

    可以得到如下截图所示效果,列表有边框,文字是红色:

    列表边框和颜色

    三、不同规则见的相互嵌套?

    首先,CSS @scope范围和CSS Nesting嵌套是可以同时使用的,例如:

    @scope(body) {
      ul {
        border: 1px solid;
        li {
          color: red;
        }
      }
    }

    同样可以让列表出现边框,内容颜色是红色。

    列表边框和颜色

    两种特性都支持和其他@规则互相嵌套。

    CSS @scope范围可以嵌套其他@scope范围,例如下面的写法是合法的:

    @scope(body) {
      ul {
        border: 1px solid;
      }
    
      @scope(li) {
        :scope {
          color: red;
        }
      }
    }

    也支持和@media媒体查询一起使用,例如:

    @scope(ul) {
      :scope {
        border: 1px solid;
      }
    
      @media(width < 640px) {
        li {
          color: red;
        }
      }
    }

    和这段代码:

    ul {
      & {
        border: 1px solid;
      }
    
      @media(width < 640px) {
        li {
          color: red;
        }
      }
    }

    均可以在窄屏下让列表文字颜色红色,如下图所示:

    列表边框和颜色

    四、究竟什么时候用哪个?

    什么时候用范围,什么使用用嵌套呢?

    我琢磨了下,似乎绝大多数场景两者是可以随意替换的。

    思来想去,总感觉最大的区别反而是语义上的区别。

    你如果仅仅是想让书写更加简洁,代码更加装逼,使用嵌套。

    如果是单独的某个组件的开发,使用范围。

    这么一想,心里舒服多了。

    好了,就扯这么多吧,如果你有其他想法,欢迎评论交流。

    😘😘😘

    本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
    本文地址:https://www.zhangxinxu.com/wordpress/?p=11144

    (本篇完)



沪ICP备19023445号-2号
友情链接