本文概述
在15年的网络开发经验中, 我曾与多家公司(从企业级到初创公司)合作, 并且与许多其他软件工程师合作。我在项目中遇到的最常见, 最重要的问题之一就是未能编写干净且易于理解的代码。
即使是顶尖公司的最优秀开发人员, 也不会总是遵循最佳实践并编写可清理和优化的代码。
凌乱和肮脏的代码的后果
引用旧的但仍然相关的博客文章讨论干净代码原则:
源代码类似于金融债务。假设你想买房子居住。大多数人没有足够的资金来支付房屋现金, 因此你选择抵押。但是抵押本身并不是一件好事。这是一种责任。你必须每月偿还债务利息……在Web开发中也是如此。该代码具有持续的成本。你必须了解它, 必须维护它, 并且随着时间的推移必须使其适应新的目标。你拥有的代码越多, 持续的成本就越大。尽可能少的源代码同时仍然能够实现我们的业务目标是我们的最大利益。
但是, 让我们不要只停留在摘要上。本文将介绍基本的干净代码原理, 用于组织代码的不同技术以及如何使其更易于维护, 可扩展和更容易调试。
质量代码从基本代码样式开始, 到在使用具有许多可重用块的HTML / CSS编写大型应用程序时扩展到最佳实践, 并且我们还将讨论命名约定以创建更高的隐式可读性以及第三方框架及其最佳实践。
在阅读完本文之后, 你应该对质量代码的基本知识以及如何使HTML和CSS代码更易于维护和扩展有充分的了解。
代码样式必备
让我们从良好的HTML和CSS代码的基础开始:W3C有效性, 命名约定, 文件结构等。
从第一天开始就要注意结构。
如果你要开发一个大型应用程序, 则需要注意文件结构。它可以或应该看起来像这样:
使用验证器检查你的代码。
尝试始终使用HTML和CSS验证器。
错误代码:
<figure>
<div>
<img src="demo.jpg" alt="">
<figcaption>
<h2>Hello world</h2>
</figcaption>
</div>
</figure>
<picture>
<source src="demo.webp" type="image/webp">
<img src="demo.jpg" alt="">
</picture>
<details>
<header>
<summary>Expand details</summary>
</header>
<p>All content goes here</p>
</details>
p {
font: 400 inherit/1.125 serif;
}
好代码:
<figure>
<img src="demo.jpg" alt="">
<!-- figcaption should be child of element figure element, not div -->
<figcaption>
<h2>Hello world</h2>
</figcaption>
</figure>
<picture>
<!-- source should have srcset attribute -->
<source srcset="demo.webp" type="image/webp">
<img src="demo.jpg" alt="">
</picture>
<details>
<!-- summary is not allowed as child of header -->
<summary>Expand details</summary>
<p>All content goes here</p>
</details>
p {
font-weight: 400;
font-size: inherit;
line-height: 1.125;
font-family: serif;
}
在<img>标记上使用替代文本以确保简洁的代码原则有效。
此属性对于SEO, 搜索引擎, 网络搜寻器, 屏幕阅读器等至关重要。
错误代码:
<img src="demo.jpg">
好代码:
<img src="demo.jpg" alt="This is placeholder of the image">
使用烤肉架(小包装)。
对于名称, 请尝试使用kebab-case(spinal-case), 而不要使用camelCase或under_score。仅在使用BEM时才使用under_score, 尽管如果使用的是Bootstrap, 则最好保持一致并使用-作为分隔符。
错误代码:
<section class="section_featured_Listing">
<h1 class="largeTitle">H1 title</h1>
</section>
好代码:
<section class="section-featured-listing">
<h1 class="large-title">H1 title</h1>
</section>
kebab-case比camelCase和under_score更具可读性。
使用任何人都可以理解的有意义的名称, 并使其简短。
类的名称应类似于.noun-形容词。
尝试使用类的通用名称, 而不是编写内容特定的名称。它使代码更具可读性
错误代码:
<div class="team-wrapper">
<button class="large-button-green"></button>
<p class="greenText-john-smith-description"></p>
<div class="white-bg"></div>
</div>
好代码:
<div class="section-team">
<button class="btn-lg btn-success"></button>
<p class="text-success"></p>
<div class="bg-white"></div>
</div>
不要在HTML5中为样式表和脚本编写类型属性。
HTML5不需要它们, 但是HTML4 / XHTML中的W3C标准需要它们。
错误代码:
<link type="text/css" rel="stylesheet" href="../styles.css">
<script type="text/javascript" src="..//main.js"></script>
好代码:
<link rel="stylesheet" href="styles.css">
<script src="app.js"></script>
必要时使用特定的类。
保持CSS选择器更具体, 然后选择所需的元素;如有必要, 尽量不要提及父母。它将允许代码更快地渲染并消除将来的任何管理障碍
错误代码:
section aside h1 span {
margin-left: 25%;
}
好代码:
.left-offset {
margin-left: 25%;
}
虽然将类应用于目标元素可能会在HTML中创建更多代码, 但它将允许代码更快地呈现并消除任何管理障碍。
如果要为同一块提供其他样式, 请向父元素添加一个类。
如果需要使用相同的块但样式不同, 请尝试使HTML尽可能保持原样。只需将一个类添加到父元素, 然后将所有新样式应用于CSS中该类的子元素。
错误代码:
<article>
<h1>Same section with another styles</h1>
<p>Lorem ipsum dolor sit amet, lorem sit eget proin id ipsum. </p>
…
</article>
<article class="another-article">
<h1 class="other-styling-title">Same section with another styles</h1>
<p>Lorem ipsum dolor sit amet, lorem sit eget proin id ipsum. </p>
…
</article>
article {
padding: 10px 15px;
h1 {
font-size: 32px;
color: #ff0000;
}
}
.another-article {
padding-bottom: 30px;
border-bottom: 4px solid #ccc;
}
h1.other-styling-title {
font-size: 20px;
}
好代码:
<article>
<h1>Same section with another styles</h1>
<p>Lorem ipsum dolor sit amet, lorem sit eget proin id ipsum. </p>
…
</article>
<article class="other-styling">
<h1>Same section with another styles</h1>
<p>Lorem ipsum dolor sit amet, lorem sit eget proin id ipsum. </p>
…
</article>
article {
padding: 10px 15px;
h1 {
font-size: 32px;
color: #ff0000;
}
&.other-styling {
padding-bottom: 30px;
border-bottom: 4px solid #ccc;
/* you will have less classes */
h1 {
font-size: 20px;
}
}
}
从零值删除单位。
添加该单元是不必要的, 并且没有附加值。 0px, 0em, 0%或任何其他零值之间没有区别。单位并不重要, 因为该值仍为零。
错误代码:
div {
margin: 20px 0px;
letter-spacing: 0%;
padding: 0px 5px;
}
好代码:
div {
margin: 20px 0;
letter-spacing: 0;
padding: 0 5px;
}
如果你可以添加hr标签, 请不要在CSS中写上border-bottom。
使用hr标签, 而不要编写新的选择器并在CSS中添加边框样式。它使代码更加基于标记, 这就是我们想要的。
错误代码:
<p class="border-bottom">I want this section to have a border.</p>
<p>Lorem ipsum</p>
.border-bottom {
border-bottom: 1px solid #000;
}
好代码:
<p>I want this section to have a border.</p>
<hr>
<p>Lorem ipsum</p>
// If necessary change hr variable in bootstrap
使用A> B选择器。
使用A> B选择器非常有帮助, 该选择器仅将规则应用于直接子代(子代), 在这种情况下, 你不必重置所有不需要该子代的其他子代的样式。例如, 在对嵌套菜单进行编码时非常有用。你将不需要重新定义子菜单样式。
错误代码:
<ul>
<li>List 1</li>
<li>List 2</li>
<li>List 3
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
</ul>
</li>
</ul>
ul li {
list-style-type: none;
}
li ul li {
/* redefine to default value */
list-style-type: disc;
}
好代码:
<ul>
<li>List 1</li>
<li>List 2</li>
<li>List 3
<ul>
<li>Submenu 1</li>
<li>Submenu 2</li>
</ul>
</li>
</ul>
ul > li {
list-style-type: none;
}
如何编写干净的HTML
转向HTML, 优先考虑的是确保强大且易于维护的前端。
尝试使前端尽可能基于标记。
使你的前端代码基于标记, 而不是编写过多的CSS。
这将有助于搜索引擎并使你的代码更具可读性, 从而有可能提高搜索排名和用户体验。
错误代码:
<div class="main-content">
<p class="content-title">Main text title</p>
<img src="http://via.placeholder.com/150x150" alt="example">
<p class="image-description">Here is image description</p>
</div>
好代码:
<main>
<h1>Main text title</h1>
<figure>
<img src="http://via.placeholder.com/150x150" alt="example">
<figcaption>
Here is image description
</figcaption>
</figure>
</main>
避免在HTML中使用不必要的包装器。
尽量不要在HTML中使用不必要的包装器元素。拥有吨吨的<div>和<span>元素已经成为过去。保持事物的细化和线性可使你实现最少的代码(请参阅下一点)。
错误代码:
<section class="container">
<div class="row">
<div class="col-xs-12">
<div class="inner-wrapper">
<span>Unnecessary br tags</span>
</div>
</div>
</div>
</section>
好代码:
<section class="container">
<p>Unnecessary br tags</p>
</section>
使用原子类进行样式设置。
不要使用任何自定义颜色或字体大小(如果颜色或字体大小不在框架中, 则只需添加原子类)。原子类是简单的单一用途的样式单位。与内联样式很像, 原子样式仅应用单个样式声明。
错误代码:
<h1>Without using atomic class</h1>
<p>Paragraph without atomic class</p>
<section>
<h1> Another h1 text</h1>
<p>Paragraph inside div without class</p>
</section>
h1 {
color: red;
}
section > h1 {
color: blue;
}
好代码:
<h1 class="text-red">Without using atomic class</h1>
<p>Paragraph without atomic class</p>
<section>
<h1 class="text-blue"> Another h1 text</h1>
<p>Paragraph inside div without class</p>
</section>
.text-red {
color: red;
}
.text-blue {
color: blue;
}
尝试保留粒度和原子类, 并在需要时使用它们。结果, 你的前端将变得更加基于标记。
利用语义元素。
使用语义可以提供更好的结构, 并使代码和内容更易于阅读。
错误代码:
<span class="heading"><strong>Welcome</strong></span>
<span>This is unnecessary br tag.</span>
好代码:
<h1>Welcome</h1>
<p>This is unnecessary br tag.</p>
使用HTML5标签。
新标签为你提供了更多的表达自由, 并可以标准化常用元素, 从而改善了文档的自动化处理。这是所有元素的完整列表。我发现很多开发人员总是使用很多<div>和<span>, 但是首先请在此处检查哪些标签符合你的情况:
错误代码:
<div class="article-blue">
<div class="article-title-red">HTML 4 title</div>
<div class="content">
Semantics
<span class="boldtext">are</span>
important.
</div>
</div>
好代码:
<article>
<h1>HTML5 title</h1>
<p>
Semantics <strong>are</strong> important.
</p>
</article>
底线:学习和使用HTML5中的新元素。值得付出努力!
CSS:干净的代码和预处理器
关于CSS, 很难不从一些非原创但又明智的建议开始:
使用CSS预处理器。
Sass是世界上最成熟, 稳定, 功能最强大的专业级CSS扩展语言。
Sass有两种语法。第一个被称为SCSS(Sassy CSS), 在本参考文献中一直使用, 它是CSS语法的扩展。第二种或更旧的语法称为缩进语法(有时也称为” Sass”), 提供了一种更为简洁的CSS编写方式。
对选择器进行分组:在SASS中使用@extend。
通过对选择器进行分组或在SASS中使用@extend, 你应该有助于使代码保持DRY(不要重复自己)。
错误代码:
p {
font-size: 22px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1 {
font-size: 41px;
color: #000;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
好代码:
.font-smoothing {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
p {
font-size: 22px;
@extend .font-smoothing;
}
h1 {
font-size: 22px;
@extend .font-smoothing;
}
在CSS中使用rem单位而不是像素。
将REM用于大小和间距, 例如, 它根据根<html>元素的字体大小制作的字体大小。它们还允许你通过更改根字体大小(例如, 以特定的媒体查询/屏幕大小)来快速缩放整个项目。
你将为响应式视图编写更少的代码:
错误代码:
p {
font-size: 22px;
padding: 10px;
}
@media (max-width: 767px) {
p {
font-size: 16px;
padding: 5px;
}
}
好代码:
html {
font-size: 14px;
}
@media (max-width: 767px) {
html {
font-size: 12px;
}
}
p {
font-size: 1.6rem;
padding: 1rem;
}
尝试避免CSS中具有固定的高度或宽度。
尝试避免CSS中具有固定的高度或宽度。高度可以通过内部内容+填充生成, 宽度可以通过网格系统定义(必要时使用嵌套网格)。
错误代码:
<footer id="footer" class="text-center">
<h2>Let's Get In Touch!</h2>
<hr>
<p>Ready to start your next project with us?</p>
</footer>
#footer {
height: 130px;
}
好代码:
<footer id="footer" class="text-center">
<h2>Let's Get In Touch!</h2>
<hr>
<p>Ready to start your next project with us?</p>
</footer>
#footer {
padding-top: 23px;
padding-bottom: 47px;
}
确保在SCSS中仅使用一次父项。
当你使用CSS预处理程序并计划为任何部分编写样式时, 请确保仅在CSS中使用父项一次, 并将所有子元素和媒体查询包含在其括号内。将来进行更改时, 这将使你可以轻松地在一个地方查找和修改主要父元素。
错误代码:
.section-parent-class {
position: relative;
h2 {
color: #ff0;
}
header {
margin: 2rem 1rem;
}
}
@media (max-width: 767px) {
.section-parent-class {
footer {
padding: .5rem;
}
}
}
好代码:
.section-parent-class {
position: relative;
h2 {
color: #ff0;
}
header {
margin: 2rem 1rem;
}
footer {
@media (max-width: 767px) {
padding: .5rem;
}
}
}
在编写CSS规则之前, 先考虑哪些元素将受到影响。
在编写任何CSS规则之前, 请务必考虑哪些元素会受到影响。如果你所做的更改不常见, 则编写规则时应仅影响特定元素, 而不会影响其他元素。
错误代码:
/* Commonly used class */
.title {
color: #008000;
}
好代码:
/* Specify it not to affect other titles */
.section-blog .title {
color: #008000;
}
在编写新的CSS规则和变量之前, 请先尝试查找它们。
在自定义CSS和框架中, 始终寻找适合所需样式的现有规则。仅当没有足够的条件时, 才开始编写新的。
在使用大型应用程序时, 这一点尤其重要。
错误代码:
.jumbotron {
margin-bottom: 20px;
}
好代码:
// change $jumbotron-padding from _variables.scss
.jumbotron {
margin-bottom: $jumbotron-padding;
}
使用特定规则。
如果背景具有一个属性, 则可以指定该属性;但是, 如果背景具有不同的背景属性, 则可以为其指定一个声明。
错误代码:
.selector {
background: #fff;
}
好代码:
.selector {
/* This way background image will not be overwritten if there is any */
background-color: #fff;
}
使用速记属性和值。
尽力使用更多速记属性和值。使用简写属性, 你可以编写简明的样式表, 并且往往可以编写更多易读的样式表, 从而节省了宝贵的时间和精力。
错误代码:
img {
margin-top: 5px;
margin-right: 10px;
margin-bottom: 25px;
margin-left: 10px;
}
button {
padding: 0 0 0 20px;
}
好代码:
img {
/* Shorthand style */
margin: 5px 10px 25px;
}
button {
/* Don’t play with shorthand too much */
padding-left: 20px;
}
使用em而不是px作为行高。
使用em和px单位可以使我们灵活地进行设计, 并且可以按比例放大和缩小元素, 而不会被固定大小的卡住。我们可以利用这种灵活性来使我们的设计在开发过程中更容易调整和响应, 并允许浏览器用户控制网站的整体规模以实现最大的可读性。
错误代码:
p {
font-size: 12px;
line-height: 24px;
}
好代码:
p {
font-size: 12px;
line-height: 2em; /* or just line-height: 2; */
}
尽可能使用Bootstrap类。
虽然该规则通常可以应用于UI框架, 但我以Bootstrap为例, 因为它是世界上最受欢迎的前端组件库。
Bootstrap允许你使用很多现成的类, 从而使你的工作更加轻松。尝试尽可能使用Bootstrap类, 以进行更多基于HTML的标记。
错误代码:
<section class="without-bootstrap">
<div class="first-column">Lorem ipsum dolor sit amet, ut ius delenit facilisis</div>
<div class="second-column">Lorem ipsum dolor sit amet, ut ius delenit facilisis</div>
</section>
.first-column, .second-column {
width: 25%;
float: left;
padding-left: 15px;
padding-right: 15px;
}
...
好代码:
<section class="row">
<div class="col-md-6">Lorem ipsum dolor sit amet, ut ius delenit facilisis</div>
<div class="col-md-6">Lorem ipsum dolor sit amet, ut ius delenit facilisis</div>
</section>
正确自定义你的框架。
Bootstrap依赖于variables.scss文件, 该文件使你可以轻松配置和自定义前端, 而无需编写任何代码。否则, 如果你要自己手动编写所有自定义设置, 则最好不要使用任何框架。
一些开发人员避免更改variables.scss, 认为他们仍然可以轻松地将Bootstrap升级到新版本, 但这可能是一项繁琐的任务。即使是较小的更新, 开发人员也需要阅读变更日志, 遍历所有标记和CSS并手动迁移到新版本。
错误代码:
navbar {
padding: 20px 10px;
}
.carousel-indicators {
li {
width: 6px;
height: 6px;
margin-right: 3px;
margin-left: 3px;
}
}
好代码:
$navbar-padding-y: ($spacer / 2) !default;
$navbar-padding-x: $spacer !default;
$carousel-indicator-width: 30px !default;
$carousel-indicator-height: 3px !default;
$carousel-indicator-spacer: 3px !default;
不要覆盖.container的宽度。
尽量不要覆盖.container的宽度。尝试改用网格系统, 或者只更改_variables.scss中的容器宽度。如果需要减小其宽度, 请使用max-width而不是width。在这种情况下, Bootstrap中的.container在响应视图中将保持不变。
错误代码:
.container {
@media (min-width: $screen-lg-min) {
width: 1300px;
}
}
好代码:
// change $container-lg from _variables.scss
.container {
@media (min-width: $screen-lg-min) {
width: $container-lg;
}
}
使用Bootstrap 4类并减少CSS编写。
即使是Beta版, 也要开始使用Bootstrap 4。它包括许多新类, 这些类将帮助你更快地创建布局, 尤其是Flexbox和spacer。
错误代码:
<div class="flex-ex">
<div>Flex item 1</div>
<div>Flex item 2</div>
<div>Flex item 3</div>
</div>
<div class="flex-ex flex-reverse">
<div>Flex item 1</div>
<div>Flex item 2</div>
<div>Flex item 3</div>
</div>
.flex-ex {
display: flex;
> div {
padding: 2px;
}
&.flex-reverse {
flex-direction: row-reverse;
}
li {
list-style: none;
padding: .5rem;
}
}
好代码:
<ul class="list-unstyled list-inline d-flex flex-row">
<li class="p-2">Flex item 1</li>
<li class="p-2">Flex item 2</li>
<li class="p-2">Flex item 3</li>
</ul>
<ul class="list-unstyled list-inline d-flex flex-row-reverse">
<li class="p-2">Flex item 1</li>
<li class="p-2">Flex item 2</li>
<li class="p-2">Flex item 3</li>
</ul>
现在, 我们可以为元素分配类, 以删除所有边界或某些边界。
错误代码:
<div class="border-example2 py-5">
<span class="border0"></span>
<span class="border-top0"></span>
<span class="border-right0"></span>
<span class="border-bottom0"></span>
<span class="border-left0"></span>
</div>
border-example2 {
> span {
width: 100px;
height: 100px;
display: inline-block;
margin: .50rem;
background-color: #e1e1e1;
border: 1px solid;
&.border0 {
border: none;
}
&.border-top0 {
border-top: none;
}
&.border-right0 {
border-right: none;
}
&.border-bottom0 {
border-bottom: none;
}
&.border-left0 {
border-left: none;
}
}
}
好代码:
<div class="border-example py-5">
<span class="d-inline-block m-2 border-0"></span>
<span class="d-inline-block m-2 border-top-0"></span>
<span class="d-inline-block m-2 border-right-0"></span>
<span class="d-inline-block m-2 border-bottom-0"></span>
<span class="d-inline-block m-2 border-left-0"></span>
</div>
.border-example {
> span {
width: 100px;
height: 100px;
background-color: #e1e1e1;
border: 1px solid;
}
}
如果.col-md-X和.col-lg-X的X值相同, 请使用.col-sm-X。
如果.col-sm-X的X值相同, 则不要写.col-md-X和.col-lg-X。例如, 无需编写.col-lg-10, 因为在写时。 col-md-10, 我们会自动在其中添加.col-lg-10。
错误代码:
<ul class="press-list list-inline row">
<li class="col-lg-4 col-md-4 col-sm-4 col-xs-6"><a href="#"><img class="img-fluid" src="assets/images/press/press-1.png" alt=""></a></li>
<li class="col-lg-4 col-md-4 col-sm-4 col-xs-6"><a href="#"><img class="img-fluid" src="assets/images/press/press-2.png" alt=""></a></li>
</ul>
好代码:
<ul class="press-list list-inline row">
<li class="col-md-4 col-xs-6"><a href="#"><img class="img-fluid" src="assets/images/press/press-1.png" alt=""></a></li>
<li class="col-md-4 col-xs-6"><a href="#"><img class="img-fluid" src="assets/images/press/press-2.png" alt=""></a></li>
</ul>
不要使用.col-xs-12。
不要使用.col-xs-12, 因为如果未分配.col-xs-X, 则默认情况下它将是.col-xs-12。
错误代码:
<section id="services">
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<h2>Services</h2>
<h3 class="text-muted">Lorem ipsum dolor sit amet consectetur.</h3>
</div>
</div>
<div class="row text-center">
<div class="col-md-6 col-xs-12">
<h4>E-Commerce</h4>
<p class="text-muted">Lorem ipsum dolor sit amet, consectetur adipisicing.</p>
</div>
</div>
</div>
</section>
好代码:
<section id="section-services" class="text-center">
<div class="container">
<h2>Services</h2>
<h3 class="text-muted">Lorem ipsum dolor sit amet consectetur.</h3>
<div class="row">
<div class="col-md-6">
<h4>E-Commerce</h4>
<p class="text-muted">Lorem ipsum dolor sit amet, consectetur adipisicing.</p>
</div>
</div>
</div>
</section>
不要使用reset.css;请改用normalize.css。
如果你使用的是Bootstrap, 那么normalize.css已经包含在其中, 无需将其包含两次。
即使不是最佳做法, 也要遵循准则。
为了保持一致性, 最好始终遵循你开始使用的规则和准则(无论是关于命名, 代码样式还是文件结构)
本文总结
希望你能够从中受益, 并希望你更多地考虑如何以最佳实践编写最少的HTML和CSS代码。
对于大公司而言, 当代码混乱时, 维护大型应用程序非常困难。当然, 大公司有钱来支付高质量。如果你遵循简洁的编码原则, 则可以提高找到一份好工作的机会。兼顾自由职业者也是值得的:处理多个项目的专业人员, 客户必须提供可以立即传递给其他开发人员的干净代码。
我希望在以后的文章中扩展到更高级的主题, 因为我打算谈论使用Gulp / Grunt任务, Linters, Editor插件, 生成代码的工具, 代替你编写代码的AI工具以及其他自动化编码过程的方法。相关话题。
我希望这是一本有趣且有益的文章。祝你编码工作顺利。