scss中利用mixin实现bem的写法
- Published on
本文最近一次更新于 1429 个天前,其中的内容很可能已经有所发展或是发生改变。
前言
BEM是一种css的命名规范,分别是Block(块)代表更高级别的抽象或组件,Element(元素) Block的后代,以及Modifier(修饰) 不同状态的修饰符,三个单词的缩写,目的是解决css混乱的命名方式,达到一个语义化的CSS命名方式。
命名方法
.block__element--modifier {
}
.block__element {
}
.block--modifier {
}
在预处理语言中的使用示例
.block {
&__header {
color: black;
}
&__button {
color: black;
&--default {
color: blue
}
}
}
scss中结合mixin的bem规范(以element ui为例)
结合sassmeister在线编译
定义mixin
// 定义block的mixin
@mixin b($block) {
$B: 'el-'+$block !global;
.#{$B} {
@content;
}
}
// 定义element的mixin
@mixin e($element) {
$E: $element !global;
$selector: &;
$currentSelector: "";
@each $unit in $element {
$currentSelector: #{$currentSelector + "." + $B + '__' + $unit + ","};
}
@if hitAllSpecialNestRule($selector) {
@at-root {
#{$selector} {
#{$currentSelector} {
@content;
}
}
}
} @else {
@at-root {
#{$currentSelector} {
@content;
}
}
}
}
// 定义modifier的mixin
@mixin m($modifier) {
$selector: &;
$currentSelector: "";
@each $unit in $modifier {
$currentSelector: #{$currentSelector + & + '--' + $unit + ","};
}
@at-root {
#{$currentSelector} {
@content;
}
}
}
@at-root指令可以使一个或多个规则被限定输出在文档的根层级上,也就是
.parent{ @at-root{.child{}}}
编译以后就是.parent{} .child{}
。
hitAllSpecialNestRule
@function selectorToString($selector) {
$selector: inspect($selector);
$selector: str-slice($selector, 2, -2);
@return $selector;
}
// 是否包含修饰词
@function containsModifier($selector) {
$selector: selectorToString($selector);
@if str-index($selector, $modifier-separator) {
@return true;
} @else {
@return false;
}
}
// 是否包含.is-前缀
@function containWhenFlag($selector) {
$selector: selectorToString($selector);
@if str-index($selector, '.' + 'is-') {
@return true;
} @else {
@return false;
}
}
// 是否包含":"
@function containPseudoClass($selector) {
$selector: selectorToString($selector);
@if str-index($selector, ':') {
@return true;
} @else {
@return false;
}
}
@function hitAllSpecialNestRule($selector) {
@return containsModifier($selector) or containWhenFlag($selector) or containPseudoClass($selector);
}
使用mixin
比如element-ui的input样式
@include b(input) {
position: relative;
font-size: 12px;
display: inline-block;
width: 100%;
@include e(inner) {
box-sizing: border-box;
}
@include m(small) {
font-size: 14px;
@include e(inner) {
height: 28px;
line-height: 28px;
}
}
}
编译以后就是
.el-input {
position: relative;
font-size: 12px;
display: inline-block;
width: 100%;
}
.el-input__inner {
box-sizing: border-box;
}
.el-input--small {
font-size: 14px;
}
.el-input--small .el-input__inner {
height: 28px;
line-height: 28px;
}
扩展element ui的样式
// 首先引用mixin
@import "xxxx/node_modules/element-ui/packages/theme-chalk/src/mixins/mixins";
// 比如说修改默认的弹窗样式
@include b(dialog) {
@include m(slim) {
@include e(body) {
padding: 0 20px 20px;
}
@include e(footer){
padding-top: 0;
}
}
}
在el-dialog
中只需要添加el-dialog--slim
样式就能修改弹窗的默认padding了,不过也是采用覆盖的方式。
<el-dialog
custom-class="el-dialog--slim">
</el-dialog>