这里总结一下 SCSS 中 @extend 和 Mixin 的几种经典用法,各自的适用场景,最佳实践。
@extend 经典用法
1, 继承样式
.message{ border:solid 1px #ddd; } .error-message{ @extend .message; color:red; }
2, 简单选择器,都可以extend
a:hover{ text-decoration: underline; } .hover-link{ @extend a:hover; }
3, 可以继承多个
.message{ border:solid 1px #ddd; } .error{ color:red; } .serious-error{ //@extend .message; //@extend .error; // 也可以逗号分隔 @extend .message, .error; background: mediumpurple; }
4, 可以链式继承
.message{ border:solid 1px #ddd; } .error-message{ @extend .message; color:red; } .serious-error{ @extend .error-message; background: mediumpurple; }
5, 嵌套的关系也可以被继承
.user-link{ color:skyblue; &:hover{ text-decoration: underline; } } .comment .link{ @extend .user-link; }
6, 占位符,只能被继承的选择器
%highlight{ color:red; font-weight: bold; } .notice{ @extend %highlight; }
7, 媒体查询指令中,不能继承外部选择器
// 正确用法 @media print, (max-width: 700px){ %panel{ padding:0; } .mobile-panel{ @extend %panel } } // 错误用法 %panel{ padding:0; } @media print, (max-width: 700px){ .mobile-panel{ @extend %panel } } // 正确用法 2 @media (max-width: 700px){ %panel{ padding:0; } } // ... @media (max-width: 700px){ .mobile-panel{ @extend %panel } }
8, @at-root 指令,取消嵌套
// 取消嵌套 .list{ padding: 10px; .item{ float:left; @at-root{ .item-tag{ font-size: 12px; } .item-badge{ border-radius: 50%; } } } } // 取消媒体查询的限制 @media (max-width: 700px){ .mobile-link{ background:lightblue; } @at-root .outer-link{ background:skyblue; } .common-link{ @at-root (without:media){ background:deepskyblue; } } }
Mixin 的经典用法
1, 重点在于复用
@mixin large-text{ font:{ size: 20px; weight:bold; } color:#333; } .page-title{ @include large-text; padding: 10px 0; margin-bottom: 10px; } .section-title{ @include large-text; margin:0; }
2, 可以不在选择器中引入
@mixin don-not-do-this{ a{ color:pink; } } @include don-not-do-this;
3, 带参数用法
@mixin dash-border($color,$width){ border:{ color:$color; width:$width; style:dashed; } } // ... p{ //@include dash-border(gray,2px); // 更容易看清参数 @include dash-border($color:gray,$width:2px); }
4, 单数的默认值、列表,map,参数对象
// ## 参数默认值 @mixin dash-border($color,$width:1px){ border:{ color:$color; width:$width; style:dashed; } } // ... p{ @include dash-border(gray); //@include dash-border($color:gray,$width:2px); } // arguments @mixin box-shadow($param...){ -webkit-box-shadow: $param; box-shadow: $param; } .box{ @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999); } @mixin colors($text,$bg,$border){ color:$text; background-color:$bg; border-color:$border; } // 列表 $value_list:#333,#666,#999; .primary{ @include colors($value_list...); } // map $value_map:(text:#000,bg:#999,border:#666); .secondary{ @include colors($value_map...); }
错误用法
1,不恰当的关联
%brand-font{ font-family: webfont, sans-serif; font-weight: 700; } // ... 三个点代表一百行代码 h1{ @extend %brand-font; font-size: 2em; } // ... .btn{ @extend %brand-font; display: inline-block; padding: 1em; } // ... .promotion{ @extend %brand-font; background: #bada55; color:#FFF; } // ... .footer-message{ @extend %brand-font; font-size: 0.75em; }
2,过分的抽象
// source 264字节 css 299字节 %bold { font-weight: bold; } //... .header--home > .header__tagline { @extend %bold; color: #333; font-style: italic; } //... .btn--warning { @extend %bold; background-color: red; color: white; } //... .alert--error > .alert__text { @extend %bold; color: red; }
// 这时候应该用 Mixin @mixin webfont() { font-family: webfont, sans-serif; font-weight: 700; } //... .foo { @include webfont(); } //... .bar { @include webfont(); } //... .baz { @include webfont(); }
3,多层嵌套的继承
.contact-text{ font-weight: bold; } .tos{ @extend .contact-text; } .foot .contact-text{ color:darkgray; } // 期望结果是这样么? .contact-text, .tos { font-weight: bold; } .foot .contact-text { color: darkgray; } // 实际结果却是 .contact-text, .tos { font-weight: bold; } .foot .contact-text, .foot .tos { color: darkgray; }
正确用法
- 没有逻辑关联的内容,不用 @extend,用Mixin
- 使用@extend的时候,尽量用 %placeholder,不嵌套
- 继承层级关系的时候,用 @extend
- keep sass simple
思考
1,DRY原则(Don’t repeat yourself)
Don’t repeat yourself:不是不让重复(don’t repeat)而是为了保证源头只有一个,源代码只出现在一处,一次修改自动同步到所有的CSS文件。CSS中,机器自动复制出来的的重复,不破坏 DRY 原则。
2,性能的考量
测试证明,开启gzip以后,用 Mixin 生成的重复更多,文件更大的 CSS 文件,压缩后性能更好。
附录
CSS 选择器分类 https://drafts.csswg.org/selectors-4/#syntax
4095 选择器 bug http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/10164546.aspx
失控的代码截图 https://twitter.com/droob/status/561161783239389185 https://twitter.com/gaelmetais/status/564109775995437057