V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sunjourney
V2EX  ›  程序员

scss 如何为 css 创建局部作用域?

  •  
  •   sunjourney · 2016-11-17 10:37:06 +08:00 · 3399 次点击
    这是一个创建于 2929 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想在 left-zone 和 right-zone 分别设置样式 reset ,理想的 css 输出如此如此:

    css:

    .left h1 {color: green; }
    .left p { color: red; }
    
    .right h1 {color; yellow; }
    .right p { color: black; }
    

    但是通过 scss 编写却没有一个很好的办法将 scss 块加上父选择器作用域

    scss:

    @mixin scope ($scope) {
      #{$scope} {
        @content;
      }
    }
    
    // 使用
    @include scope('.left') {
      h1 {color: green;}
      p {color: red;}
    }
    
    // 或者
    .left {
      h1 {color: green;}
      p {color: red;}
    }
    

    看上去可以,但遇到了 ampersand 符号,就很不友好了

    scss:

    @mixin scope ($scope) {
      #{$scope} {
        @content;
      }
    }
    
    // 一:将被加上作用域的 scss
    .a {
      .b & {
        color: white;
      }
    }
    
    // 二:加上作用域
    @include scope('.scope') {
      .a {
        .b & {
          color: white;
        }
      }
    }
    

    输出是

    css:

    // 一:原始的输出
    .b .a {
      color: white;
    }
    
    // 二:加作用域失败,不是 .scope .b .a { ... }
    .b .scope .a {
      color: white;
    }
    

    怎么包裹一个写好的 scss 块呢?想了想,只能通过拿 ampersand 最后一个选择器了

    @function g($amp) {
      $a: nth($amp, 1);
      @return nth($a, length($a));
    }
    
    // 改写一
    .a {
      .b #{g(&)} {
        color: white;
      }
    }
    
    // 使用 scope ,输出是 .scope .a .b .a ,失败,被嵌套的部分没有显式出现 `&` 而是 #{g(&)},嵌套的部分被 展开成了 .a .b #{g(&)}。而且 `#{g(&)}` 代替 `&` 也实在太丑了。
    @include scope('.scope') {
      .a {
        .b #{g(&)} {
          color: white;
        }
      }
    }
    

    有没有优雅的解决办法? @import 测试的结果和 @include 一样,& 总是先在 @mixin scope 中被展开,子 scss 块中的 & 就总是带有 scope 的内容。

    用 css module 加[data-scope='abc']的方法暂时不考虑,目前想加输出块前加一个父选择器。

    第 1 条附言  ·  2016-11-17 12:40:16 +08:00
    gh 上同样的问题, https://github.com/sass/sass/issues/1459 。至今也没合适的解决 `&` 的方案, https://codepen.io/trey/post/nesting-sass-includes 提供的 `@import` 方法表现的和 `@include` 也是一样的
    3 条回复    2016-11-17 11:15:44 +08:00
    sunjourney
        1
    sunjourney  
    OP
       2016-11-17 10:42:55 +08:00
    主要的问题就是加了 scope ,里面的 `&` 不能任意玩耍了,只能放选择器前面而不能后面。 BEM 中常遇到
    ```scss

    .block {
    &__element {
    color: red;
    }
    a:hover &__element {
    color: green;
    }
    }
    ```
    本来好好的,加上 scope 就废了
    viko16
        2
    viko16  
       2016-11-17 11:05:21 +08:00
    印象中有个 @at-root
    sunjourney
        3
    sunjourney  
    OP
       2016-11-17 11:15:44 +08:00
    @viko16 `@at-root` 对加 scope 好像没帮助呀
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2647 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 02:56 · PVG 10:56 · LAX 18:56 · JFK 21:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.