Last active
February 29, 2020 15:27
-
-
Save elado/af17ed255333dc34375876a4decd827e to your computer and use it in GitHub Desktop.
Advanced BEM SASS Mixins
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@mixin reset { | |
&, * { | |
margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; | |
box-sizing: border-box; min-height: 0; min-width: 0; | |
ul { list-style: none; } | |
button { width: auto; height: auto; border: 0; background-color: transparent; cursor: pointer; outline: none; line-height: 1; } | |
} | |
} | |
$bem-use-namespace: false !default; | |
$bem-reset: false !default; | |
$__current-block-stack: () !global; | |
@for $i from 1 through 1000 { | |
$__current-block-stack: append($__current-block-stack, null) !global; | |
} | |
$__current-block-stack-index: 0 !global; | |
@function current-block-config() { | |
@return nth($__current-block-stack, $__current-block-stack-index); | |
} | |
@function current-block-name() { @return map-get(current-block-config(), 'block-name'); } | |
@function current-block-promote() { @return map-get(current-block-config(), 'promote'); } | |
@function current-block-namespace() { @return map-get(current-block-config(), 'namespace'); } | |
@mixin block($block-name, $namespace: $bem-use-namespace, $reset: $bem-reset, $promote: true) { | |
$__current-block-stack-index: $__current-block-stack-index + 1 !global; | |
@if $__current-block-stack-index > 1 { | |
$promote: false; | |
} | |
$config: ( | |
'block-name': $block-name, | |
'promote': $promote, | |
'namespace': $namespace | |
); | |
$__current-block-stack: set-nth($list: $__current-block-stack, $n: $__current-block-stack-index, $value: $config) !global; | |
// apply reset only for root level | |
@if $__current-block-stack-index == 1 and $reset { | |
#{block-selector($block-name, $namespace: $namespace, $promote: false)} { | |
@include reset; | |
} | |
} | |
#{block-selector($block-name, $namespace: $namespace, $promote: $promote)} { | |
@content; | |
} | |
$__current-block-stack-index: $__current-block-stack-index - 1 !global; | |
} | |
@mixin block-child($child-name, $promote: false, $pseudo: null) { | |
@if type-of($child-name) != 'list' { | |
$child-name: ($child-name); | |
} | |
$sel: ''; | |
@each $child-name-item in $child-name { | |
$current-selector: block-child-selector( | |
$block-name: current-block-name(), | |
$block-namespace: current-block-namespace(), | |
$child-name: $child-name-item, | |
$block-promote: current-block-promote(), | |
$child-promote: $promote, | |
$pseudo: $pseudo | |
); | |
$sel: '#{$sel}#{$current-selector},'; | |
} | |
#{$sel} { | |
@content; | |
} | |
} | |
@mixin block-override($args...) { | |
@include block($args...) { @content; } | |
} | |
@mixin blocks-override($block-names, $promote: true) { | |
@each $block-name in $block-names { | |
@include block($block-name, $promote: $promote) { | |
@content; | |
} | |
} | |
} | |
@mixin block-mod($mod-name, $mod-value: null, $promote: false, $pseudo: null, $op: 'or') { | |
@if type-of($mod-name) == 'string' { | |
$tmp: (null); | |
$tmp: set-nth($tmp, 1, ($mod-name, $mod-value)); | |
$mod-name: $tmp; | |
} | |
$sel: null; | |
@each $mod-item in $mod-name { | |
$mod-name-item: nth($mod-item, 1); | |
$mod-value-item: null; | |
@if length($mod-item) > 1 { | |
$mod-value-item: nth($mod-item, 2); | |
} | |
$current-selector: block-mod-selector( | |
$block-name: current-block-name(), | |
$block-namespace: current-block-namespace(), | |
$mod-name: $mod-name-item, | |
$mod-value: $mod-value-item, | |
$block-promote: current-block-promote(), | |
$mod-promote: $promote, | |
$pseudo: $pseudo | |
); | |
$sel: '#{$sel}#{&}#{$current-selector}'; | |
@if $op != 'and' { | |
$sel: '#{$sel},'; | |
} | |
} | |
@at-root #{$sel} { | |
@content; | |
} | |
} | |
@function block-selector($block-name, $namespace: null, $promote: false) { | |
$sel: '.'; | |
@if $namespace { $sel: '#{$sel}#{$namespace}-'; } | |
$sel: '#{$sel}#{$block-name}'; | |
@if $promote { $sel: '#{$sel}[class]'; } | |
@return $sel; | |
} | |
@function block-child-selector($block-name, $block-namespace, $child-name, $child-promote: false, $block-promote: true, $pseudo: null) { | |
$sel: '#{block-selector($block-name, $block-namespace, false)}__#{$child-name}'; | |
@if $child-promote { $sel: '#{$sel}[class]'; } | |
@if $pseudo { $sel: '#{$sel}#{$pseudo}'; } | |
@return $sel; | |
} | |
@function block-mod-selector($block-name, $block-namespace, $mod-name, $mod-value: null, $mod-promote: false, $block-promote: true, $pseudo: null) { | |
$sel: '#{block-selector($block-name, $block-namespace, false)}--#{$mod-name}'; | |
@if $mod-value { | |
$sel: '#{$sel}--#{$mod-value}'; | |
} | |
@if $mod-promote { $sel: '#{$sel}[class]'; } | |
@if $pseudo { $sel: '#{$sel}#{$pseudo}'; } | |
@return $sel; | |
} | |
@function current-block-child-selector($child-name) { | |
@return block-child-selector(current-block-name(), current-block-namespace(), $child-name, $block-promote: false); | |
} | |
@function current-block-mod-selector($child-name) { | |
@return block-mod-selector(current-block-name(), current-block-namespace(), $child-name, $block-promote: false); | |
} | |
@mixin b($args...) { | |
@include block($args...) { @content; } | |
} | |
@mixin m($args...) { | |
@include block-mod($args...) { @content; } | |
} | |
@mixin c($args...) { | |
@include block-child($args...) { @content; } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$bem-use-namespace: 'ns'; | |
$bem-reset: true; | |
// .ns-InfoPane[class] | |
@include b('InfoPane') { | |
border: 1px solid red; | |
// .ns-InfoPane[class] .ns-InfoPane__header | |
@include c('header') { | |
background: gray; | |
} | |
// .ns-InfoPane[class] .ns-InfoPane__main | |
@include c('main') { | |
line-height: 1.4em; | |
} | |
// .ns-InfoPane[class].ns-InfoPane--minimized .ns-InfoPane__main { | |
@include m('minimized') { | |
@include c('main') { | |
height: 20px; overflow: hidden; | |
} | |
} | |
} | |
// .ns-Message[class] | |
@include b('Message') { | |
// .ns-Message[class] .ns-Message--direction--outgoing | |
@include m('direction', 'outgoing') { | |
} | |
} | |
// .ns-MessageList[class] | |
@include b('MessageList') { | |
a: 1; | |
// .ns-MessageList[class] .ns-Message | |
@include b('Message') { | |
b: 2; | |
// .ns-MessageList[class] .ns-Message .ns-UserAvatar | |
@include b('UserAvatar') { | |
c: 3; | |
} | |
@include m('direction', 'outgoing') { | |
// .ns-MessageList[class] .ns-Message .ns-Message--direction-outgoing .ns-UserAvatar | |
@include b('UserAvatar') { | |
d: 4; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.ns-InfoPane, .ns-InfoPane * { | |
margin: 0; | |
padding: 0; | |
border: 0; | |
font-size: 100%; | |
font: inherit; | |
vertical-align: baseline; | |
box-sizing: border-box; | |
min-height: 0; | |
min-width: 0; | |
} | |
.ns-InfoPane ul, .ns-InfoPane * ul { | |
list-style: none; | |
} | |
.ns-InfoPane button, .ns-InfoPane * button { | |
width: auto; | |
height: auto; | |
border: 0; | |
background-color: transparent; | |
cursor: pointer; | |
outline: none; | |
line-height: 1; | |
} | |
.ns-InfoPane[class] { | |
border: 1px solid red; | |
} | |
.ns-InfoPane[class] .ns-InfoPane__header { | |
background: gray; | |
} | |
.ns-InfoPane[class] .ns-InfoPane__main { | |
line-height: 1.4em; | |
} | |
.ns-InfoPane[class].ns-InfoPane--minimized .ns-InfoPane__main { | |
height: 20px; | |
overflow: hidden; | |
} | |
.ns-Message, .ns-Message * { | |
margin: 0; | |
padding: 0; | |
border: 0; | |
font-size: 100%; | |
font: inherit; | |
vertical-align: baseline; | |
box-sizing: border-box; | |
min-height: 0; | |
min-width: 0; | |
} | |
.ns-Message ul, .ns-Message * ul { | |
list-style: none; | |
} | |
.ns-Message button, .ns-Message * button { | |
width: auto; | |
height: auto; | |
border: 0; | |
background-color: transparent; | |
cursor: pointer; | |
outline: none; | |
line-height: 1; | |
} | |
.ns-MessageList, .ns-MessageList * { | |
margin: 0; | |
padding: 0; | |
border: 0; | |
font-size: 100%; | |
font: inherit; | |
vertical-align: baseline; | |
box-sizing: border-box; | |
min-height: 0; | |
min-width: 0; | |
} | |
.ns-MessageList ul, .ns-MessageList * ul { | |
list-style: none; | |
} | |
.ns-MessageList button, .ns-MessageList * button { | |
width: auto; | |
height: auto; | |
border: 0; | |
background-color: transparent; | |
cursor: pointer; | |
outline: none; | |
line-height: 1; | |
} | |
.ns-MessageList[class] { | |
a: 1; | |
} | |
.ns-MessageList[class] .ns-Message { | |
b: 2; | |
} | |
.ns-MessageList[class] .ns-Message .ns-UserAvatar { | |
c: 3; | |
} | |
.ns-MessageList[class] .ns-Message.ns-Message--direction--outgoing .ns-UserAvatar { | |
d: 4; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment