让我们开门见山: 编写优秀的 CSS 代码是件十分痛苦的事情. 很多开发人员都不想做 CSS 开发. 你让我干什么都行, 但是 CSS 还是算了吧.
前端 560 集视频学习资料需要的 + web 前端扣扣裙: 939106847 领取
在我创建应用的时候, 从来都无法从 CSS 中享受到乐趣. 但是你也躲不过去, 是不是? 我是说, 我们全神贯注于用户体验, 但是如今设计也是不容忽视的部分.
项目刚开始的时候, 一切都很美好. 你有一些 CSS 选择器, 诸如 .title,input,#App 等等, 非常简单. 但是随着应用逐渐变大, CSS 也越来越糟. 你对 CSS 选择器感到困惑. 你会发现自己写了一些 div#App .list li.item a 之类的东西. 然后你一遍又一遍地写相同的代码. 最后你把所有代码都扔到文件末尾, 因为你根本不在乎, CSS 烂透了. 结果你得到了 500 行根本无法维护的 CSS 代码.
我本人经常和 CSS 苦苦纠缠.
今天目的是: 让你写出更好的 CSS. 我想让你回顾一下旧项目, 然后想一想: 天啊, 我怎么会写这样的东西? 但是, 你可能会想: 好, 你说的很对, 但是 CSS 框架呢? CSS 框架就是为了帮助我们写出更好的 CSS 代码, 不是吗?
当然, 但是 CSS 框架也有一些缺点:
它经常会使用平淡无奇的设计.
CSS 框架使得定制很困难, 更不用说超越框架了.
在使用之前, 你必须先学习如何使用它们.
既然你关注了这篇文章, 那么你一定有自己的原因, 对不对? 好了, 废话不多说, 让我们开始学习如何写出更好地 CSS 代码.
注意: 这篇文章不是关于如何设计漂亮的应用. 本文是关于如何写出便于维护的 CSS 代码以及如何组织代码.
1. SCSS
将在下面例子中使用 SCSS.SCSS 是一个 CSS 的预处理器. 从根本上来说, 它是一个 CSS 的超集: 它增加了一些很酷的功能, 例如变量, 嵌套, 导入和混入 (mixins) 等.
下面介绍一些我们即将使用的功能.
变量
你可以在 SCSS 中使用变量. 主要的好处在于可重用性. 我们假设你的应用有一组颜色. 主色是蓝色.
那么你处处都用到了蓝色: 按钮的 background-color(背景色), 标题和链接的 color(颜色). 蓝色无处不在.
突然有一天, 你不喜欢蓝色, 开始喜欢绿色.
如果没有变量: 你需要修改所有包含蓝色设置的代码.
如果使用了变量: 你只需要修改这个变量.
// Declare a variable$primary-color: #0099ff; // References a variableh1 { 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 还有很多其他功能: 比如混入, 继承和其他指令(@for,@if, 等等), 在此不做一一介绍了.
前端 560 集视频学习资料 + 教程 限时免费分享
需要的转发文章 + 私信小编 "资料" 领取
2. 组织 CSS 代码: BEM 方法论
我记不清曾经多少次在 CSS 类中使用包揽一切的名字了. 比如:..button.,..page-1.,..page-2.,..custom-input..
我们常常不知道如何命名. 然而命名很重要. 假如你正在构建某个应用, 并且由于某种原因不得不将其搁置数月, 那该怎么办? 还有更糟的, 假如有人想把项目拿回去, 该怎么办? 如果你的 CSS 代码没有恰当的命名, 那么乍一看上去很难明白你在说什么.
BEM 可以帮助我们解决这个问题. BEM 是一种命名约定, 是英文 Block Element Modifier(块元素修饰符)的缩写.
这种方法可以使我们的代码结构化, 并提高模块化和可重用性. 现在让我们说一说什么是块, 元素和修饰符.
块
你可以把块视为组件. 还记得你小时候玩过乐高积木吗? 让我们回忆一下小时候.
如果需要建造一个简单的房子, 你会怎么做? 你需要一个窗户, 一个屋顶, 一扇门和一些墙壁. 这些就是我们的块. 它们有着本身的意义.
命名: 块名:.block
示例:.card,.form,.post,.user-navigation
元素
接下来, 你应该如何用你的乐高积木建造一个窗口呢? 可能有些积木看起来像框架, 如果你把四个这样的积木组装起来, 就会得到一个漂亮的窗户. 这些就是我们的元素. 它们是块的一部分, 它们对于建块必不可少. 但是, 在块外面的时候, 它们便无用武之地.
命名: 块名 + __ + 元素名:.block__element
示例:.post__author,.post__date,.post__text
修饰符
现在窗户已经建好了, 但是你可能想要一个绿色或一个小窗户. 这些我们称之为修饰符. 它们是块或元素上的标志, 它们用于改变行为, 外观等等.
命名: 块名称或元素名称 + -- + 修饰符名称:.block__element-- 修饰符,. 块 -- 修饰符
示例:.post--important,.post__btn--disabled
注意事项
在使用 BEM 的时候, 你可以用且只能用类来命名. 不能用 ID, 不能用标签. 只能用类.
块和元素可以嵌入其他块和元素, 但是它们必须是完全独立的. 请记住: 独立. 所以如果你想将把一个按钮放在标题下的话, 就不要在按钮上加边距, 否则按钮就会与标题绑定. 请改用工具类.
是的, 你的 html 文件会超负荷, 但是不用担心, 与 BEM 带来的好处相比, 这只是个小小的缺点.
示例
以下是一个练习. 你可以去你最喜欢或最常用的网站, 然后想想看哪些是块, 元素和修饰符.
例如, 以下是我想象中的 Google 商店:
Google 商店
现在该你了. 认真想想哪些地方可以改进. 与往常一样, 你必须自己搜索, 实验和构件, 以便更好地满足你的需求.
融会贯通
下面的示例演示了 BEM 的功能.
BEM 的功能
写一个博文组件
博文组件
写多个按钮
3. 组织 CSS 文件: 7-1 模式
你还跟得上节奏吗? 很好! 现在让我们来介绍如何组织 CSS 文件. 这个部分可以真正帮助你提高工作效率, 并帮助你立刻找到需要修改的 CSS 代码.
为此, 让我们了解一下 7-1 模式. 你可能会想, 我从未听过这种模式. 相信我, 这很简单. 你必须遵守以下两条规则:
将所有内容分别写入 7 个不同的文件夹中.
将它们全部导入位于根级别的 main.SCSS 文件中. 仅此而已.
7 个文件夹:
base: 你可以将所有的样板代码放入该文件夹中. 对于这里的样板, 我指的是: 每次开始一个新项目时, 你需要写的所有 CSS 代码. 例如: 排版规则, 动画, 工具程序 (对于工具程序, 我指的是 margin-right-large,text-center,... 等类) 等等.
components: 这里指组件. 这个文件夹包含所有用于构建页面的组件, 例如按钮, 表单, 滑块, 弹出窗口等等.
layout: 页面不同部分用到的布局, 也就是说: 页眉, 页脚, 导航, 分区, 你自己的网格等等.
pages: 页面. 有的页面可能有特定的样式, 与通常的处理方式不同. 那么你可以将它放入该文件夹.
themes: 主题. 如果你的应用中有不同的主题(黑暗模式, 管理员等等), 那么可以将它们放入该文件夹.
abstracts: 抽象. 你可以将所有函数和变量与混入 (mixin) 放在这里. 简而言之, 就是你所有的帮手.
vendors: 外部资源. 应用或项目怎么可能没有外部的库呢? 你可以将所有不依赖于你的文件都放入该文件夹. 例如, 你可以放入 Font Awesome 文件, Bootstrap 和其他类似的东西.
主文件
你需要将以上所有内容导入到该文件中.
- @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 代码放在头部的 link 标签内. 接下来, 如果你的应用只有一个主题的话, 可以省略 themes 文件夹. 最后, 你可能不会有大量页面特定的风格, 所以也 pages 也没必要. 好了, 现在只剩下 4 个文件夹了.
然后, 你有两个选择:
你可以按照 7-1 模式组织 CSS 代码, 那么你需要留下 abstracts,components,layout 和 base 文件夹.
你想将所有的分块文件和 mail.CSS 放在一个大文件夹内, 那么你会得到如下结构:
- Sass/
- _animations.SCSS
- _base.SCSS
- _buttons.SCSS
- _header.SCSS
- ...
- _variables.SCSS
- main.SCSS
你可以随便选.
你可能会想: 你说服了我! 但是我该如何使用呢? 我是说, 哪些不支持 SCSS 文件的浏览器该怎么办呢? 说的好! 这是我们的最后一步, 我们现在就来学习如何将 SCSS 编译为 CSS.
4. 从 SCSS 到 CSS
首先, 你需要 Node.JS 和 NPM(或 Yarn).
我们将使用一个名为 node-Sass 的包, 它可以让我们将 .SCSS 文件编译为 .CSS 文件.
它的 CLI(命令行界面)相当容易使用:
node-Sass [options]
它有多个选择, 但我们只使用其中两个:
-w: 监视目录或文件. 这意味着 node-sasswaits 在时刻监督你的代码是否发生改动, 一旦出现发生, 它就会自动编译成 CSS. 这在开发时非常有用.
--output-style:CSS 文件的输出内容. 它的值可以是: 嵌套, 展开, 紧凑, 压缩. 我们将使用它来构建你的 CSS 文件.
如果你是一个好奇心很重的人 (我希望如此, 因为开发人员应该好奇!) 那么, 请点击这里查看 完整的文档.
现在我们知道需要用哪些工具. 其余的工作更简单. 只需按以下步骤操作:
创建项目: mkdirmy-App && cd my-App
初始化: NPM init
添加 node-Sass 库: NPM install node-Sass --save-dev
创建文件夹, index.HTML 和 main.SCSS 文件:
touch index.htmlmkdir -p Sass/{abstracts,base,components,layout} csscd Sass && touch main.SCSS
将这些脚本加入到 package.JSON 文件中:
- {
- ...
- "scripts": {
- "watch": "node-sass sass/main.scss css/style.css -w",
- "build": "node-sass sass/main.scss css/style.css --output-style compressed"
- },
- ...
- }
将包含编译好的 CSS 文件的连接加入到 index.HTML 文件的 head 标签内:
My App
My App
然后就可以了, 你准备好了! 你可以在编程的时候运行 NPM run watch, 并在浏览器中打开 index.HTML 文件. 如果你想缩小 CSS, 只需运行 NPM run build.
5. 补充
添加实时重新加载
你可能希望添加实时重新加载以提高工作效率, 而无需手动重新加载本地 index.HTML 文件.
你可以按照以下简单的步骤操作:
安装 live-server 软件包: NPM install -g live-server. 注意: 它是一个全局包.
将 NPM-run-all 添加到项目依赖项中: NPM install NPM-run-all --save-dev: 有了它我们就可以同时运行多个脚本.
将这些脚本添加到 package.JSON:
- {
- ...
- "scripts": {
- "start": "npm-run-all --parallel liveserver watch",
- "liveserver": "live-server",
- "watch": "node-sass sass/main.scss css/style.css -w",
- },
- ...
- }
现在如果你运行 NPM run start, 就可以立即看到代码的变更.
添加自动前缀
我们设置好了开发工具, 太棒了! 现在, 让我们来谈谈构建工具, 特别是: 自动前缀(Autoprefixer).
它是一个工具 (尤其是 postcss 插件), 它可以解析 CSS, 并利用这些值(https://caniuse.com/) 将提供商的前缀加入到 CSS 规则中.
实际上, 在构建网站时, 你可能会使用一些并非所有浏览器都完全支持的新功能. 因此, 提供商方案可以提供对这些功能的支持. 以下是一个示例:
- -webkit-animation-name: myAnimation;
- -moz-animation-name: myAnimation;
- -ms-animation-name: myAnimation;
你可能会想, 这写起来太乏味了. 这就是为什么我们需要自动前缀来帮助我们的 CSS 代码获得浏览器的兼容, 而不用增加额外的复杂性.
那么我们如何用更聪明地构建 CSS 呢?
将所有的 SCSS 文件编译成一个主 CSS 文件.
使用自动前缀为 CSS 文件添加前缀.
压缩 CSS 文件
还有最后几步, 请坚持看下去, 马上就结束了.
添加两个依赖项, postcss-cli 和 autoprefixer:NPM install autoprefixer postcss-cli --save-dev
修改 build 脚本, 并将这些脚本添加到 `package.JSON:
- {
- ...
- "scripts": {
- "start": "npm-run-all --parallel liveserver watch",
- "liveserver": "live-server",
- "watch": "node-sass sass/main.scss css/style.css -w",
- "compile": "node-sass sass/main.scss css/style.css",
- "prefix": "postcss css/style.css --use autoprefixer -o css/style.css",
- "compress": "node-sass css/style.css css/style.css --output-style compressed",
- "build": "npm-run-all compile prefix compress"
- ...
- }
现在当你运行 NPM run build 时, 可以生成经过压缩的 CSS 代码, 并且添加了提供商前缀! 太棒了是不是吗? 但是你知道更酷的是什么吗? 这里为你设置了一个代码仓库, 以帮助你迅速开始:)
如果你想知道我是如何在项目中应用这些技术的, 请点击这里查看 代码仓库 和 结果. 希望你能通过这些例子更深入理解. 现在, 你可以准备开始编写具有可维护性, 模块化和可重用性的 CSS 代码了.
小伙伴们, 加油!!!
前端 560 集视频学习资料 + 教程 限时免费分享
需要的转发文章 + Web 前端扣扣裙: 939106847 领取
来源: http://www.jianshu.com/p/08f75420e9ad