概论
HTML
一、body
的第一个子元素应该是一个容器,它包含各种不需要在页面显示的图标,比如width
、height
样式都为0的分享图,以及其他图标之类的东西。
二、页面正式内容请遵守下面的七级结构,这七级结构已经足以构建最复杂的页面,尤其是在使用了bs的前提下。
三、凡是页面默认不显示,需要触发显示的内容,比如弹出层、飘窗等,应当放到正式内容的后面,单独用容器存储,这样能尽快加载正式内容。
四、表示内容的图片,用img
标签,表示形式的图片,用css背景图。网站LOGO应当用背景图。
五、在每一个块状元素,列表元素和表格元素后,加上一新空白行,以跟其他元素区分开。
六、内联元素尽量写在一行内,这样可以避免空格让元素之间出现缝隙。
CSS
一、嵌套选择器中应当尽量多出现类名,少出现元素名,如果一定要出现元素名,也应出现在最后一级。嵌套选择器尽量用>子选择器,而不是空格后代选择器。嵌套最好不要超过三级,最多四级。
二、响应式css的精髓之一就是隐藏和显示,要善于在小宽度浏览器中隐藏某些组件,然后显示另一些组件。
三、类名应该是语义化的,也就是说,用类名来描述这个元素“是干什么的”,而不是描述它“是什么样子的”。所以,应当少用表象的词,比如left、center、red这种,我不是说不用,而是说要少用,控制在最低。应该多用表意的词,比如alert、danger、large等。
四、类的命名应当遵守统一的规范,目前最流行的规范就是BEM规范,我有专门的文章介绍它:BEM命名法,其实很简单
五、类的命名还应当遵循单一功能原则,单一功能原则规定每个类都应该有一个单一的功能,并且该功能应该由这个类完全封装起来。在CSS中,单一功能原则代表每一段代码、类和模块只做一件事。当我们提交CSS文件时,这意味着每个独立的组件(例如轮播效果和导航栏)都应该有自己的CSS文件。
对于文件的目录结构,可以有两种,一种是以组件为大类,另一种是以文件类型为大类,下面都有举例。用哪种都是可以的,视具体情况而定。
/components
|- carousel
|- |- carousel.css
|- |- carousel.partial.html
|- |- carousel.js
|- nav
|- |- nav.css
|- |- nav.partial.html
|- |- nav.js
/components
|- css
|- |- carousel.css
|- |- nav.css
|- html
|- |- carousel.partial.html
|- |- nav.partial.html
|- js
|- |- carousel.js
|- |- nav.js
六、不要滥用id,id的主要用途有两个:第一个是锚点,第二个是给横切命名。id跟表现无关,id在css里面只用在横切身上。
七、声明顺序
这是一个选择器内书写CSS属性顺序的大致轮廓。这是为了保证更好的可读性和可扫描重要。作为最佳实践,我们应该遵循以下顺序(应该按照下表的顺序):
结构性属性:
display
position, left, top, right etc.
overflow, float, clear etc.
margin, padding
表现性属性:
background, border etc.
font, text
八、并列选择器书写
祖先元素一样的,写在同一行,不一样的,另写一行,比如:
h1,
h2,
h3 {
font-size: 16px;
}
.slide>a, .slide>b {
font-size: 16px;
}
基于Bootstrap,我将页面的正式内容分成七级结构:
第一级:横切(part)
横切是body元素下的单位,它的宽度一般是浏览器的宽度(所以body元素宽度也应该是浏览器宽度),横切高度根据内容实际高度而定。横切的作用是,给HTML代码分最大级别的块,以及给后代元素当祖先元素。
第二级:容器(container)
这个是bs引入的层,我把它放到横切的里面。它只用于控制页面结构。通常一个横切就只包含一个容器,偶尔会包含多个容器。容器的内容宽度就不是浏览器宽度了,肯定比浏览器宽度小。
第三级:行(row)
行也是bs引入的层,是容器内的单位,一个容器内可以有一行,也可以有多行。
第四级:列(colomn)
列也是bs引入的层,也就是div.col-lg-x,是row内的单位,它的宽度一般是N/12(因为栅格结构一般是12列)。一个行内可能有一个列,也可能有多个列。
第五级:区块(block)或者叫组件(Component)
区块是列内的最高单位,是第一个跟内容紧密相关的实体。任何UI组件都是区块,任何相当于一个UI组件的东西都是区块,比如一个ul列表就是一个内容块,一系列的图文块的集合也是内容块,一个form组件是一个区块。
两个区块通常是上下排列,极少数情况两个区块也会左右排列。
第六级:元素组(element-group)
元素组是区块/UI组件的组成单位,比如幻灯组件里面的一系列图片,就是一个元素组,幻灯组件里的若干个小点(或缩略图)又是一个元素组,等等。或者,幻灯组件里面的一个大图加一个小图加一行文字描述组成一个元素组,比如,ul列表里面的一个li元素就是一个元素组,因为li元素中可能包括图片、文字、链接。
注意,元素组不代表只有一层结构,元素组是页面最复杂的结构,可能有多层,是这七层中最难搞的一层,也是一个前端程序员在这七层中最需要熟练掌握的部分。
第七级:元素(element)
基层单位,比如幻灯组件里的大图元素组里的一张大图,就是一个元素,一张缩略图也是一个元素,ul列表里li元素下的a元素就是元素,img元素也是一个元素,一个button元素也是元素。
总结:这七个层级,前四级负责内容呈现的位置、响应式设计等,后三级负责内容本身。
各级的类名命名原则
第一级:横切
横切的类名跟HTML术语有关,比如下图的各种名称,以及适当的其他类似名称来命名,比如banner、belt(腰带)等。有一个惯例是,把相当于页面躯干的部分叫做wrap,因为不能叫body。
下图其实是HTML5新增的标签,这些标签你可以用也可以不用,我个人偏向于只让header、footer、nav用标签,其他用div.xxx写法,因为header、footer、nav表意明确无歧义,其他几个标签不容易直观辨识。强调一下,根据HTML5的规定,nav只表示header下面的那个长条形的导航,如果你的页面还有其他小型导航,不要用nav标签。
第二级:容器、第三级:行、第四级:列
它们自带类名,所以不需另写类名。
第五级:区块
区块类名以内容含义命名,比如网站logo,可以叫header-logo,也就是横切名加含义的写法。比如一个幻灯区块,类名就可以叫wrap-slide,表示wrap横切里面的一个幻灯组件。
第六级:元素组
元素组的类名一般是“区块名-元素组名”,比如幻灯组件里有一系列缩略图,那么包裹这套图的容器就是元素组,它的类名可以是slide-thumbnails。
第七级:元素
元素的类名,可以遵守著名的“BEM命名法”,也就是说,将区块名、元素名、修饰符加在一起,就是元素级的类名。当然也可以不写类名,用嵌套选择器声明。
另外
另外,适当的使用嵌套选择器,可以减少类名。你应当适量使用嵌套选择器,以及适量使用类名选择器,不要偏向某个极端。嵌套选择器不应该超过三级,最多四层,也就是最好a>b>c,极限是a>b>c>d,不要再多。
用Emmet表示我推荐的层级结构
div.global-partname>div.container>div.row>div.col-lg-6.col-md-7>div.blockname>div.elementgroupname>element
展开得到
<div class="global-partname">
<div class="container">
<div class="row">
<div class="col-lg-6 col-md-7">
<div class="blockname">
<div class="elementgroupname">
<element></element>
</div>
</div>
</div>
</div>
</div>
</div>
横切的命名示例
我推荐的一个命名示例是:
div.#icon //-->用于存放各种LOGO和ICON
header //-->LOGO、网站项目名(比如文章、图库、论坛等)和登陆组件等
nav //-->本项目的导航条
wrap //--> 躯干
footer //-->页脚
div.#fixed //--> 各种漂浮、弹窗等