每次写 html 结构涉及到 CSS 命名时,都要挣扎一番。关于 CSS 命名的规范,市面上有不少,如 OOCSS、SMACSS、BEM 和 MVCSS 等。在这里面最火的应该算 BEM 了。本文将详细介绍 CSS 命名
【BEM】
说起 CSS 命名,当然要提到 BEM。BEM 的意思就是 B 模块 (block)、E 元素 (element)、M 修饰符 (modifier)。模块和子元素之间用两个下划线分隔,子元素和修饰符之间用两个中划线分隔
关于子元素 E,有两种写法。一种是按照层级嵌套来写,如
,但是这样写会导致命名过长;另一种是扁平化,一个模块 B 下的所有子元素,无论相互层级如何,都直接连接 B,如
- block-ele1-son-inner
,但是这样就无法表示层级关系,命名时也可能会出现冲突
- block-inner
BEM 的命名是很好的,不然也不能成为最流行的命名方法。但是,BEM 对子元素的命名,无论是层级长命名还是扁平化短命名,都有缺陷
【NEC】
相较于 BEM 以模块 B 为顶级元素,子元素类名中包含继承关系的命名,网易的 NEC 规范使用后代选择器方式
NEC 将元素分为了 5 类:布局 (grid)(.g-);模块 (module)(.m-);元件 (unit)(.u-);功能 (function)(.f-);皮肤 (skin)(.s-);状态 (.z-)。而后代选择器不需要完整表现结构树层级,尽量能短则短
- .m - list {
- margin: 0;
- padding: 0;
- }.m - list.itm {
- margin: 1px;
- padding: 1px;
- }.m - list.cnt {
- margin - left: 100px;
- }
个人认为,网易对于元素分类的做法很好。关于一些全局可复用的功能性的模块进行区分,结构更为清晰。但是,对于使用后代选择器的方式,个人不太认同。当嵌套层级较深时,命名冲突依旧是一个问题
【JD】
京东的命名规则采用表示层级嵌套关系的长命名。当子孙模块超过 4 级或以上的时候,考虑在祖先模块内具有识辨性的独立缩写作为新的子孙模块
- <div class="modulename">
- <div class="modulename_cover">
- </div>
- <div class="modulename_info">
- <div class="modulename_info_user">
- <div class="modulename_info_user_img">
- <img src="" alt="">
- <!-- 这个时候 miui 为 modulename_info_user_img 首字母缩写-->
- <div class="miui_tit">
- </div>
- <div class="miui_txt">
- </div>
- ...
- </div>
- </div>
- <div class="modulename_info_list">
- </div>
- </div>
- </div>
京东这种因子元素名字过长而采用首字母缩写的做法非常赞,至今市面上没有其他更好的解决长命名的方案
【后代选择器还是类名】
关于 CSS 命名,最大的争论就是使用后代选择器还是使用类名。以下例所示
- <ul class="list">
- <li class="list-item">
- </li>
- <li class="list-item">
- </li>
- <li class="list-item">
- </li>
- </ul>
- <ul class="list">
- <li class="item">
- </li>
- <li class="item">
- </li>
- <li class="item">
- </li>
- </ul>
- <ul class="list">
- <li>
- </li>
- <li>
- </li>
- <li>
- </li>
- </ul>
如果采用第一种长类名的方式,为 <li> 元素设置样式,只需如下设置即可
- .list - item {}
如果采用第二种短类名的方式,则为 <li> 元素设置样式,需如下设置
- .list.item {}
如果采用第三种后代选择器的方式,则为 <li> 元素设置样式,需如下设置
- .list li {}
如果从简易角度来看,第三种后代选择器的方式最简单,无需花时间去给子元素起名,且在 sass 中书写很容易
- .list {
- li {}
- }
但是,它有一个很严重的问题,就是如果 HTML 结构层级较深,往往出现选择器层级过长,如. list li span a{}
而且,因为后代选择器强烈地依赖 HTML 结构,为了避免因为少写一层结构,导致选择器特殊性降低,样式无法生效的情况,也不得不这样写
一个不得不提的问题是,CSS 选择器的解析顺序是从右到左。而使用后代选择器. list li{},浏览器需要遍历出所有的 li,再找出. list 下的 li,效率是最低的
因此,个人认为第三种后代选择器的方式并不是好选择
下面介绍第二种短类名的方式
1、选择器解析效率比第三种方式好,毕竟. item 比 li 的范围小很多
2、短类名. list .item 同样存在依赖 HTML 结构的情况,很可能出现选择器层级过长
3、使用较简易,在 sass 中书写容易,且起名也较简单
4、由于给 li 增加了类名,于是增加了 HTML 文件大小
最后介绍第三种长类名的方式
这种方式的选择器效率最高,因为. list-item 这个类型页面中只出现一次,可类比于 id 选择器的解析速度
由于使用长类名的方式,可以完全不使用后代选择器,则无需考虑选择器特殊性较低,样式无法生效的情况,也不会出现选择器层级过长,因为它仅有一级
但是,相应地,它最大的缺点是类名较长,大大地增加了 HTML 文件大小。于是,可借鉴京东,当子孙模块超过 3 级时,采用首字母缩写,并将缩写后首字母大写的做法,在如将. list-item-link-title 缩写为. Lil-title
最终,选择可缩写的长类名作为 CSS 命名的主要方式
【分隔符】
一般地,classname 分隔符有 3 种,中划线 -,下划线_,以及首字母大写,以分隔 list 和 item 为例
- //中划线
- list - item
- //下划线
- list_item
- //首字母大写
- listItem
1、中划线
中划线可以用来表示层级关系
- <div class="box">
- <ul class="box-list">
- <li class="box-list-item">
- </li>
- <li class="box-list-item">
- </li>
- <li class="box-list-item">
- </li>
- </ul>
- </div>
2、下划线
下划线可以用来表示不同的状态
- <div class="box">
- <button class="box-btn box-btn_default" type="button">
- </button>
- <button class="box-btn" type="button">
- </button>
- </div>
3、首字母大写
首字母大写可以用来表示因为样式的需要,而不得不增加的 HTML 结构。一般地,如果在外层增加结构,可以增加 Wrap,在内层增加结构,可以增加 Inner,且不影响原先的 classname 的命名
- <div class="boxWrap">
- <section class="box">
- <h2 class="box-title">
- </h2>
- <p class="box-content">
- </p>
- </section>
- </div>
【组件】
通过上面的长命名方式和分隔符的使用,解决了基础结构的命名。但是,在页面中,很可能出现一些组件的应用,这些组件可以复用到页面的多个位置。这时,再使用上面的方式就不太合适
于是,可以以 m - 为前缀,来表示这是一个组件
- <div class="box">
- <button class="m-btn m-btn_error" type="button">
- </button>
- <button class="m-btn" type="button">
- </button>
- </div>
有了合适的命名方式,还需要语义化命名,且有不影响语义的情况下,可以简写
【布局】
- 文档doc头部header(hd)主体body尾部footer(ft)主栏main侧栏side容器box / container
【通用部件】
- 列表list列表项item表格table表单form链接link标题caption / heading / title菜单menu集合group条bar内容content结果result
【组件】
- 按钮button(btn)字体icon下拉菜单dropdown工具栏toolbar分页page缩略图thumbnail警告框alert进度条progress导航条navbar导航nav子导航subnav面包屑breadcrumb(crumb)标签label徽章badge巨幕jumbotron面板panel洼地well标签页tab提示框tooltip弹出框popover轮播图carousel手风琴collapse定位浮标affix
【语义化小部件】
- 品牌brand标志logo额外部件addon版权copyright注册regist(reg)登录login搜索search热点hot帮助help信息info提示tips开关toggle新闻news广告advertise(ad)排行top下载download
【功能部件】
- 左浮动fl右浮动fr清浮动clear
【状态】
- 前一个previous后一个next当前的current
- 显示的show隐藏的hide打开的open关闭的close
- 选中的selected有效的active默认的
- default反转的toggle
- 禁用的disabled危险的danger主要的primary成功的success提醒的info警告的warning出错的error
- 大型的lg小型的sm超小的xs
- <header class="hd">
- <nav class="hd-navbar m-navbar m-varbar_primary">
- <div class="hd-navbar-tel">
- 联系方式:400-888-8888
- </div>
- <ul class="hd-navbar-nav">
- <li class="Hnn-itm m-btn m-btn_info">
- <a href="#">
- 登录
- </a>
- </li>
- <li class="Hnn-itm m-btn">
- <a href="#">
- 快速注册
- </a>
- </li>
- <li class="Hnn-itm m-btn">
- <a href="#">
- 关于
- </a>
- </li>
- <li class="Hnn-itm m-btn">
- <a href="#">
- 帮助
- </a>
- </li>
- </ul>
- </nav>
- ...
- </header>
关于 CSS 命名,并没有最佳实践之说,根据项目的复杂程序进行合适的命名才是可取的
欢迎交流
来源: http://www.cnblogs.com/xiaohuochai/p/7173867.html