【问题标题】:sass, custom selectors based on parentsass,基于父级的自定义选择器
【发布时间】:2014-04-20 14:28:28
【问题描述】:

我有以下 mixin 可以轻松使用 BEM 语法,sass 3.3.2 代码:

=b($name)
  .#{$name}
    @content

=e($name)
  &__#{$name}
    @content

=m($name)
  &--#{$name}
    @content

+b(menu)
  +e(item)
    color: grey
  +e(item)
    +m(alert)
      color: red

这给了我想要的结果:

.menu__item {color: grey;}
.menu__item--alert {color: red;}

所以这对元素级修饰符非常有效,但是当我想要块级修饰符时,问题就开始了:

+b(menu)
  +m(theme-1)
    +e(item)
      color: blue

css 输出:

.menu--theme-1__item {color: blue;}

当我真正想要的是:

.menu--theme-1 .menu__item {color: blue;}

所以我需要一种方法来检查元素的上下文是什么,当上下文是块时没有问题,但当是修饰符时语法失败。我尝试在 e mixin 中将父选择器作为字符串,所以当e parent 是 b 时,它不会有 -- 语法,反之,当他的 parent 是 m 时,它将有 @987654331 @ 语法,这样我可以决定两种上下文使用什么语法。 我没有找到将父选择器作为字符串的方法,我认为这是不可能的,有没有办法让它工作?

更新 我发现一个不是很简单的解决方案可以正常工作,它在元素 mixin 中使用上下文参数:

=e($name, $context:null)
  @if $context
    &
      +b($context)
        &__#{$name}
          @content
  @else
    &__#{$name}
      @content

现在我可以按如下方式调用 mixin:

+b(menu)
  +m(theme-1)
    +e(item, nav)
      color: blue

得到:

.menu--theme-1 .menu__item {color: blue;} 

【问题讨论】:

  • +1 -- 我正要问这个问题。

标签: css sass bem


【解决方案1】:

回答一个 2 岁的问题 - 远射 :) 但希望也能帮助其他人。

因此,一种更稳健的方法是改进您的 Element mixin 以检查父选择器是否具有修饰符。

所以你需要两个函数:

  • 检查选择器是否包含修饰符
  • 从该选择器获取块名称

@function _bem-selector-has-modifier($selector) {
  $selector: _bem-selector-to-string($selector);

  @if str-index($selector, $bem-modifier-separator) or str-index($selector, ':') {
    @return true;
  } @else {
    @return false;
  }
}


@function _bem-get-block-name($selector) {
  $selector: _bem-selector-to-string($selector);
  $modifier-separator: '--';

  $modifier-start: str-index($selector, $modifier-separator) - 1;

  @return str-slice($selector, 0, $modifier-start);
}

然后你只需要在你的元素混合中应用检查

$bem-element-separator: '__';

@mixin element($element) {
  $selector: &;

  @if _bem-selector-has-modifier($selector) {
    $block: _bem-get-block-name($selector);

    @at-root {
      #{$selector} {
        .#{$block + '__' + $element} {
          @content;
        }
      }
    }
  } @else {
    @at-root {
      #{$selector +'__' + $element} {
        @content;
      }
    }
  }
}

因此,在 modifier('with-modifier') 中调用 element('item') 应该会在编译后的 CSS 中呈现 .block--with-modifier .block__item 选择器,并且您不必手动传递上下文。

贴出来的代码是SCSS,不过思路应该和SASS一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-15
    • 1970-01-01
    • 1970-01-01
    • 2020-07-08
    • 2015-05-04
    • 2018-08-11
    • 2013-09-16
    • 1970-01-01
    相关资源
    最近更新 更多