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

2016-11-17 10:37:06 +08:00
 sunjourney

想在 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']的方法暂时不考虑,目前想加输出块前加一个父选择器。

3399 次点击
所在节点    程序员
3 条回复
sunjourney
2016-11-17 10:42:55 +08:00
主要的问题就是加了 scope ,里面的 `&` 不能任意玩耍了,只能放选择器前面而不能后面。 BEM 中常遇到
```scss

.block {
&__element {
color: red;
}
a:hover &__element {
color: green;
}
}
```
本来好好的,加上 scope 就废了
viko16
2016-11-17 11:05:21 +08:00
印象中有个 @at-root
sunjourney
2016-11-17 11:15:44 +08:00
@viko16 `@at-root` 对加 scope 好像没帮助呀

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/321109

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX