“Every line of code should appear to be written by a single person, no matter the number of contributors.” —@mdo
- 避免在 CSS 使用 HTML 标签选择器
- 例如,
.o-modal {}
要优于div.o-modal {}
- 相对于 HTML 标签,你应该优先使用类(除非是重置 CSS 这样的特殊情况)
- 例如,
- 不要使用 id 选择器
#header
相比.header
太过具体,难以覆盖其样式。- CSS 中使用 id 选择器的更多坏处可以参见这篇文章。
- 嵌套曾测不应该超过 3 层
- 层次嵌套过深意味着太过具体,覆盖其样式时则需要更具体的选择器,这很容易引起维护问题。
- 除伪类选择器和状态选择器外,应尽量避免过度嵌套。
- 嵌套
:hover
,:focus
,::before
等选择器没问题,但是嵌套普通选择器应当避免。
- 不要使用
!important
- 永远!
- 如果一定要使用它必须留下足够详细的注释。你应当在使用
!important
前尽可能地使用其它方法解决问题。 !important
会大幅提升 CSS 规则的优先级,极难覆盖,除非再使用一个!important
。
- 不要使用
margin-top
- 垂直 margin 会折叠在一起。优先设定
padding-top
或者前面元素的margin-bottom
。
- 垂直 margin 会折叠在一起。优先设定
- 避免使用属性简称(除非真的有必要)
- 在有些情况下你可以考虑这样使用,比如使用
background: #fff
而不是background-color: #fff
,但是这样做会覆盖该简写属性所包含的所有属性。(在这个例子中background-image
会被覆盖为none
。) - 一个简写就能覆盖所有的属性:比如 border, margin, padding, font 等等。
- 在有些情况下你可以考虑这样使用,比如使用
- 四个缩进
- 属性定义中
:
后应放置空格- 比如
color: red;
而不是color:red;
- 比如
- 定义规则时
{
前应有空格.o-modal {
而不应该.o-modal{
- 每条 CSS 规则单独成行
- 规则定义结束应在
}
后换行 - 聚合规则时,每条规则应单独成行
- 规则定义结尾的
}
应单独成行 - .scss 文件的结尾添加空行
- 不要使用多余的空格
- 所有选择器都应该是小写,使用连此符连接,也就是 “spinal case” 表示法。例如:
.my-class-name
- 优先使用 Sass 双斜线
//
注释,即使块级注释也是如此。 - 零值不需要单位,比如:
margin: 0;
而不要margin: 0px;
- 样式规则后面应该加上分号
- 小数前面应该保留 0
opacity: 0.4;
而不要opacity: .4;
- 自选择器前后加上空格,
div > span
要优于div>span
- import 语句
- 变量
- 基础样式
- 试验样式
例如:
//------------------------------
// Modal
//------------------------------
@import "../constants";
@import "../helpers";
$DBmodal-namespace: "c-modal" !default;
$DBmodal-padding: 32px;
$DBmodal-background: #fff !default;
$DBmodal-background-alt: color(gray, x-light) !default;
.o-modal { ... }
// Many lines later...
// EXPERIMENT: experiment-rule-name
.o-modal--experiment { ... }
// END EXPERIMENT: experiment-rule-name
- 应该在文件的顶部紧跟在 import 后的地方定义变量
- 本地变量前应当加上文件名(SASS 没有文档级变量)
- 例如
business_contact.scss
→$business_contact_font_size: 14px;
- 例如
- 本地变量应当遵循蛇形命名
$snake_lowercase
- 本地常量应当是大写蛇形
$SNAKE_ALL_CAPS
- 使用颜色变量来定义颜色
- 表示颜色的十六进制数值应当全部小写,如:
#fffff
- alpha 通道最多保持两位有效数字。不要省去前面的 0
示例:
// Bad
.c-link {
color: #007ee5;
border-color: #FFF;
background-color: rgba(#FFF, .0625);
}
// Good
.c-link {
color: color(blue);
border-color: #ffffff;
background-color: rgba(#ffffff, 0.1);
}
试验性规则应当以注释包裹:
// EXPERIMENT: experiment-rule-name
.stuff { ... }
// END EXPERIMENT: experiment-rule-name
属性以及嵌套的声明应当按照以下顺序排列,每种规则间以换行隔开:
- 所有
@
规则 - 布局及盒模型规则
- margin, padding, box-sizing, overflow, position, display, width/height 等等
- 排版属性
- 例如 font-*, line-height, letter-spacing, text-* 等等
- 样式属性
- color, background-*, animation, border 等等
- UI 属性
- appearance, cursor, user-select, pointer-events 等等
- 伪元素
- ::after, ::before, ::selection 等等
- 伪选择器
- :hover, :focus, :active 等等
- 装饰类
- 嵌套元素
综合示例:
.c-btn {
@extend %link--plain;
display: inline-block;
padding: 6px 12px;
text-align: center;
font-weight: 600;
background-color: color(blue);
border-radius: 3px;
color: white;
&::before {
content: '';
}
&:focus, &:hover {
box-shadow: 0 0 0 1px color(blue, .3);
}
&--big {
padding: 12px 24px;
}
> .c-icon {
margin-right: 6px;
}
}
-
出于可读性的考虑,应当避免三层以上的选择器嵌套
-
优先使用嵌套样式而不是嵌套元素。例如:
.block { padding: 24px; &--mini { padding: 12px; } }
可以通过优秀的类命名方法(BEM)来减少嵌套。应当避免直接使用标签选择器。
Block(块):独立、有意义的名字,样式的逻辑单元。应当避免过度简化
- Good:
.alert-box
or.recents-intro
or.button
- Bad:
.feature
or.content
or.btn
Element(元素):块的子元素才拥有的样式,块本身也是元素。元素的类名应当是块名加上两个下划线加上元素名。例如:
.alert-box__close
.expanding-section__section
Modifier(修饰符):重载或者扩张块或者元素的基础样式 。其类名应当是块或者元素名加上两个下划线加上元素名。例如:
.alert-box--success
.expanding-section--expanded
不要基于块元素样式 @extend
(扩展)修饰符。
- Good:
<div class="my-block my-block--modifier">
- Bad:
<div class="my-block--modifier">
不要在元素中创建元素。如果你真的认为有必要,先试着将元素转换为 block。
- Bad:
.alert-box__close__button
明智地选择修饰符。下面两条规则的意义完全不同:
.block--modifier .block__element { color: red; }
.block__element--modifier { color: red; }
- 为类型使用基于 BEM 的(中文)命名方式。
- 使用修饰符类时,永远应当加上基类/未修改的类。
- 像这样使用嵌套的 SASS 来管理 BEM 选择器:
.block { &--modifier { //编译为 .block--modifier text-align: center; } &__element { // 编译为 .block__element color: red; &--modifier { // 编译为 .block__element--modifier color: blue; } } }
类型命名空间中有一些保留名,用于全局抽象。
.o-
表示 CSS 对象。对象通常是基于通用设计模式(比如 Flag 对象),修改这项元素可能会引起严重问题。.c-
表示 CSS 组件。组件通常是基于 UI 的设计元素,比如按钮、输入框、模态窗以及横幅。.u-
表示帮助工具。工具类通常是用于单一目的,拥有高优先级。比如浮动元素、消除 margin 等等。.is-, .has-
表示状态类,遵循 SMACSS 形式。这些类用于表示临时、可选或者短期存在的状态和样式。._
一些 hack 用法。当你需要使用!important
或者增加 specificity 时应当使用这种类名。只应当临时使用,不应该绑定使用。.t-
主题类。在独立样式的页面或者需要覆盖组件/对象的样式时应当使用主题类。
分类思想(One Thing Well™)
你应该尽可能地提取出相同的 padding、字体、布局模式,并将其抽象为可重用的基于名字空间的类,可以保证绑定的元素只提供单一约束。这样做有助于防止规则的覆盖和重复,并且有助于按方面区分。
// 糟糕的例子
// HTML:
// <div class="modal compact">...</div>
.modal {
padding: 32px;
background-color: color(gray, x-light);
&.compact {
padding: 24px;
}
}
// 优秀的例子
// HTML:
// <div class="c-modal u-l-island">...</div>
// <div class="c-modal u-l-isle">...</div>
// components/_modal.scss
.c-modal {
background-color: color(gray, x-light);
}
// helpers/_layout.scss
.u-l-island {
padding: 32px;
}
.u-l-isle {
padding: 24px;
}
Media query 应当以 SMACSS 的形式写在 CSS 选择器中。
.selector {
float: left;
@media only screen and (max-width: 767px) {
float: none;
}
}
应该为经常用到的断点(breakpoint)设置变量
$SCREEN_SM_MAX: "max-width: 767px";
.selector {
float: left;
@media only screen and ($SCREEN_SM_MAX) {
float: none;
}
}