编写 CSS 以使其简洁易读时遵循的 26 条规则
编写 CSS 以使其简洁易读时遵循的 26 条规则
CSS Stylelint Errors Examples
并非所有开发人员都遵循相同的 规则 在编写 CSS 时。如果您与前端开发人员团队合作,则尤其如此。您可能会看到以不连贯/不可读的形式编写的代码,这会影响前端/后端开发人员的理解。
从您的团队和公司的角度到您的项目本身,以一致的方式编写代码的好处很多。用一个 短绒 验证和执行这些规则将确保您的团队正在编写 符合标准 代码并防止引入错误。
“所以,如果你想快速完成,如果你想快速完成,如果你想让你的代码易于编写,就让它易于阅读。” — 罗伯特·C·马丁
在本文中,我们将回顾我的 CSS 编码 指导方针 列在一个[ .stylelintr](https://github.com/freemh/stylelint-rules/blob/main/.stylelintrc)
包含编写 CSS 的良好实践列表的文件,以扩展其可读性和可维护性,即使代码库增长;
但首先,让我们检查一下遵循这些规则可以做什么。
规则摘要
1 — 不要使用 ID 进行样式设置。
2 — 不要在类选择器中引用或设置后代元素
3 — 删除文件的所有尾随空格
4 — 不要将空格与制表符混合用于缩进
5 — 使用标准注释块将您的代码分成一个逻辑部分。
6 - 在您的部分评论下留下一条清晰的线条。
7 — CSS 规则应该用逗号分隔,但要换行
8 — 在规则集的左大括号之前包含一个空格
9 — 在声明的冒号后包含一个空格。
10 - 在声明块中的每个声明的末尾包含一个分号
11 — 在逗号分隔的属性或函数值中的每个逗号后包含一个空格。
12 — CSS 块应该用一条清晰的线分隔
13 — 始终使用双引号,在选择器中引用属性值
14 - 使用小写和速记十六进制值
15 - 在允许的情况下,避免指定零值单位
16 - 不允许速记属性中的冗余值。
17 — 从不使用 !重要的
18 - 显式设置属性
19 — 强制执行 粗鲁的
使用十六进制颜色的任何 CSS 属性中的变量,除了 当前颜色
和 你继承
价值观。
20 - 通过按照顺序(Sass 继承、定位、框模型、排版、视觉、动画、杂项)组合在一起对相关的属性声明进行排序
21 — 用一个冒号声明伪类
22 — 用双冒号声明伪元素
23 — 使用 雷姆
单位作为主要单位类型,这包括:
- 定位:
最佳
,正确的
,底部
,剩下
- 方面:
宽度
,高度
,利润
,填充
- 字体大小→使用
像素
单位作为以下属性的主要单位类型 - 边框宽度:
边框:1px 实心#bada55;
- 应保持行高 无单位 .如果您发现您正在使用具有固定单位类型的 line-height,请尝试考虑替代方法来实现相同的结果。如果这是一个需要特定的特殊情况
像素
或者雷姆
单元,用评论概述推理,以便其他人知道其目的。
24 — 避免使用幻数。重新思考问题( 上边距:37px
)
25 - 目标是只有 1 个嵌套规则的最大深度
26 - 组件语法应该遵循 <componentName>[--modifierName|-descendantName]
.componentName
必须用驼峰式书写。
.componentName
类名尽可能短,但要尽可能长。--修饰符名称
必须用驼峰写法--修饰符名称
必须用两个连字符与组件名称隔开后代名
必须用驼峰写法- 利用
componentName.is-stateOfComponent
用于组件的基于状态的修改 is-stateOfComponent
必须是骆驼案is-stateOfComponent
应该用作邻接类- 变量应该是这样的名称
[<componentName> [--modifierName][-descendantName]-]<propertyName> -<variableName> [--<modifierName> ]
使用类来设计元素
当您使用 ID 进行样式设置时,您将该元素绑定到一个 DOM 节点,并为该类型的每个节点提供相同的样式。这意味着如果您选择移动元素,您的 CSS 将需要更新。另外,如果您使用 ID 嵌套元素,则存在 ID 在嵌套元素的不同级别上相互冲突的风险。
ID 最终只是元素身份的指标。它们作为要操纵的给定元素脱颖而出。但是在 CSS 中使用 ID 并没有真正的意义,几乎在所有情况下,您都应该使用结合了纯 CSS 选择器和子组合器的类来维护 高特异性 .
Stylelint 规则
“选择器最大 ID”:0
例子
✅ 使用类进行样式设置。
。零件 {
...
}
❌ 不要使用 ID 进行样式设置。
#零件 {
...
}
✅ 对基本元素进行样式化(例如排版元素)
h1 {
...
}
❌ 不要在类选择器中引用或设置后代元素
.组件 h1 {
...
}
表现
过于具体的选择器可能会导致性能问题,它需要大量的 DOM 遍历,并且对于大型文档可能会导致布局时间显着增加。
尝试足够具体,以便不超过一个元素与选择器匹配。确保在重要的地方增加特异性,同时在所有其他时间保持低水平。这将确保精益和快速加载。
因此,与其关注选择器的复杂性,不如关注标记中的内容。更好的是,尽量不要过于具体,并在有意义的情况下使用类。
例子
✅ 做
.用户列表链接:悬停{
...
}
❌不要
ul.user-list li span a:hover {
...
}
格式和缩进
从您的 CSS 代码中删除所有尾随空格。这将确保您的文件干净且易于阅读,以供将来参考。
Stylelint 规则
“no-eol-whitespace”:真
除非您有独特的理由使用空格而不是制表符, 真的没有理由混合制表符和空格 .每个压痕深度值大约两个空格。
但是,如果要记住一个要点,那就是: 开发人员不会关心您使用哪些实验性的时髦缩进规则,只要它们在您的文档中一致地应用 ……这意味着坚持:
“D 不要将空格与制表符混合用于缩进 。”
Stylelint 规则
“缩进”:2
评论
使用像 BEM 这样的良好 Classe 命名约定已经为您的 CSS 代码提供了上下文,不过,我还是喜欢在样式表的顶部添加一个注释来描述整个文件正在做什么,为此:
- I 使用标准注释块将代码分成一个逻辑部分。
- 并且,在您的部分评论下留下一条清晰的线条。
我建议每个评论块都有一个明确的目的,而不是写一堵文字墙。目的是使代码更具可读性,因此注释应该简短而甜美,而不是更长的定义。
例子
// ================================================= ====================
// 文件标题/章节标题
// ================================================= ====================
//评论块/子部分
//------------------------------------------------ -----------------
//
// 目的:这将描述何时应该使用该组件。这条评论
// 块长 80 个字符
//
// 1. 用此处解释的数字标记代码行。
// 这可以让你的代码保持干净,同时也允许详细的注释。
//
//------------------------------------------------ -----------------
。零件 {
... // 1
}
间距
CSS 规则应该用逗号分隔,但在新行上。
Stylelint 规则
“选择器列表逗号换行后”:“总是”
在规则集的左大括号之前包含一个空格。
Stylelint 规则
“block-close-brace-space-before”:“总是”
- 在声明的冒号后包含一个空格。
- 在声明块中的每个声明的末尾包含一个分号
- 在逗号分隔的属性或函数值中的每个逗号后包含一个空格。
- CSS 块应该用一条清晰的线分隔
引号
CSS 引号在创建选择器时至关重要。它们用于将字符串值包含在样式表中,并且引号必须是双引号。
这样做的原因是因为 CSS 支持转义字符 (例如,*、 &、#) ,并且如果您在样式表中只使用单引号,那么您将无法转义这些字符,因此请坚持使用双引号来引用选择器中的属性值
例子
✅ 做
输入[类型=“复选框”] {
背景图片: url("/img/you.jpg");
字体家族:“Helvetica Neue Light”、“Helvetica Neue”、Helvetica、Arial;
}
❌不要
输入[类型=“复选框”] {
背景图片:网址(/img/you.jpg);
字体家族:Helvetica Neue Light、Helvetica Neue、Helvetica、Arial;
}
声明价值
CSS 单位系统的目标是提供一种声明易于阅读和理解的值的方法。应选择单位值,以便它们 简洁明了 .
声明 CSS 值时,请使用小写、十六进制和速记单位值。为您声明的每个属性使用尽可能短的单位值,以下规则非常适合编写具有可读性的值:
- 使用小写和速记十六进制值
- 使用无单位的行高值
- 在允许的情况下,避免指定零值单位
- 显式设置属性(避免
!重要的
)。 背景颜色:#333
超过背景:#333
上边距:10px
超过边距:0px 0 0
例子
✅ 做
。零件 {
背景颜色:#ccc;
颜色:#aaa;
左:0;
行高:1.25;
最小高度:400px;
填充:0 20px;
顶部:0;
}
❌不要
。零件 {
背景:#ccc;
颜色:#aaaaaa;
左:0px;
行高:24px;
高度:400px!重要;
填充:0px 20px 0px 20px;
顶部:0px;
}
申报单
CSS 声明的顺序是必不可少的。我在一些代码库中看到的最典型的问题是声明的顺序不一致。这会使代码难以阅读,并且还会在浏览器中引发意想不到的结果。
当您编写 CSS 时,按照相同的编写模式对声明进行排序以使它们更易于阅读通常很有帮助。
下面的示例遵循以下顺序:
-
声明
-
使用 Sass 时的 Sass 继承
-
内容
-
定位
-
盒子模型
-
排版
-
视觉的
-
动画
-
杂项
.declarationOrder {
/* 声明 */
$varName: #ccc;/* Sass 继承 */
@extend %a-占位符;
@include 愚蠢的链接;// 内容
内容: ””;// 定位
位置:绝对;
顶部:0;
右:0;
底部:0;
左:0;
z 指数:10;// 盒子模型
显示:块;
浮动:对;
宽度:100rem;
高度:100rem;
填充:10rem;
保证金:10rem;// 排版
颜色:$varName;
字体:普通 1rem “Helvetica”,无衬线;
行高:1.3;
文本对齐:居中;// 视觉的
背景颜色:$varName;
边框半径:4px;
不透明度:1;// 动画
过渡:全为 1;// 杂项
用户选择:无;
}
例子
✅ 做
。零件 {
// Sass 继承
@extend %a-占位符;
@include 愚蠢的链接;
// 位置和布局
顶部:0;
左:0;
// 盒子模型
宽度:150px;
最小高度:400px;
填充:0 20px;
// 排版
行高:1.25;
颜色:#aaa;
}
❌不要
。零件 {
顶部:0;
填充:0 20px;
@include 愚蠢的链接;
左:0;
@extend %a-占位符;
最小高度:400px;
行高:1.25;
宽度:150px;
颜色:#aaa;
}
伪元素和类
伪元素是一种向 HTML 元素添加合成内容的方法。它们是用一个冒号创建的 :
在元素名称之后,可用于为该元素创建其他样式。
✅ 声明伪 班级 带有一个冒号
.组件:焦点{
...
}
.component:悬停{
...
}
✅ 声明伪 元素 带有双冒号
.component::before {
...
}
.component::after {
...
}
❌不要
.component:{之后
...
}
单位
✅ 做
- 利用
雷姆
单位作为主要单位类型,这包括: - 定位:
最佳
,正确的
,底部
,剩下
- 方面:
宽度
,高度
,利润
,填充
- 字体大小
- 利用
像素
单位作为以下属性的主要单位类型 - 边框宽度:
边框:1px 实心#bada55;
- 行高应保持无单位。如果您发现您正在使用具有设定单位类型的线高,请尝试考虑替代方法来实现相同的结果。如果这是一个需要特定的特殊情况
像素
或者雷姆
单元,用评论概述推理,以便其他人知道其目的。
❌不要
- 避免使用幻数。重新思考问题(
上边距:37px
)
嵌套
嵌套有时很方便,但会与我们的 特异性 和 表现 指导方针。
当我们遵循 BEM 等广泛接受的方法的惯例和思想时,使用后缀可以提供极大的帮助。
- 仅仅因为你可以,并不意味着你应该。
- 观察您的输出,注意本文档中描述的特异性和性能。
下面的示例将显示一些 Sass 代码。
✅ 瞄准只有 1 个嵌套规则的最大深度
.面板体{
位置:相对;
} .panel-sideBar {
z 指数:10;
} .panel-sideBar-item {
光标:指针;
} .panel-sideBar-item-label {
颜色:#aeaeae; &.has-smallFont {
字体大小:1rem;
}
}
在最坏的情况下,这会产生:
.panel-sideBar-item-label.has-smallFont {
字体大小:1rem;
}
❌不要
.bc-tab-panel {
.面板体{
位置:相对; .panel-side-bar {
z 指数:10; .panel-side-item {
光标:指针; .panel-side-item-label {
颜色:#aeaeae; &.小字体{
字体大小:1rem;
}
}
}
}
}
}
在最坏的情况下,这会产生:
.bc-tab-panel
.panel-body
.panel-side-bar
.panel-side-item
.panel-side-item-label.small-font {
字体大小:13px;
}
成分
句法: <componentName>[--modifierName|-descendantName]
这个组件语法主要取自 西装 CSS 稍作修改。
组件驱动开发在读写 HTML 和 CSS 时提供了几个好处:
- 它有助于区分组件根、后代元素和修改的类。
- 它使选择器的特异性保持在较低水平。
- 它有助于将表示语义与文档语义分离。
您可以将组件视为包含特定语义、样式和行为的自定义元素。
❌ 不要根据视觉呈现或内容来选择类名
✅ 主要架构划分在组件和实用程序之间:
- 组件名称(例如。
。落下
或者.buttonGroup
) - componentName — 修饰符名称(例如。
.dropdwon--dropUp
或者.button--主要
) - componentName-descendantName(例如。
.dropdown-item
) - componentName.is-stateOfComponent(例如。
dropdown.is-active
) - u-utilityName(例如。
u-textTruncate
)
组件名称
组件的名称必须用驼峰写。使用尽可能短但尽可能长的类名。
-
例子
.nav
不是。导航
-
例子
。按钮
不是.btn
.myComponent {
/.../
}...
componentName — 修饰符名称
组件修饰符是一个类,它以某种形式修改基本组件的表示。修饰符名称必须以驼峰形式书写,并用两个连字符与组件名称隔开。除了基本组件类之外,该类还应包含在 HTML 中。
。按钮 {
...
} .button--primary {
...
} <button class="button button--primary">...</button>
组件名-后代名
组件后代是一个附加到组件后代节点的类。它负责代表特定组件将演示文稿直接应用于后代。后代姓名必须用驼峰式书写。
<article class="tweet">
<header class="tweet-header">
<img class="tweet-avatar" src="{$src}" alt="{$alt}" />
...
</header> <div class="tweet-body">...</div>
</article>
你可能会注意到 推特头像
,尽管是 推文标题
没有类 推文标题头像
.为什么?因为它不一定 有 住在那里。它可能毗邻 推文标题
并以相同的方式发挥作用。因此,如果必须住在那里,您应该只在其父母之前添加后代。尽量保持类名尽可能短,但要尽可能长。
在构建组件时,您经常会遇到这样的情况:您有一个列表、组或只是需要一个容器来容纳一些后代。在这种情况下,最好遵循将容器复数并让每个后代都是单数的模式。这使后代级别之间的关系保持清晰。
✅ 做
<nav class="pagination">
<ul class="pagination-list">
<li class="pagination-listItem">...</li>
</ul>
</nav> <ul class="breadcrumbs">
<li class="breadcrumb">
<a class="breadcrumb-label" href="#"></a>
</li>
</ul>
❌ 避免冗长的后代名称
<nav class="pagination">
<ul class="pagination-pages">
<li class="pagination-pages-page">...</li>
</ul>
</nav> <ul class="breadcrumbs">
<li class="breadcrumbs-breadcrumb">
<a class="breadcrumbs-breadcrumb-label" href="#"></a>
</li>
</ul>
componentName.is-stateOfComponent
利用 is-stateName
用于组件的基于状态的修改。州名必须是驼峰式。永远不要直接设置这些类的样式;它们应始终用作相邻类。
JS
或任何后端语言都可以添加/删除这些类。这意味着可以在多个上下文中使用相同的状态名称,但是每个组件都必须为状态定义自己的样式(因为它们的范围仅限于组件)。
<article class="tweet is-expanded">...</article> .tweet {
...
} .tweet.is-expanded {
...
}
结论
毕竟,仅仅在一段时间后查看您的代码可能会令人困惑,因此,在编写新代码时很容易意外引入错误,或者只是忘记添加特定样式的标点符号。 linter 将扫描您编写的每个单独文件并即时显示任何错误——甚至在您的代码被检入项目的主分支之前。
在这篇文章中,我们回顾了一些最有用的 linting 规则,我个人应用这些规则来以一致且可读的方式编写代码。
使用 CSS linter 和样式指南可以节省您调试代码和解决命名冲突和其他问题的时间。
谢谢阅读!
如果您觉得这篇文章有帮助,您可以通过点击拍手按钮并在下方发表评论来表达您的感激之情!
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明