【第1346期】如何更好的编写CSS
前言
这篇不会很复杂,基础篇。今日早读文章由@JeLewine翻译分享。
正文从这开始~
废话不多说,咱们就开门见山吧:想写出优质的CSS代码将会是非常痛苦的。很多开发者都不想做CSS开发。我可以做你想做的一切,但是,除了CSS!
当我在构建应用时,CSS是我挺讨厌的部分。但你无法摆脱它,对吧?我的意思是,正是因为我们如此的专注于用户体验和设计,所以现在我们才不能跳过这一部分。
在开始一个项目时,一切都很正常。你有一些CSS选择器:.title input #app,这看起来非常的简单。
但是当你的应用变得越来越大时,它就开始变的越来越糟糕了。你对CSS选择器感到困惑。你发现你写的像div#app .list li.item a诸如此类的东西,自己在一遍又一遍地在重复相同的代码。你把所有代码都放在文件末尾,因为你根本就不在乎。CSS像一坨shit。然后你要狗带了:500行的CSS完全没法维护。
我今天有一个小目标:让你更好的去编写CSS。我想让你回首看看自己的旧项目并发出感慨:oh,boy,我怎么能写这么一坨东西?
好吧,你可能会想,你说的有道理。但是CSS框架呢?这就是他们的用法,不是吗?这就是我们编写好CSS代码的方法。
是的没错,不过这样还是会有一些缺点:
它往往会带来平凡的设计
想要定制或跳出CSS框架会变的困难
在使用它们之前,你必须先学习它们
不过毕竟,你已经开始在看这篇文章了。这一定是有原因的,不是吗?所以,不用多说了,让我们开始学习如何更好的编写CSS吧。
注意:这不是关于如何设计优雅应用程序的文章。它是关于学习如何编写和组织可维护的CSS代码的。
SCSS
在这篇文章里我将会用SCSS作为例子。
SCSS是一个CSS的预处理器。简单来说,它是一个CSS的超集:他为CSS添加了一些很酷的功能,例如变量,嵌套,导入和mixins。
我将先谈谈我们立即会使用到哪些功能。
变量
通过SCSS,你可以使用变量了。它带来的主要好处就是可复用性。我们假设你的应用有一组颜色。你的主色调是蓝色。
所以你的应用到处都是蓝色:按钮的背景颜色,标题的颜色,链接。蓝色无处不在。
突然之间,你不喜欢蓝色。你更喜欢绿色了。
没有变量:更改所有使用了蓝色的地方
使用变量:只需更改变量
// 声明变量
$primary-color: #0099ff;
// 引入变量
h1 {
color: $primary-color;
}
嵌套
你还可以使用SCSS来嵌套代码。看一下下面的例子:
h1 {
font-size: 5rem;
color: blue;
}
h1 span {
color: green;
}
可以变成下面这样:
h1 {
font-size: 5rem;
color: blue;
span {
color: green;
}
}
更具有可读性,不是吗?使用嵌套来编写复杂选择器所花费的时间更少。
局部文件和引入
出于可维护性和可读性方面的考虑,我们不可能将所有代码保存在一个大文件中。在试验或构建小型应用程序时,这么做也许可以满足你的需求,但在更专业的情况下…请不要这么做。不过幸运的是,SCSS允许我们这样做。
您可以通过使用前置下划线命名文件的方式来创建局部文件:_animations.scss,_base.scss,_variables.scss等。
至于引入,我们可以使用@import命令。例如,下面这样是你可以做的:
// _animations.scss
@keyframes appear {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
// header.scss
@import "animations";
h1 {
animation: appear 0.5s ease-out;
}
看到这里,你可能会认为这里是不是搞错了。应该是_animations.scss而不是animations。
不。当你用这种方式命名时,scss可以很聪明的知道你正在讨论一个局部文件。
以上就是我们所需要了解到的变量,嵌套,局部文件和引入。SCSS还有一些其他功能,像是mixins,继承指令(@for,@if,…)之类的,不过我今天不会在这里介绍他们了。
如果你想了解更多的信息,可以查看他们文档。他们写的很不错,非常容易理解。
组织CSS代码:BEM方法论
我已经记不清有多少次在我的CSS课程里用到这些名称了。你懂的:.button,.page-1,.page-2,.custom-input。
我们其实经常不知道该如何去命名。然而这是非常重要的。如果你正在构建一个应用程序,并且由于某些原因决定将其搁置几个月,该怎么办?或者更糟糕的是,如果有人要交接该项目怎么办?如果你的CSS代码没有一个正确命名,那么很难一目了然地知道你在说什么。
BEM帮我们解决了这个问题。BEM是一种命名约定,代表着块元素修饰符【译者注:原文为Block Element Modifier。在中文前端圈内发现大部分文章都将block直译为”块”,其实译者个人觉得翻译为”模块”可能会让人更好理解一点。不过本文还是选择和已有译法保持一致】。
这种方法可以使我们的代码结构化,更加模块化和可复用。现在让我来解释什么是块,元素和修饰符。
块
我们可以把“块”视为组件。你还记得小时候玩的乐高积木吗?【译者注:小时候没玩过,现在我也玩不起…】ok,让我们回到过去。
你会如何建造一个简单的房子?你需要一个窗户,一个屋顶,一扇门,一些墙壁,就是这样。那些是我们的块。他们各自有各自的作用。
命名:块名称:.block样例:.card,.form,.post,.user-navigation
元素
现在,你将如何用你的乐高去搭一个窗户呢?这发现其中也许有一些看起很像边框,当你把四个边框组装在一起时,一个窗户就搭好啦。那就是我们的元素。它们是“块”的一部分,它们是构建“块”的必要条件。但是,当它们离开块时就没有用了。
命名:块名称 + _ + 元素名:.block_element
样例:.post_author,.post_date,.post_text
修饰符
现在你已经搭起了一个窗户,不过也许你想要的是一个绿色的或小的。这些就是修饰符。它们是“块”或“元素”上的标志,它们用于改变行为和表现等。
命名:块名称或元素名 + - + 修饰名:.block_element-modifier, .block-modifier
样例:.post-important,.post_btn-disabled
一些笔记
当您使用BEM时,你为类命名,也只能是为类命名。没有ID,没有标签。只有类。
块/元素可以嵌套到其他块/元素中,但它们必须要能完全独立。记住这个词:独立。因此
请不要因为你想将按钮放在标题下就将margin写在按钮上,否则您的按钮将与您的标题完全绑定。请改用其他公用类来代替这个操作。
是的,你的HTML文件将会过载。但不要担心,与BEM带给您带来的好处相比,这是一个小小的缺点。
一个例子
下面是一个对你的小练习。转到你最喜欢或最常用的网站,并尝试使用BEM。
例如,下面就是我在Google商店中的想象:
轮到你了。要保持好奇人们如何可以做的更好。你必须自己去搜索,尝试和创造,这样才能更好的贴合你自己的需求。
将它们合在一起
你会发现下面的一些例子充分的展示了BEM的功力。
<!--html-->
<div class="post">
<span class="post__author">Thomas</span>
<span class="post__date">3 minutes ago</span>
<p class="post__text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laboriosam sit voluptatem aut quis quisquam veniam delectus sequi maxime ullam, inventore blanditiis quia commodi maiores fuga, facere quaerat doloremque in. Nisi! </p>
</div>
<div class="post mt-large post--important">
<span class="post__author">Thomas</span>
<span class="post__date">2 hours ago</span>
<p class="post__text">
Voluptatem incidunt autem consequatur neque vitae aliquam, adipisci voluptatum. Ipsum excepturi dolores exercitationem rem ab similique consequatur nesciunt, tempora aut vel unde. </p>
</div>
<!--SCSS-->
.post {
display: inline-block;
padding: 1rem;
background-color: #ccc;
border: 1px solid #222;
border-radius: 5px;
&--important {
background-color: yellow;
}
&__author {
font-size: 1.2rem;
font-weight: bold;
color: blue;
}
&__date {
float: right;
}
&__text {
line-height: 2rem;
font-size: 1.3rem;
}
}
<!--html-->
<div>
<button class="btn">
Click me </button>
<button class="btn btn--danger">
Danger </button>
<button class="btn btn--success">
Success </button>
<button class="btn btn--small">
Small </button>
<button class="btn btn--big">
Big </button>
<button class="btn btn--border">
Border </button>
</div>
<!--SCSS-->
.colors {
font-size: 1.5rem;
font-family: sans-serif;
}
.btn {
background-color: #FF6B93;
color: #fff;
text-transform: uppercase;
padding: 1.5rem 2.5rem;
border-radius: 4px;
transition: all .2s;
font-size: 1.3rem;
border: none;
letter-spacing: 2px;
cursor: pointer;
&:hover {
background-color: #D15879;
}
&:focus {
outline: none;
}
&--danger {
background-color: #FF3B1A;
&:hover {
background-color: #D43116;
}
}
&--success {
background-color: #00D123;
&:hover {
background-color: #00AB1D;
}
}
&--small {
padding: 1rem 2rem;
font-size: 1rem;
}
&--big {
padding: 1.8rem 4.5rem;
font-size: 1.7rem;
}
&--border {
background-color: #fff;
color: #FF6B93;
border: 1px solid #FF6B93;
&:hover {
background-color: #FF6B93;
color: #fff;
}
}
}
组织CSS文件:7-1模式
你坚持看到这儿了?优秀! 现在让我们看看如何组织CSS文件。这部分将真正帮助你提高工作效率,并能够让你立即找到必须要修改的CSS代码的位置。
为此,我们将了解7-1模式。
你可能会想这是个什么玩意【译者注:711便利店?233】。
相信我,这很简单。你只须遵守下面2条规则:
将所有的局部文件写入7个不同的文件夹中。
将它们全部导入位于根级别的一个main.scss文件中。
就是这样。
7个文件夹
base:在这里,把所有的脚手架代码都放进去。通过脚手架,我指的是每次启动一个新项目时要写的所有CSS代码。例如:排版规则、动画、公用(公用类,我指的是margin-right-large,text-center,……之类的类)。
components:这里的名称是明确的。此文件夹包含用于构建页面的所有组件,如按钮,表单,swipers,弹出窗口等。
layout:用于布局页面的不同部分。也就是说,页眉,页脚,导航,自己的网格等等。
pages:你有时可能会有一个页面会具有一些自己特定的样式。将它们与那些通用的样式分开,然后将它们放在pages文件夹中。
themes:如果你的应用有不同的主题(黑暗模式,管理员模式等),请将它们放在此文件夹中。
abstracts:将所有函数与变量和mixin一起放在这里。
vendors:现在有什么项目是没有依赖外部库的?在vendor文件夹中放入所有不依赖于你的文件。你可能希望在此处添加Font Awesome文件,Bootstrap和类似的东西。
主文件
在这里导入你所有的partials。
@import abstracts/variables;
@import abstracts/functions;
@import base/reset;
@import base/typography;
@import base/utilities;
@import components/button;
@import components/form;
@import components/user-navigation;
@import layout/header;
@import layout/footer;
...
是的。这看起很庞大。不过我知道你会这么想,这种架构适用于更大的项目,而不是小的。这里有一个适用于较小项目的版本。
首先,你不需要vendors文件夹。只需将所有外部CSS代码放置在头文件中的链接标签中即可。然后你可以跳过themes文件夹,因为你的应用可能只有一个主题。最后,你的页面不会有很多特定的样式,所以你也可以跳过pages这个页面。太好了,只剩下4个文件夹了!
接下来,你又两个选择:
你希望你的CSS代码组织遵循7-1模式,因此你保留了abstact、components、layout和base。
你更喜欢有一个大文件夹,把所有的局部文件和你的main.scss文件放在一起。所以你会产生以下类似的东西:
sass/
_animations.scss
_base.scss
_buttons.scss
_header.scss
...
_variables.scss
main.scss
这完全取决于你自己。
你把我说服了!但是我该怎么用呢?我的意思是,浏览器并不支持SCSS,不是吗?
说的好!现在到了我们的最后一步了。我们将学习如何将SCSS文件编译成CSS。
从SCSS到CSS
为此,你需要先安装Node.js和NPM(或Yarn)
我们将使用一个名为node-sass的包,它能够帮我们将.scss文件编译为.css文件。
它的CLI(命令行界面)相当容易使用:
node-sass <input> <output> [options]
node-sass提供了多种选项,不过我们只需要两个就够了:
-w: 观察目录或文件。这意味着node-sass能够观察到代码中的任何更改。一旦更改发生时,它会自动编译为CSS。 这在开发时非常有用。
—output-style:CSS文件的输出模式是什么。它可以是以下值之一:nested|expanded|compact|compressed。我们将使用它来构建你的CSS文件。
如果你是一个有好奇心的人(我希望你是,开发人员应该保持好奇!),可以到这里查看完整的文档。
现在我们已经知道了我们将使用哪些工具。接下来的事就非常简单了。只要跟着下面的步骤走:
创建你的项目:mkdir my-app && cd my-app- 初始化:npm init- 添加node-sass库:npm install node-sass —save-dev- 创建你的文件夹,你的index.html和你的main.scss文件:
touch index.html
mkdir -p sass/{abstracts,base,components,layout} css
cd sass && touch main.scss
修改在package.json中你的脚本命令:
{
...
"scripts": {
"watch:scss": "node-sass sass/main.scss css/style.css -w",
"build:scss": "node-sass sass/main.scss css/style.css --output
style compressed"
},
...
}
将包括那些已编译的CSS文件的引用链接添加到你的index.html文件的head标签中:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8">
<meta name=”viewport” content=”width=device-width, initial-scale=1.0">
<meta http-equiv=”X-UA-Compatible” content=”ie=edge”>
<link rel=”stylesheet” href=”css/style.css”>
<title>My app</title>
</head>
<body>
<h1 class=”heading”>My app</h1>
</body>
</html>
就这样,已经可以跑起来了!当你开始coding并在浏览器中打开index.html时,记得运行npm run watch:scss。如果你想要压缩你的css文件,跑一下npm run build:scss就好了。
添加热更新
你可能在开发中更希望通过热更新来提高效率,而不是每次都要手动重载index.html文件。
只要跟着以下几个简单的步骤:
安装live-server包:npm install -g live-server。注意:这是一个全局包
添加npm-run-all包到你的项目依赖中:npm install npm-run-all —save-dev。它能够让你同时运行多个脚本命令。
添加下面的命令到package.json中:
{
...
"scripts": {
"dev": "npm-run-all --parallel liveserver watch:scss ",
"liveserver": "live-server",
"watch:scss": "node-sass sass/main.scss css/style.css -w",
"build:scss": "node-sass sass/main.scss css/style.css --output-style compressed"
},
...
现在,当你运行npm run dev时,你可以立即看到你的修改,而且无需手动重载任何内容。太棒了,不是吗?
不过你知道更棒的是什么吗?为了方便你快速上手,我为此建了一个repo。
如果你想要知道我是如何将这些技巧应用到我的项目中的,可以查看这个repo。这里是演示结果。我希望你可以通过这个例子拥有更深的理解。
这就是今天要说的一切!现在,你已经做好了编写可维护,模块化和可复用的CSS代码的准备。
关于本文
译者:@eLewine
译文:
https://zhuanlan.zhihu.com/p/40326332
作者:@Thomas Lombart
原文:
https://medium.freecodecamp.org/how-to-get-better-at-writing-css-a1732c32a72f
最后,为你推荐