【问题标题】:BEM generator mixin want to match MDL structureBEM 生成器 mixin 想要匹配 MDL 结构
【发布时间】:2016-06-26 08:03:26
【问题描述】:

所以我有以下 mixin 来生成我的 BEM 类:

$es: '__';
$ms: '--';

@function to-string($selector) {
    $selector: inspect($selector); //cast to string
    $selector: str-slice($selector, 2, -2); //remove brackets
    @return $selector;
}

@function contains-modifier($selector) {
    $selector: to-string($selector);
    @if str-index($selector, $ms) {
        @return true;
    } @else {
        @return false;
    }
}

@function get-block($selector) {
    $selector: to-string($selector);
    $modifier-start: str-index($selector, $ms) - 1;
    @return str-slice($selector, 0, $modifier-start);
}

@mixin blck($block) {
    .#{$block} {
        @content;
    }
}

@mixin elem($element) {
    $selector: &;
    @if contains-modifier($selector) {
        $block: get-block($selector);
        @at-root {
            #{$selector} {
                #{$block+$es+$element} {
                    @content;
                }
            }
        }
    } @else {
        @at-root {
            #{$selector+$es+$element} {
                @content;
            }
        }
    }
}

@mixin modf($modifier) {
    @at-root {
      #{&}#{$ms+$modifier} {
            @content;
        }
    }
}

@include blck(block) {
    background: red;
    @include elem(child){
        color: blue;
    };
    @include modf(modifier) {
        background: blue;
        @include elem(child) {
            color: red;
        }
    }
}

现在这实际上生成了完美的 BEM 样式代码,但我想匹配 MDL 代码结构,这意味着我想更具体地嵌套我的修饰符

.block
.block--modifer

.bock.block--modifier

如前所述,这样做的原因是为了匹配 MDL,可以在此处查看此格式的示例:https://github.com/google/material-design-lite/blob/master/src/card/_card.scss

现在我几乎可以通过改变这一行得到想要的效果:

@mixin modf($modifier) {
    @at-root {
      #{&}#{$ms+$modifier} {
            @content;
        }
    }
}

到这里:

@mixin modf($modifier) {
    @at-root {
      #{&}#{&}#{$ms+$modifier} {
            @content;
        }
    }
}

但这会改变 CSS 输出:

.block {
  background: red;
}
.block__child {
  color: blue;
}
.block--modifier {
  background: blue;
}
.block--modifier .block__child {
  color: red;
}

到这里:

.block {
  background: red;
}
.block__child {
  color: blue;
}
.block.block--modifier {
  background: blue;
}
.block.block--modifier .block.block__child {
  color: red;
}

现在您可以看到,这修复了修饰符的特异性,但破坏了修饰符的子级。

想要的输出如下:

.block.block--modifier .block__child {
  color: red;
}

您可以在这里看到这一切:http://codepen.io/crashy/pen/wGWPvr

【问题讨论】:

  • 你有没有停下来想想这是否是个好主意?您已经在这里编写了很多代码,以便为自己节省一些击键次数。您的问题的任何解决方案都将变得更加冗长。
  • @cimmanon 你好,是的,我有,我想这样做的原因是它可以阻止你孩子中的错字之类的事情并进行修改,它可以保持 CSS 的扁平和正确的结构,虽然它有很多给出的小示例的代码一旦应用于有多个 BEM 结构化类的框架,我认为它将变得非常宝贵。

标签: css sass mixins bem


【解决方案1】:

这是我通过叉你的笔快速想到的:

  1. 在 modf mixin 中添加 #{$selector}。

  2. 修改 get-block 函数,使其返回实际的基类。首先,我们将字符串分割到修饰符 (--) 的位置,然后检查连接的字符串中是否有多个类。如果有多个,我们将获得第一个。

来自codepen的链接:http://codepen.io/MKallivokas/pen/bpBYEg

$es: '__'; // Element
$ms: '--'; // Modifier
$ns: 'ns'; // Name space (Set to null if un-wanted)

@if($ns) {
  $ns: $ns + '-';
}

@function to-string($selector) {
    $selector: inspect($selector); //cast to string
    $selector: str-slice($selector, 2, -2); //remove brackets
    @return $selector;
}

@function contains-modifier($selector) {
    $selector: to-string($selector);
    @if str-index($selector, $ms) {
        @return true;
    } @else {
        @return false;
    }
}

@function get-block($selector) {
    // do what get-block was doing in order to
    // remove the modifier's part from the string
    $selector: to-string($selector);
    $modifier-start: str-index($selector, $ms) - 1;
    $selector: str-slice($selector, 0, $modifier-start);
    // remove the first dot
    $selector: str-slice($selector, 2, str-length($selector));
    // check if there is another dot
    $modifier-start: str-index($selector, '.') - 1;
    @if $modifier-start >= 0 {
      // if there's another dot we slice the string up to that point
      $selector: str-slice($selector, 0, $modifier-start);
    }
    // we insert the dot that we removed to the start
    $selector: str-insert($selector, '.', 1);
    @return $selector;
}

@mixin blck($block) {
  .#{$ns}#{$block} {
        @content;
    }
}

@mixin elem($element) {
    $selector: &;
    @if contains-modifier($selector) {
        $block: get-block($selector);
        @at-root {
            #{$selector} {
                #{$block+$es+$element} {
                    @content;
                }
            }
        }
    } @else {
        @at-root {
            #{$selector+$es+$element} {
                @content;
            }
        }
    }
}

@mixin modf($modifier) {
  $selector: &;
  @at-root {
    #{$selector}#{$selector+$ms+$modifier} {
      @content;
    }
  }
}

@include blck(block) {
    background: red;
    @include elem(child){
        color: blue;
    };
    @include modf(modifier) {
        background: blue;
        @include elem(child) {
            color: red;
        }
    }
}

我不知道它是否完全适合您的需求或涵盖您想做的所有情况,但我希望它有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多