本文由大漠根据Krasimir Tsonev的《Starting to Write CSS》所译,整个译文带有咱们本身的理解与思想,若是译得很差或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://davidwalsh.name/starting-css,以及做者相关信息javascript
——做者:Krasimir Tsonevphp
——译者:大漠css
你不要以为CSS没什么重要可言?最近几年他成为一个热门的话题,不少人都在讨论他。CSS并非一个简单的事情,前端开发者可使用他将页面制做的更佳漂亮。看得更远一些,咱们更关心的是网站的性能以及如何制做出更好的网站。在本文中,我想分享我最近几个月的学到的有关于CSS编码的知识。做为一个程序员,我真正感兴趣的事情是框架(Architectural
)部分。我以为写CSS应该须要去改变,为此我深挖了不少知识。我搜索了好的程序、工做流和原则。这篇文章将带领你们和CSS一块儿旅行,不少人都说写CSS并非编程,我就不一样意,我说写CSS一样是有趣的,富有挑战性的。html
让咱们一块儿面对吧,在世界上写CSS并非一件好笑的事情。CSS预处理器看起来就像CSS,但他更像一个魔术师同样,使用一些魔法会产生有效的CSS代码。这让你的样多和浏览器之间新增长了一层,这样不是更加的糟糕吗?看上去是这样,但事实不是这样的,由于CSS预处理器提供了一些真正有用的特性。前端
我认为最有价值的东西是链接你的文件。我相信,你知道使用@import
来引用你的.css
文件,告诉浏览器获取这个文件。这样作,浏览器须要增长一个请求,这样有点麻烦,由于你可能有不少个这样的文件。增长额外的请求,使你的程序性能变得更低。若是您使用CSS预处理器语言,这个问题将不会存在。他们只会编译你样式文件中单个.css
文件。java
LESS和Sass是最主要的两个CSS预处理器。咱们都支持扩展。虽然他们的工做方式略有不一样,但他们的想法是同样的。你能够作一个基本的类(一般称为mixin
)和一群属性,而后在另外一个选择器导入这些属性,如:node
// less .bordered(@color: #000) { border: dotted 2px @color; } .header { .bordered; } .footer { .bordered(#BADA55); } // 编译出来的CSS .header { border: dotted 2px #000000; } .footer { border: dotted 2px #bada55; }
这里的问题是,若是你没有定义一个参数的mixin
,例如刚才的示例:git
.bordered { border: dotted 2px #000; }
这是最后编译的CSS文件,不管你是否使用都没有任何关系。由于他是一个有效的选择器。在Sass中咱们能够作得更灵活一些。他有混合(mixins
)、扩展(extends
)和占位选择器(placeholders
)(若是您想看到他们之间的区别,我强烈建议您阅读这篇文章)。接下来咱们简单看看Sass是如何工做和编译的:程序员
// sass @mixin bordered($color: #000) { border: dotted 2px $color; } .header { @include bordered; } .footer { @include bordered(#BADA55); } //编译的CSS .header { border: dotted 2px black; } .footer { border: dotted 2px #bada55; }
它看起来和前面几乎相同,但若是咱们秋看第二个placeholder
的用例:github
// sass %bordered { border: dotted 2px #000; } .header { @extend %bordered; } .footer { @extend %bordered; } // 编译的CSS .header, .footer { border: dotted 2px #000; }
这个有两个优点,首先不会编译出.bordered
类名,其次会使用组合选择器,合并相同的样式,使代码变得更加简洁。
LESS和Sass都支持变量,你能够调用这些变量,将将他们做为属性的值:
// sass $brand-color: #009f0A; ... h1 { color: $brand-color; }
这是一个很好的特性,由于你能够储存一些重要的东西,好比说颜色或者网格的宽度,将他们存放在同一个地方,若是你须要修改一些不常常改动的代码,会变得很是的简便。
另外一个好处理,可使用变量的插值,以下面演示的方法:
// sass @mixin border($side) { border-#{$side}: solid 1px #000; } .header { @include border("left"); } // 编译的CSS .header { border-left: solid 1px #000; }
.less
或.sass
文件,可是输出是什么很是重要。你可能有写得很好的Sass代码,但这并不意味着,你最终会有很好的CSS代码。可能会有一些特异性的问题,因此须要按期检测编译的版本。好的,我找到了一个新的好玩工具。这个预处理器能够节省大量的时间,但他不能为你写出好的结构。首先,我开始考虑是一个命名约定,让咱们来看如下的HTML标签:
<header class="site-header"> <div class="logo"></div> <div class="navigation"></div> </header>
可能会写出对应的样式:
.site-header { ... } .logo { ... } .navigation { ... }
这样的样式能正常的工做,但它有一个问题——阅读CSS,让人难于理解。例如,logo
是属于header
部分的,你可能有另外一个logo
要放在页脚footer
处。那么将添加一个后代选择器来控制:
.site-header .logo { ... }
可是使用这些选择器并非很好的主意,由于它始终须要依赖于特定的标记和结构。一旦你把logo
移到<header>
外面,样式将会丢失。另一种作法是给logo
添加一个site-header
,给其从新命名:
.site-header-logo { ... }
很棒了,本身就是说明,但它并不能运用于全部状况之下。例如,我想在12的圣诞节使用一个圣诞节版本的logo
。因此,我不能写:
.site-header-logo-xmas { ... }
由于个人逻辑是,写一个选择器要像嵌套HTML标签同样匹配。
BEM可能解决这样的状况。这意味着块(Block)、元素(Element)和修改器(Modifier)和一些建立规则,你能够遵循这些规则。使用BEM,咱们的小例将变成:
.site-header { ... } /* block */ .site-header__logo { ... } /* element */ .site-header__logo--xmas { ... } /* modifier */ .site-header__navigation { ... } /* element */
也就是说site-header
是咱们的块。那么logo
和navigation
是这个块的元素,圣诞版本的logo
是修饰符。也许它看起来简单,可是它真的很强大。一旦你开始使用它,会发现他能让你的结构更加的优秀。固然也有反对的理由,那就是由于其语法。是的,或许看起来有点丑,但为了有一个好的结构,我会准备为此作出牺牲。(更好的阅读请点这和这)。
自从我发现BEM,我就开始在思考如何正确的使用个人类名。也许,个人第一件事情要读一篇关于面向对象的CSS。面向对象编程添加了一些抽像的概念,CSS也支持这样的概念。若是你使用了CSS预处理器,你或多或少知道一些。作为一个编写代码的人,我发现这个概念离我平时编程很近,拿JavaScript为例,有两个主要原则:
咱们用下面的例子来进行介绍:
.header { background: #BADA55; color: #000; width: 960px; margin: 0 auto; } .footer { background: #BADA55; text-align: center; color: #000; padding-top: 20px; }
其中有一些样式是重复的,咱们能够考虑在另外一个类中提取这些相同的样式:
.colors-skin { background: #BADA55; color: #000; } .header { width: 960px; margin: 0 auto; } .footer { text-align: center; padding-top: 20px; }
因此咱们使用colors-skin
作为一个对象,用来扩展。这样HTML模板修改为像这样:
<div class="header colors-skin"> ... </div> <div class="colors-skin"> ... </div> <div class="footer colors-skin"> ... </div>
这样作有几个好处:
这里的想法是,每一个元素应该有相同的样式,无论他放在何处。因此,你应该尽可能避免使用像下面演示的选择器:
.header .social-widget { width: 250px; }
若是你把.social-widget
移动.header
容器的外面,那么.social-widget
的宽度就变了。尤为是用在页面上的组件。这也是我鼓励CSS模块化以及我强烈建议采用更多的时间去尝试。就我我的而言,如下的原则会将CSS写得更好。
若是你在GitHub上打开OOCSS库你能够看到一个框架。是的,这个框架使用了面向对象的概念,他的CSS有不少很优秀的现成组件。很长一段时间我并不喜欢框架。若是你有在工做使用框架,你会发现他分为两个部分。事实上,你使用框架处理一些事情,你必须遵照他的规则。不过我更喜欢使用一些微小的框架。固然我不是说我得从新去造轮子,但我老是试图去寻找一种平衡。一般现成的解决方案致使系统的混乱和复杂。我建议是为必定的目的创建一个特定的东西。若是你试图去覆盖一些东西,你老是想到框架中的东西。
但事,我强烈建议你去查寻一个OOCSS框架。这是一个独特的知识块,也许它将适合用在你须要的地方。最先是由Nicole Sullivan提出这样的一个概念。若是你对OOCSS有什么意向或者想法,可到这里参加讨论。
另外一个流行的概念是SMACSS。SMACSS表明可伸缩的和是模块化的CSS结构体系。Jonathan Snook为CSS开发人员介绍了相似于这样的样式指南。为了单独的应用程序将其分为如下几类:
clearfix
header
和sidebar
我没有使用SMACSS的任何经验,便它是很是受欢迎,实际上也能促进你有更好的想法。这比一个框架的概念更强。因此,你不须要遵循任何严格的规则、类或者组件。
知道了OOCSS和SMACSS后,请容许我找一个恰当的比喻,请快速登陆这个页面。这里展现了一个伟大的原子设计概念。它的做者是Brad Frost,众所周知,他是一位有名的Web开发人员,致力于响应式设计和移动端开发。
这个想法是很是有趣的。如下是一些术语,咱们能够说,物质的基本单位是原子。Brad Frost说咱们的页面是用移动的原子构建,一个原子能够是:
<label>Search the site</label>
或者
<input type="text" placeholder="enter keyword" />
也就是说原子是包括了一些基本样式的DOM元素。如颜色、字体大小或者过渡动画。后来这些部分能够结合成分子,例如:
<form> <label>Search the site</label> <input type="text" placeholder="enter keyword" /> <input type="submit" value="search" /> </form>
因此表单元素包含了几个原子。这样抽象带来的灵活性,由于咱们可使用相同的原子来构建另外一个分子。这样一来,咱们在不一样的上下文中能够重用相同的形式:
Brad Frost并无中止。生特体是构建分子的东西,遵循一样的方法,咱们能够编写如下的结构,并将其称为有机体:
<header> <div class="logo"> </div> <nav> <ul> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Contacts</a></li> </ul> </nav> <form> <label>Search the site</label> <input type="text" placeholder="enter keyword" /> <input type="submit" value="search" /> </form> </header>
第二件事是模板的概念。他们不是直接相关的化学反应,但被放入了Web的上下文。一旦咱们开始结合不一样的生物构建咱们的模板。后来这些模板形式就是咱们最后获得的页面。
你可能已经使用相似的方法来构建应用程序。然而,命名的东西以一种合理的主式带来良好的结构。在开发中,你和你的队友会有不少事情须要去弄明白。分离的原子和分子是很重要的部分,由于它提升了工做效率和让你更好的维护您的Web应用程序。
两个月前,我写了一篇文章,是有关于Organic的,他是一个用JavaScript写的一个伟大的小框架。它更像是一种设计模式,我我的很是喜欢。我甚至在好几个项目中使用了它,而且一切都很顺利。若是你有兴趣的话,我强烈推荐您阅读这篇文章。
当我阅读了Brad Frost的文章,我就已经有了相似于的概念,由于我知道Organic。Brad作的很是的棒,可是我决定更深刻的去了解,或尝试本身在基于原子设计概念的基础上写一个小型的框架。我最终选择了Sass做为预处理器和在Github上建立了一库organic-css。
让我匀先从框架最小的一部分开始——原子。维基百科是这样定义的,原子是物质的基本单位。在CSS中,我认为它是一个属性和一个属性值,例如:
margin-top: 24px;
仅仅为了写样式添加原子而直接添加类名,这并非我想要的,若是有一个这样的类型:
body { margin-top: 24px; } header { margin-top: 24px; }
预处理器将会失去他本身做用,由于我想要的结果是这样的:
body, header { margin-top: 24px; }
在Sass中可使用placeholders
的功能,例如:
%margin-top-24 { margin-top: 24px; } body { @extend %margin-top-24; } header { @extend %margin-top-24; }
因此我不得不使用placeholder
。这也意味着,我必需要定义不少placeholders
,才能使用。在那一刻,我决定,这个框架将只包含原子。也许有一些分子和通用的函数,例如reset.css
、网格的定义等等。我想写点东西,做为一个基础的CSS开发。也许我会看到项目中的一些模式,将其放在核心处,做为一个开始,并保持干净和简单。
事情变得更加的一致化,我建立了一个mixin
做为一个原子。如这个例子:
@include define-atom("block") { display: block; } @include define-atom("font-family") { font-family: Georgia; }
使用这种方法,我建立了一个原子群,而且能够很容易的适合用于每个项目。你能够点击查看。我而且拿其余的框架做为对比,让我更好的去实践,从中学到不少东西。还能够制做一个mixin
分子,将原子相结合在一块儿:
@mixin header { // <- molecule called 'header' @include atoms(( block, clearfix, font-family )); }
分子是一个DOM元素须要样式,但他没有子元素。或者他有子元素,便也不会直接链接到它。如<img src="logo.jpg" />
,多是一个分子。若是你很难在你的页面识别这些分子,只须要想到什么是由原子构建就行。有些元素也有多是构建其余分子的原子。如:
@mixin login-box { @include atoms(( block, font-size-20, margin-top-23, bold )); }
咱们将面对一些颇有趣的事。好比说咱们的body
标签。他是什么呢?它是一个分子或其余什么吗?固然,这须要一些样式,但通常在原子中包含其余分子。它应该是其余东西。个人结论是,CSS应该是主要部分,也就是说,若是body
样式须要几个原子,那么他就是一个分子。这也就意味着,从理论上讲,我不该该附加任何其余的分子给它。这看起来有点不切实际,但在大多数状况下,会让你使用不一样的选择器,这将是一个好的发展迹象。
一旦你认识到这个DOM元素是分子,那么你能够将其看到是一个细胞器。例如,典型的表单元素是一个很好的细胞器例子,他包含像label
、input
和textarea
这样的分子。
.login-form { @include label; @include input; @include textarea; }
这些也许是框轲中的一部分,它紧密的链接到当前应用程序中。原子和分子可能在不一样项目之间移动,而细胞器是不可能会移动的。
不少时候你可能想把几个别的东西放在一块儿,这样细胞器变得更加抽象:
Atom → Molecule → Organelle → Cell → Tissue → Organ → Sys → Organism
这将面对一个选择问题,你将如何构建你的CSS。我之前只在一个项目中使用OrganicCSS,到目前为止,我还能够说他是清晰的。我把不一样的元素放在他们本身的目录中和按他们的名命名,这样我能够很容易的找到他们,并作相应的处理。例如,若是有一个细胞器称为header
,我只须要将其修改成o-header
。后来,让我读到HTML标记,我就能够看到该元素的CSS样式就在细胞器文件夹中。
这是一个颇有趣的旅程。我不知道我未来会不会使用OrganicCSS,但这并非最重要的部分。我能从中学到东西才是最重要的。我知道我必须改变咱们的CSS开发过程,我作到了。我认为咱们应该多谈谈CSS的框架。你能够看到咱们有不少好的资源。咱们必须找到他们,学习他们作什么以及如何工做。只有这样咱们才能够决定是否使用他们。更好的是,当你看到整个图片你能够创造一些更适合你的需求。
特别声明:本文有不少概念也是初次接触,就对此文进行翻译,若是有理解错语的地方,但愿不会给您带来误解,同时更但愿这译文能改变你对CSS的构建方式,从而找出更适合您或您团队使用CSS的最佳方式。最后但愿更多的同行朋友能指正文中不正确的地方和分享相关的资源(^_^)
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了我的对技术的理解。若是翻译有不对之处,还烦请同行朋友指点。谢谢!
如需转载烦请注明出处: