javascripty已经走上工程化的道路了,各种mvm,mvvm框架已经让人目不暇接了,这里就不讨论js了。我来讲下我在实际工作中编写CSS的一些经验吧,当然很多人也总结过这样的经验,我说的肯定没有哪些大牛写的好,我只是简单的把自己的工作经验拿出来与大家分享下。
工欲善其事,必先利其器
在编写css的时候,你需要至少掌握一个开发工具,无论是SASS,还是LESS,本质上来说他们一样的,只是语法有点不一样。如果你还是在纯手写css,那么请尽快了解它们,并根据自己的习惯选择其中一个并使用他们。个人而言,我比较喜欢sass,更符合我的书写习惯。也有很多人喜欢Less,他们觉得less语法更加便捷。
什么SASS/LESS
SASS(LESS)是CSS3的一个扩展,增加了规则嵌套、变量、混合、选择器继承等等。通过使用命令行的工具或WEB框架插件把它转换成标准的、格式良好的CSS代码。
为什么需要SASS/LESS
它们作为一个开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护。
它们也是编写模块化、可维护的CSS的基石。
该如何使用
网上关于SASS/LESS的教程一大堆,我这里不浪费篇幅写基本语法了。
推荐几个学习他们的网址,它们都差不多,学了一个基本都可以使用了:
SASS
- SASS中文文档
- SASS用法指南-阮一峰
- SASS入门
LESS
- LESS中文网
- LESS入门
下面的内容我用SASS举例,内容不限于SASS,LESS同样适用!
神说,无规矩不成方圆
是的,无规矩不成方圆,你需要了解一种css命名规范或者制定自己的规范(不建议自定义,不利于团队合作);
为什么需要有一种命名规范呢?
当你编写过大量css时候,你就发现没有一种有效的命名规范会让你痛不欲生。如果你在一个稍微大一点的项目中,或者在与其他人合作开发的过程,这种感觉特别明显。因为当你为css命名的时候会发现这个命名在别的地方使用了,或者队友已经使用过了,你必须重新命名。久而久之,css的命名就会杂乱无章而且又臭又长,一眼望去根本猜不到这个命名的意义。
BEM命名规范
各种命名规范是仁者见仁,智者见智,在这里我介绍下BEM命名规范,我介绍的不一定就是适合你的,你需要自己思考何种命名规范适合自己。。
BEM是由Yandex团队提出的一种CSS Class 命名方法,旨在更好的创建CSS/Sass模块。
BEM的意思就是块(block)、元素(element)、修饰符(modifier)。
- block: 可以理解为一个区域、一个组件或者一个块级元素,具体如何区分需要根据实际情况具体分析;
- block__element: 就是一个上面的block里面的元素,比如说导航(nav:block)里面有a标签(a: element)就是一个元素, block与element使用两个下划线链接;
- block__element--modifier: 我的理解是状态或属性。比如element里面的a标签,它有active、hover、normal三种状态,这三种状态就是modifier。midifier是使用两个“--”中横线连接
就上面所说的例子我用实际的代码来示范下:
// SASS写法
.nav{
&__item{
&--active{
}
&--hover{
}
&--normal{
}
}
}
/* 编译后的css */
.nav{ }
.nav__item{ }
.nav__item--active{ }
.nav__item--hover{ }
.nav__item--normal{ }
从上面的例子可以一眼看出css的含义,而且编译后的css没有任何的嵌套,但是SASS的结构却很清晰,一目了然。
由此可见,使用SASS配合BEM可以写出一份易读、可维护、模块化的代码;
神说,需要介绍
一份可读性的SASS必须有一份说明,一个文件,一个函数都需要一份说明。
对于一份SASS文件,你至少需要说明两点,这份SASS是公用还是私有、哪个页面哪个部分
@charset "utf-8"
/*
* 预定义函数
* author:xxx
* time:xxxx-xx-xx
*/
/*
* 清除浮动
* use: @include clearfix();
*/
@mixin clearfix(){
*zoom: 1;
&:before,
&:after {
content: "";
display: table;
}
&:after {
clear: both;
overflow: hidden;
}
}
神说,世界要统一
- reset
css reset必不可少,网上有很多css reset的代码,compass也有reset的module,只需要@import “compass/reset”。如果你觉得这些代码太冗余,太多,你至少需要保证你的css有margin和padding的reset,这样才可以保证在各个浏览器中css有相同的样式。
*{
margin: 0;
padding: 0;
}
- border-box
*{
box-sizing: border-box
}
建议border-box,更好的计算box宽高。
神说,要有variables(变量)
一份可维护的SASS,首先需要有一份variables,这是提高开发效率基础,也是确保页面一致性的基石。
什么是variables
variables就是说你需要在编写SASS前定义一份变量表,将项目需要用到的一些基本的样式通过变量保存起来。
举个例子来说:
你拿到一个项目的设计稿,在编写CSS之前,你需要快速浏览设计稿,找出其中相同的元素(没有必要很详细,先将视线能分辨的元素用变量保存起来,其他的可以在以后使用的再添加)。
那么问题又来了,什么是相同元素呢?
- 间距/行距/边距
- 字号
- 颜色
- 层级
- 高度
- ……
为什么需要variables
使用一份单独的variables,好处很多,最大的好久就是可维护性,谁用谁知道!
可维护性
- 等你开发完了,拿给设计师验收,设计师说这里不好,换个颜色!—— 没事,我改个变量!
- 产品说,这里不好,列表间距太大了,小屏幕只显示那么一点点!—— 没事,我改个变量!
- 来来来,产品说我们换一套皮肤! —— 没事,我重新定义一份变量!
- ……
这些例子可以让你明白有一份variables是多么重要了吧。其实这些只是在可维护方面的好处。作为一名前端,我们是最接近用户的工程师,我们不能仅仅停留在代码层面,更需要的是站在用户体验的角度思考问题,而variables可以让我们有一套规范,确保页面一致性。
一致性
FE是面向用户的,我们需要对用户负责。设计师在设计页面的时候,不能所有的像素的都很精确,不可能每次的颜色都是毫无差错的。所以在这时候,就需要规范了,如果设计师没有规范,那我们自己制定一套规范。例如:
- 同一个项目,一个页面的列表高度是20px,另一个页面的列表是21px,这时我们无需理会,直接使用我们之前定义的列表高度进行开发。
- 同一个页面,有两个error的颜色#dc4c4c和#d84a4a,我们也无需理会,使用统一的error颜色变量;
这些是用户体验的细节,通过一份variables可以让我们保持页面的一致性。
这里只是略微提下用户体验,之后我再写一篇《前端工程师必须重视的用户体验》来详细讲解下用户体验。
module(模块化,基于SASS/LESS)
模块化在js中经常听到,对于css来说,模块化对于易读性和可维护性同样重要。那么如何来做模块化呢?
多文件夹
建立多个文件夹,分类存放sass文件。例如:将variables、mixin、公共样式、私有样式分成多个文件夹存放;
多文件
同一个文件夹的sass可以按模块、功能等等分成多个文件,最终用@import 导入
这样说的有点粗糙,我举个例子吧(下划线开头的sass文件不会编译单独css文件)
——sass
——config //基本变量
——mixin //函数
——common //公用
——header
——aside
——_list.scss
——_nav.scss
——_base.scss
——compoment //组件样式
——dropdown
——lightbox
——page
——index //首页
——_ad.scss //广告样式
——_content.scss //内容信息
——_info.scss //个人信息样式
——_base.scss //index样式,@import 'ad';@import 'content';@import 'info';
——write
——preview
——_aside.scss //preview页面独有侧边栏
——about
——main.scss //导入所需要的样式,最终生成一个main.css
如上面所示的目录结构,能让人一目了然sass的目录的结构,维护的时候可以快速准确的找到文件。
如果是多页面的项目,也可以最大限度复用代码,而且可以导出公用样式,利用缓存提高加载速度,不用每个页面都重复写一样的代码。
注意:common文件夹的公共样式必须是其他页面所共有的样式,如果有些页面有特殊的样式,应该将会覆盖的css抽取出来,在页面中分别导入不同的私有样式。
根据命名规则限定使用样式
比如说preview页面有一个私有aside样式,可以在这样写preview里面的_aside.scss:
@charset "utf-8"
/*
* 预览页面侧边栏
* author:xxx
* time:xxxx-xx-xx
*/
@import '../../common/aside/base'
.preview{
.aside{
/* css */
&__item{
/* css */
}
}
}
这里需要注意的是,css覆盖会导致重新渲染,影响性能。
原文链接