sass,基于父级的自定义选择器

时间:2014-03-15 04:31:19

标签: css sass bem

我有以下mixins,可以轻松使用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时,它将不具有--语法,而在其他父级为{{1}时它将具有m语法,我可以决定两种语境使用什么语法。 我没有找到一种方法将父选择器作为一个字符串,我认为是不可能的,有没有办法使这个工作?

更新 我找到了一个不太直接的解决方案,它运行正常,它在元素mixin中使用了一个context参数:

--

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

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

得到:

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

1 个答案:

答案 0 :(得分:0)

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

因此,更强大的方法是改进Element mixin以检查父选择器是否具有修饰符。

所以你需要2个功能:

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

@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);
}

然后你只需要在元素mixin中应用检查

$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;
      }
    }
  }
}

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

发布的代码是SCSS,但这个想法应与SASS相同。