Skip to content

Instantly share code, notes, and snippets.

@IPRIT
Last active April 7, 2017 00:43
Show Gist options
  • Select an option

  • Save IPRIT/be31cf05f291dc3822cd9be72cfe7eb0 to your computer and use it in GitHub Desktop.

Select an option

Save IPRIT/be31cf05f291dc3822cd9be72cfe7eb0 to your computer and use it in GitHub Desktop.
The mixin provides an easy way to build `bem` classes (block, element, modifier) like in example section
/**
* Copyright (c) 2017 Alex Belov
* MIT
*/
/* Prefixes */
$bem-block-prefix: ab-; // .ab-class { .. }
$bem-element-prefix: __; // .ab-class__element { .. }
$bem-modifier-prefix: _; // .ab-class__element_modifier { .. }
/**
* Helpers
*/
@function str-last-index($string, $substr) {
$index: null;
$length: str-length($string);
@for $n from $length through 1 {
$index: str-index(str-slice($string, $n, $length), $substr);
@if $index { @return $index + $n - 1; }
}
@return $index;
}
@function unwrap-scope($scope) {
@return str_slice(quote($scope), 1 + (str-last-index(quote($scope), unquote(' ')) or 0));
}
@mixin bem-block($block, $at-root: true) {
$scope: unwrap-scope(&);
$is-class: str-index($block, unquote('.'));
$selector: $block;
@if (not $is-class) {
$selector: unquote('.')#{$bem-block-prefix}#{$selector};
}
@if ($at-root) {
@at-root #{$selector} {
@content;
}
} @else {
#{$selector} {
@content;
}
}
}
@mixin bem-element($element, $at-root: true) {
$scope: unwrap-scope(&);
$selector: #{$scope}#{$bem-element-prefix}#{$element};
@if ($at-root) {
@at-root #{$selector} {
@content;
}
} @else {
#{$selector} {
@content;
}
}
}
@mixin bem-modifier($modifier, $at-root: true) {
$scope: unwrap-scope(&);
$selector: #{$scope}#{$bem-modifier-prefix}#{$modifier};
@if ($at-root) {
@at-root &#{$selector} {
@content;
}
} @else {
&#{$selector} {
@content;
}
}
}
/**
* Usage example:
*
* @include bem($block: block) {
* background: #faf;
* @include bem($element: element) {
* color: #8496F3;
* @include bem($modifier: modifier) {
* border: 1px solid #f5f;
* &:hover {
* background: #000;
* }
* }
* }
* }
*
* or
*
* @include bem-block(block) {
* background: #faf;
* @include bem-element(element) {
* color: #8496F3;
* @include bem-modifier(modifier) {
* border: 1px solid #f4f;
* &:hover {
* background: #000;
* }
* }
* }
* }
*
* Outputs:
* .ab-block {
* background: #faf; }
* .ab-block__element {
* color: #8496F3; }
* .ab-block__element.ab-block__element_modifier {
* border: 1px solid #f5f; }
* .ab-block__element.ab-block__element_modifier:hover {
* background: #000; }
*
*/
@mixin bem($block: null, $element: null, $modifier: null, $at-root: true) {
@if ($element and $modifier) {
@include bem-element($element, $at-root) {
@include bem-modifier($modifier, $at-root) {
@content;
}
}
} @else if ($element) {
@include bem-element($element, $at-root) {
@content;
}
} @else if ($modifier) {
@include bem-modifier($modifier, $at-root) {
@content;
}
} @else {
@include bem-block($block, $at-root) {
@content;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment