Github: https://github.com/nzbin/snackDocs: https://nzbin.github.io/snackcss
这篇文章我已经酝酿了半年之久,或者说拖沓了这么久吧。想说的东西不少,却又无从提及。现在轻量级框架如雨后春笋,层出不穷。我想每一个人都应该概括总结工做中的常见需求,编写一套适合本身的 CSS 框架。在以前的文章中,我提到了面向对象的 CSS(好比 BEM、OOCSS、SMACSS,详见 http://vanseodesign.com/css/d...)。这是一种思想,并不涉及具体的 CSS 问题,主要是类命名的策略!如今仍然有不少人对于前端框架的认识还停留在表面,认为 Bootstrap 是后端人员专用,前端不必等等。我不知道这种说法从何而来,我最开始也不喜欢使用框架,或许和不少人的想法同样,畏惧新知识、惧怕难以驾驭、遇到问题的时候没法解决等等。最关键的一点是不少人认为框架的样式是固定的,修改起来太麻烦,还不如本身根据设计图写起来方便。html
为何使用框架?答案显而易见,效率。除此以外,使用框架或者研究框架的意义还有不少,好比面向对象思想的具体实现。在上一家公司工做的时候,开始的几个项目我也是用最原始的方法书写 CSS 。项目之中最让我头疼的就是类的命名。我想大多数人都是根据功能去命名,这就形成了不少的冗余,相同的组件可能写不少次。简单举一个例子,以下图,我的中心的登陆界面。前端
不少人包括我刚开始的时候可能会选择下面的类命名及布局方式,其通用性很是差node
<div class="login-area"> <div class="login-img"> <img src="..." /> </div> <div class="login-text"> <a href="...">请点击登陆</a> </div> </div>
然而了解 Bootstrap 的人应该一眼就发现上图就是一个 media 对象,无非一些小细节须要调整一下git
<div class="media"> <div class="media-left"> <img src="..." /> </div> <div class="media-body media-middle"> <a href="...">请点击登陆</a> </div> </div>
为了让文字与图片居中对齐,咱们可使用 Bootstrap 的 .media-middle
的辅助类。若是在工做中还要根据需求自定义一些辅助类调整细节,固然这是一个移动端的例子,能够选择移动端框架相关的 media 对象。github
另外,在项目改版的时候,原始的方法的修改更是惨不忍睹,能够说是噩梦,冗长的 CSS 文件、混乱的功能划分、类名、色值等等。最后也只能硬着头皮一点一点修改。那一刻我才体会到框架的意义以及前端工具的重要性。我从工做中总结出,要么你能够熟练的使用某一个框架,要么就本身实现一个框架。npm
目前市面上前端框架主要分重量级与轻量级。重量级主要有 Bootstrap、Semantic、UIkit、Foundation 等,轻量级有 Pure、Skeleton、Miligram 等。常常关注前端动态的工程师会发现轻量级框架每一年都层出不穷。在我上面提到的主流轻量级框架以外还有不少相似的框架。我一直问本身,为何要重复造轮子。通过研究,我发现这些轻量级框架其实大多都不能胜任工做需求,并且模仿的痕迹很重,基本上都或多或少的有 Bootstrap 的影子。那么这些轻量级框架有没有意义呢?固然有。可是就我我的观点,选择轻量级框架反倒不如本身实现一个框架。由于大多轻量级框架就像是工做总结,是根据本身的业务需求实现的。因此大多不具备通用性。后端
前端框架的对比主要以 Bootstrap、Semantic、UIkit 为主,由于我我的感受这三个最具备表明性,并且设计风格各有特点。Foundation 也有不少大公司在用,但以我我的观点,不管是框架的易用性仍是设计风格,相比其它几个框架稍逊一筹。sass
其中 Bootstrap 和 Semantic 是面向对象的最好体现。前端框架
我先说一下 Bootstrap 的优点,不是设计风格,不是模块,不是特效,而是栅格,响应式栅格。Bootstrap 的栅格在与其它框架对比中占有绝对优点,不管是栅格的划分仍是类名的风格都堪称经典。若是读者有心看一下 Bootstrap 的 Less 源文件,就会感觉到 Bootstrap 对于响应式栅格的独具匠心。其实在 Bootstrap 以前也有不少栅格方案,可是给人的感受就是不够利索,类名繁琐很差记。然后来的不少框架,尤为轻量级的框架大多都有 Bootstrap 的影子。
下面咱们经过对比几个框架的栅格和按钮来看一下类命名的策略。
Bootstrap
<div class="row"> <div class="col-md-8"></div> <div class="col-md-4"></div> </div> <button class="btn btn-primary" type="submit">Button</button>
Semantic
<div class="ui grid"> <div class="ten wide column"></div> <div class="six wide column"></div> </div> <button class="ui primary basic button">Primary</button>
Foundation
<div class="row"> <div class="small-3 columns"></div> <div class="small-9 columns"></div> </div> <button type="button" class="primary button">Primary</button>
UIkit
<div class="uk-grid"> <div class="uk-width-1-2"></div> <div class="uk-width-1-2"></div> </div> <button class="uk-button uk-button-primary" type="button">Primary</button>
Pure
<div class="pure-g"> <div class="pure-u-1-2"></div> <div class="pure-u-1-2"></div> </div> <button class="pure-button pure-button-primary">A Primary Button</button>
经过上面的对比,你们应该已经发现了这些框架的命名策略的不一样。不能否认,Bootstrap 的命名最经典。
以前在网上看到有人讨论关于框架的易用性,有人说 Bootstrap 的类名太长,然而经过上面几个框架的对比,Bootstrap 的类并不繁琐,并且用预处理器编写框架时嵌套会比较灵活。
Semantic 的类名最简洁,经过多个定语的修饰组成一句话,确实颇有意思。可是过多的修饰类在编写框架时会稍显凌乱,有利有弊,因人而异吧。
Foundation 的栅格应该是最丰富的,策略上相似 Bootstrap,只是对公共属性进行了拆分,你们也能够看看其中的具体细节。
UIkit 和 Pure 的策略相同,都加了前缀以区分其它框架,可是很显然类名过于冗长了。我在编写框架时也这样想过,可是最终放弃了这种方式。
CSS 预处理器早已不是什么新鲜事,可是真正可以在工做中运用的人有多少呢?熟练使用预处理器特性的人又有多少呢?
我以前工做的时候也没有用预处理器,由于不用,因此也意识不到预处理器的好处。主要是以为麻烦,由于要使用编译器编译一下,还不如直接写 CSS 方便。可是在项目维护的时候就意识到预处理器的好处。后来在几个项目中尝试了预处理器,可是对于模块化的写法不太明确。预处理器做为工具,能够实现模块化编写 CSS,那么应该如何划分模块?另外,预处理器有不少特性,可是大多数人刚开始只用到变量和嵌套,其它的特性几乎不多用到。我相信在本身动手实现一个轻量级框架的过程当中,咱们能够对预处理器有一个全面的了解。
目前流行的预处理器有 Less,Sass,Stylus 三个,选择哪一个彻底是看本身的习惯。我最开始由于 Bootstrap 了解的 Less,可是由于习惯选择了 Sass,其次 Sass 的功能要更全面一些。
不管是工做仍是本身写项目,都要搭建一个项目环境,也就是安装一系列的 npm 包。相比刀耕火种的开发方式,使用工具开发的前期准备过程稍显麻烦,然而一旦环境建好,后期的开发将会游刃有余。
Miligram 这个轻量级框架在 Github 上有很高人气,可是说实话,用处并不大。不过这个框架的构建方式很是值得学习。虽然 CSS 对于不少人来讲很简单,可是真要去写一个框架,仍是很是棘手,这时候就须要借鉴一些优秀的框架。
编写框架大体会用到的 npm 以下:
--autoprefixer --node-sass --npm-run-all --rimraf --onchange
其实最主要的就是一个 node-sass,其它的都是辅助 CSS 文件的生成修改,你们感兴趣的话能够去 npm 官网搜索这些插件,了解具体用法,若有不懂能够给我留言,我就不啰嗦了。
终于到了本篇文章的重头戏。
简单介绍一下,我给本身编写的框架取名 Snack,原意“快餐”,主要表达简单之意。虽然是轻量级框架,但我并不想拿轻量级作为噱头,毕竟体量轻意味着某些功能的缺失以及疏漏。这个框架的意义更多的是交流学习,我试图借鉴其它框架的优秀之处,尽可能简化类名,以及尝试探索一些更通用的组件。
大多数的轻量级框架只是 CSS 框架,不涉及 JS 部分,主要用于网页的布局。我之因此打算本身编写框架,是由于工做中重复的东西太多,经过框架能够很好的将这些零散组件整合到一块儿。另外一方面,写个小项目,学点新知识是一件趣事。
编写框架是去年想作的事情,但由于时间缘由,拖了好久。写框架之初我曾陷入一个误区,我打算设计一些比较前卫的样式,立体的按钮、浮动的面板等,好比下图中的风格。
https://dribbble.com/shots/524593-Soft-Interface-Black
可是在断断续续编写框架的过程当中,我逐渐找到了方向,上图的样式只是一种皮肤,编写框架之初不该该把重点放在这上面。固然,好的 UI 设计也是框架成功的一部分。
编写框架的第一步就是要肯定框架应该包含哪些模块。由于是轻量级框架,因此模块确定没有重量级框架那么全面,只有核心的一些组件。经过比较一些轻量级框架以及工做总结,大体经常使用的模块包括栅格、媒体、按钮、排版、表单、表格、面板以及辅助工具。
在经常使用的这几个组件中,须要重点关注的是栅格、表单及面板,媒体组件也很重要,可是自由发挥的空间不大,我直接用了 Bootstrap 的媒体组件。
首先是类命名的层次与结构。类命名一直是我比较纠结的地方,刚开始工做的时候为了起一个见名知意又简洁的类名老是抓耳挠腮。我在编写框架时尽可能避免与 Bootstrap 的类名重叠,但也不能彻底避免。对比其余框架会发现,这种状况不可避免的会出现,毕竟类名会有必定的规律性以及层次性。在这一点上我比较喜欢 Bootstrap 的风格。下面和 Bootstrap 的表单作一个对比。
Bootstrap 的表单结构及类名
--div.form-horizontal --div.form-group --label.control-label --input.form-control
Snack 的表单结构及类名
--div.form-horizontal --div.form-item --label.form-label --input.form-field
这个表单结构总体而言还算不错,只是个别地方须要修改。有一些框架不给 input
等元素起类名,而是给父元素一个类名,我的对这种作法表示疑问,不起类名会下降框架编写及使用的灵活性。
第二个策略是组件的修饰,好比按钮及面板都存在多个语境(颜色、大小等),在这一点上我编写框架时作了一些简化,风格上有些 Semantic 的影子。
<button class="btn primary">primary</button> <table class="table bordered striped">...</table> <div class="boxes primary">...</div>
关于修饰类的策略是一个仁者见仁智者见智的问题,至于哪一种方法更好,还须要在编写框架的过程当中摸索。
演示示例: https://nzbin.github.io/snack/#grid
任何框架必须创建在栅格的基础上才能灵活布局。我在前面提到了 Bootstrap 的精华就是栅格系统。栅格系统的编写须要使用预处理器的循环功能,不然就要作无谓的重复劳动了。我遇到过一些轻量级框架是用 Less 编写的,其栅格系统就没有用循环,这样的源码稍显唐突,多是做者对 Less 的循环功能不熟,固然 Less 自己的循环比较弱,用起来有些别扭。关于预处理器的循环,能够参照我以前翻译的《CSS 预处理器中的循环》,比较详细地对比了三种流行预处理器的循环功能。简单说一下,Less 没有循环,但能够用递归实现,而 Sass 和 Stylus 有真循环。
我编写的栅格系统也是默认 12 列,可是后来发现 12 列的栅格缺乏最经常使用的列宽(好比 10%、20%、30%等),好比下面 CodePen 展现的例子用 12 列栅格是没法完成的,因此我又添加了 10 列栅格,但仍然没法面面俱到,不过已经很灵活了。
See the Pen snack-grid
栅格的使用和 Bootstrap 是同样的,除了 12 列栅格外,10 列栅格以及均分栅格都要添加 .cols-
类
<!-- 默认 12 列栅格,因此省略 cols-12 --> <div class="row"> <div class="col-5"></div> <div class="col-7"></div> </div> <!-- 10 列栅格 --> <div class="row cols-10"> <div class="col-3"></div> <div class="col-7"></div> </div>
这个栅格并无响应式,只有一个断点,小屏手机上的话全部栅格都会单行显示。一方面,这样的设计符合大多数轻量级框架的初衷;另外一方面,我打算再写一个针对移动端的框架,毕竟 Web 端和移动端的风格差距较大,按照业务需求分开会更好。不过最近我更改了源文件,为响应式预留了扩展方式。
演示示例: https://nzbin.github.io/snack/#forms
在上面的命名策略中已经展现了 Snack 表单的基本结构,基本表单除告终构以外,样式上并无太多能够讨论的地方。在此说一下表单中 checkbox
的结构调整,先看一下 Bootstrap 的 checkbox
结构。
<!-- checkbox --> <div class="checkbox"> <label> <input type="checkbox" value=""> checkbox </label> </div> <!-- checkbox-inline --> <label class="checkbox-inline"> <input type="checkbox" id="inlineCheckbox1" value="option1"> checkbox </label>
以上两种结构不能有误差,稍有误差样式就会错乱,灵活性较差。其次我在想两种结构能不能整合在一块儿,加强灵活性。想了好久,找到了方法,Snack 结构以下:
<!-- checkbox --> <div class="checkbox"> <label> <input type="checkbox" value=""> checkbox </label> </div> <!-- checkbox-inline --> <div class="checkbox inline"> <label> <input type="checkbox" value=""> checkbox </label> </div>
也能够将样式直接加到 label
标签上。另外,若是将 input
移到 label
标签外也是没有问题的,以下:
<!-- checkbox --> <div class="checkbox"> <input type="checkbox" id="checkbox1" value=""> <label for="checkbox1">checkbox</label> </div> <!-- checkbox-inline --> <div class="checkbox inline"> <input type="checkbox" id="inlineCheckbox1" value=""> <label for="inlineCheckbox1">checkbox</label> </div>
这种结构有一个好处,就是能够自定义 input
样式,详见下面的 CodePen 的 scss
文件。radio
的设置和 checkBox
是同样的。
See the Pen snack-forms
辅助类是一系列类的组合,好比字号大小、颜色值、padding、margin 以及左右浮动等。在一些 Bootstrap 搭建的后台管理系统中尤其常见,这样布局起来就会比较灵活。如下是一个边框的辅助类。
.border-left-right { border-left: 1px solid #eee; border-right: 1px solid #eee; } .border-top-bottom { border-top: 1px solid #eee; border-bottom: 1px solid #eee; } .border-left { border-left: 1px solid #eee; } .border-right { border-right: 1px solid #eee; } .border-top { border-top: 1px solid #eee; } .border-bottom { border-bottom: 1px solid #eee; }
关于辅助类的更多内容能够阅读这篇文章《如何编写通用的 Helper Class》
演示示例: https://nzbin.github.io/snack/#boxes
盒组件是我整个框架中比较满意的一个模块。之因此要作这个组件主要是以为 Bootstrap 的 list 组件和 panel 组件能够整合到一块儿。固然,这样的作法有利有弊。盒组件在后台管理系统的布局中表现的尤其突出。其命名也是多种多样,好比 panel、widget、portlet、ibox、card等,每一个后台管理系统框架都会对这个组件进行深度开发,可见其在布局上的重要性。给一个组件起一个合适的类名也很关键,想了好久,最后用了 box
的类名,固然通常状况下尽可能不要用 box
,由于这个类名比较宽泛。下面的 CodePen 模拟了 Bootstrap 的 list 及 panel 组件。
See the Pen snack-boxes
给框架添加主题是一件有趣的事情。Snack 的默认主题是白色,由于喜欢黑色,最后添加了暗夜主题,编写主题只需改变组件的颜色。演示文档 的页面用了暗夜主题,点击上方的红色按钮能够切换主题。
若是你们问我那个框架更好,我会绝不犹豫的选择 Bootstrap。在工做中能够根据需求的难易进行框架选择,若是业务比较重,最好根据 Bootstrap 进行二次开发;反之,能够选择一些轻量级框架,最好仍是根据本身的需求造轮子,若是你们愿意选择或是借鉴个人框架,那会是个人荣幸。