概述
本文由大漠根据Thierry Koblentz的《Challenging CSS Best Practices》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://coding.smashingmagazine.com/2013/10/21/challenging-css-best-practices-atomic-approach/,以及作者相关信息
——作者:Thierry Koblentz
——译者:大漠
这篇文章介绍的技术特性在Yahoo通过实践以及有问题的技术代码到今天为止我们还在使用。你可能有兴趣阅读Jonathan Snook的《Decoupling HTML From CSS》、Tim Huegdon的《On HTML Elements Identifiers》和Robin Rendle的《Atomic Design With Sass》等等。请记住:一些提到的技术并不认为是最佳实践。——Thierry Koblentz
当谈到CSS,我相信神圣的原则——点分离(SoC)。他已经让我们接受膨胀、报废、冗余、缓存甚至更多。现在,我确信唯一的方法是远离这一原则来改善我们的作者样式表。
对于从未听说过SoC原则在Web设计中的上下文,它涉及到一些俗称“三层分离”:
- 结构
- 表现
- 行为
为了避免一些担忧,将它划分成独立的资源:一个HTML文档,一个或多个样式文件和一个或多个JavaSctript文件。
但当涉及到表现层,“最佳实践”已经超出了资源的分离。CSS作者完全可能通过样式表应付,例如Dave Shea写的CSS禅意花园就是一个优秀的项目。CSS禅意花园是大多数(如果不是全部)开发人员用来做为如何写样式表的参考标准。
标准
今天能过实践来帮我说明相关问题,我将使用一个非常常见的模块:媒体对象。它结合了HTML标记和CSS样式,将是我们开始探讨的起点。
模板结构
在我们的模板中,有一个容器(div.media
)包含了一个链接容器(a.img
),接着有一个div
容器(div.bd
):
CSS
我们给容器设置10px的margin
,同时给容器和div.bd
设置为一个BFC。换句话说,容器包含了一个浮动的链接,并且div.bd
不能围绕在链接的周围。同时在图片和文本之间设置一个10像素的margin
(在浮动的一侧):
.media {
margin: 10px;
}
.media,
.bd {
overflow: hidden;
_overflow: visible;
zoom: 1;
}
.media .img {
float: left;
margin-right: 10px;
}
.media .img img {
display: block;
}
结果
这是一个容器的表现形式,有一个图片在链接中以及文本围绕在一侧:
新的需求出现时
假设我们现在需要将文本显示在图像的另一边。
模板结构
非常庆幸BFC
的魔力,现在我们需要修改链接的样式风格。为此,我们给图片增加一个新的类名imgExt
。
CSS
我们将添加一个向右浮动的样式给链接,并修改他们的margin
值:
.media {
margin: 10px;
}
.media,
.bd {
overflow: hidden;
_overflow: visible;
zoom: 1;
}
.media .img {
float: left;
margin-right: 10px;
}
.media .img img {
display: block;
}
.media .imgExt {
float: right;
margin-left: 10px;
}
结果
图像现在显示在另一边:
另一个需求出现时
假设我们现在需要在正常的页面中将文本设置的更小。为此,我们创建一个新规则,使用#rightRail
作为上下文的选择器:
模板结构
我们的模块现在放在一个div#rightRail
的容器里面:
CSS
再一次,我们创建一个额外的规则,这一次使用后代选择器#rightRail .bd
:
.media {
margin: 10px;
}
.media,
.bd {
overflow: hidden;
_overflow: visible;
zoom: 1;
}
.media .img {
float: left;
margin-right: 10px;
}
.media .img img {
display: block;
}
.media .imgExt {
float: right;
margin-left: 10px;
}
#rightRail .bd {
font-size: smaller;
}
结果
这里是我们的原始模块,显示在div#rightRail
内:
这个模块有什么错误?
- 在样式表中给模块改变简单的样式可以得到新的效果:必须有一个方法不总是为需要的样式风格写更多的CSS规则。
- 组合选择器是常见的样式(
.media,.bd{}
):使用了组合选择器,而没有使用一个类定义样同的样式,而导致更多的CSS。 - 我们有六种规则,四种规则是基于上下文:上下文相关的规则是很难维护的。样式与这些规则不太可重用。
- RTL和LTR接口变得复杂:改变方向,我们需要覆盖我们的一些样式(即写更多的规则)。例如:
.rtl .media .img {
margin-right: auto; /* reset */
float: right;
margin-left: 10px;
}
.rtl .media .imgExt {
margin-left: auto; /* reset */
float: left;
margin-right: 10px;
}
满足原子层叠样式表
a·tom·ic:组件中的单元组成一个更大的系统。
我们都知道,越小的单位,更可重用它。
把代码当作成乐高。把代码尽可可能断成小块的。——@csswizardry(via@stubbornella)#btconf
将样式分解成单元块,我们可以将这些单元块映射到样式中的单个类,而不是很多。这个规则将导致一个更细粒度的规则,进而提高可重用性。
让我们重新考虑媒体对像使用这种新方法。
模板结构
我们使用了五个类名,没有哪个类是与内容相关的:
CSS
每个类都关联到一个指定的样式。在大多数情况下,这意味着我们有一个声明规则。
.Bfc {
overflow: hidden;
zoom: 1;
}
.M-10 {
margin: 10px;
}
.Fl-start {
float: left;
}
.Mend-10 {
margin-right: 10px;
}
.Fz-s {
font-size: smaller;
}
结果
这个如何?
现在我们忽略了类名和关注是这样做(或不这样做)。
- 没有上下文样式:我们没用使用上下誩或后台选择器,这意味着我们的样式没有权重一说。
- 方向(左和右)是“抽象的”:不用覆盖样式,容器在样式表中使用了RTL规则,例如下面的代码:
.Fl-start {
float: right;
}
.Mend-10 {
margin-left: 10px;
}
相同类名,相同的属性,不同的属性值。
但要注意最重要的事情是,我们美化模板样式。我们已经必变了模上下文样式。现在编辑HTML模板而不是样式表。
我相信这种方法是改变了,因为它大大缩小了范围。我们样式不是全局的,只是模块的和块级别的样式。我们可以改变一个模块的样式,而不用担心破坏别的页面。我们可以不做什么给这个样式表添加任何规则,只需要创建一个新类名和规则:
这样一来没有冗余。选择器是不重复的,样式是属于一个单独的而不是其他的一部分。例如,在样式表中页面包含了72个float
的声明。
同时,放弃一种样式——例如,总是保持图片在左侧的模块——这并不会任何样式规则过时。
听起来不错吧?
不是吹的吧?我听到了你说“这就违背了书中每一个规则”。这没有与行内样式比。你的类名是神秘的,但也是不具语义化的。
这是公平的。让我们解决这些问题。
关于没有语义化的类名
如果你查阅了W3C的网站管理的技巧,它说“好名字不改变”,你将看到这样的论点是关于维护,而不是语义化本身。所也这样说的也是,在CSS文件中修改样式要比在多个HTML文件中修改要来得容易多。如果只改变一个元素的样式而要求我们修改声明,.border4px
将是一个不好的类名,这类名和名字联系在一起。换句话说:
.border4px {border-width:2px;}
关于语义模糊的类名
在大多数情况下,这些类名名称遵循Zen Coding的语法——查看Zen Coding字符表(PDF)——现在称为Emmet。换句话说,他们是简单的缩写。
关于(left和right)相关联的样式,包括一个组合声明。例如,Bfc代表“块格式化上下文”。
关于模仿行内样式
希望下图能帮助你清理:
- 特殊性(Specificity):这项技术并不像
@style
具有特殊性。他的样式权重很低,因为都只是依赖于单个类名,而不像.parent .bd{}
这样的后代选择器,选择为0.0.2.0
(有关于权重的相关教程,请查阅CSS Specificity: Things You Should Know)。【中文版本可以点击《你应该知道的一些事情——CSS权重》】。 - 冗余(Verbosity):大多数类是采用缩写来声明样式(例如,
M-10
表示的是margin:10px
)。一些类名,如.Bfc
是指多于一种样式的集合(如上图的映射部分)。还有其他一些类使用start
和end
这样在关键词,而没使用left
和right
值(见上图中的抽象部分)。
下面是@style
的一些优点:
- 范围(Scope):样式就是将接点相连在一起的一个“沙箱”。
- 可移植性(Portability):因为样式是封装在一些的,你可以移动到模块中而不会丢失他们的样式。当然,我们仍然需要样式表;但是,因为不受限于上下文结构,模块可以放置在任何一个页面上,网站中甚至是网络中。
臃肿的路径
因为模块的样式是直接依靠类名,他们可以实现我们想要的任何效果。例如,如果我们需要创建一个简单的两列布局,我们所需要做的是在模板中用div
来替代当初的链接。看起来像这样:
我们只需要在样式表中增加一个额外的规则:
.Bfc {
overflow: hidden;
zoom: 1;
}
.M-10 {
margin: 10px;
}
.Fl-start {
float: left;
}
.Mend-10 {
margin-right: 10px;
}
.Fz-s {
font-size: smaller;
}
.W-50 {
width: 50%;
}
与传统方法相比:
这里我们需要创建三个新的类名,添加一个额外的样式规则和组选择器:
.wrapper,
.content,
.media,
.bd {
overflow: hidden;
_overflow: visible;
zoom: 1;
}
.sidebar {
width: 50%;
}
.sidebar,
.media .img {
float: left;
margin-right: 10px;
}
.media .img img {
display: block;
}
我认为上面的代码很好的展示了SoC原则。根据我的经验,它只是增加了样式表大小。
此外,文件越大,越有由复杂的规则和选择器组成。然后没有人敢去编辑现有的样式规则:
- 我们不敢去修改样式规则,害怕修改现有样式规则后会破坏一些东西。
- 我们只能创建新的样式规则,而不是修改现有样式规则,因为我们不确定后者是100%安全的。
换句话来说,我们使事情变得更糟糕,因为我们使文件变得越来越臃肿。
如今,人们习惯于非常大的样式表,和很多程序员认为他们熟悉他们的领域。而不是去思考减少臃肿,他们使用工具(如预处理器)来帮助他们去处理它。Chris Eppstein告诉我们:
LinkedIn有超过1100个Sass文件(每个SCSS文件有230K行)和每天有超过90个开发人员在编写Sass。
CSS臃肿对比HTML臃肿
让我们一起来面对它们:数据必须放对地方。考虑下面的两种结构
在很多案例中,语义化的类名要比表像的类名使用更多的字节(.wrapper
与.Bfc
对比)。但我不认为这是一个真正让人担忧的问题,相比之下,现在大多数应用都在使用data-
属性。
这就是gzip进来的好处,因为高冗余的类名在整个文档将取得更好的压缩。同样的道理也适用于样式表中,我们有很多冗余的样式:
.M-1 {margin: 1px;}
.M-2 {margin: 2px;}
.M-4 {margin: 4px;}
.M-6 {margin: 6px;}
.M-8 {margin: 8px;}
etc.
缓存
表面上的规则不改变。样式表由这些成熟的工具集制作,作者可以找到他们所需要的一切。通过他们的特征,他们停止增大文件,成为不可变的。而不可变是缓存最友好的。
没有更好的.button
类名?
这里讨论的技术并不是禁止语义化类名和规则,以及群组选择器声明样式。这个想法只是为了评估常用的方法的好处,而不是采用它作为事实上的技术来美化Web页面。换句话说,我们是限制“组件”方法的几个案例,这是很有意义的。
例如,你可能会发现我们的样式表中有以下规则。这些规则设定我们的样式,我们不创建简单的类或规则,确保跨浏览支持。
.button {
display: inline-block;
*display: inline;
zoom: 1;
font-size: bold 16px/2em Arial;
height: 2em;
box-shadow: inset 1px 1px 2px 0px #fff;
background: -webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ededed), color-stop(1, #dfdfdf));
background: linear-gradient(center top, #ededed 5%, #dfdfdf 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#dfdfdf');
background-color: #ededed;
color: #777;
text-decoration: none;
text-align: center;
text-shadow: 1px 1px 2px #ffffff;
border-radius: 4px;
border: 2px solid #dcdcdc;
}
.modal {
position: fixed;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
*width: 600px;
*margin-left: -300px;
*top: 50px;
}
@media 0screen {
.modal {
width: 600px;
margin-left: -300px;
top: 50px;
}
}
另一方面,你将在样式中看到如下所列的规则(即样式绑定到特定的模块),因为我喜欢将相同的风格使用多个类来实现:一个用于字体大小、颜色,一个用于浮动等。
.news-module {
font-size: 14px;
color: #555;
float: left;
width: 50%;
padding: 10px;
margin-right: 10px;
}
.testimonial {
font-size: 16px;
font-style: italic;
color: #222;
padding: 10px;
}
我们包括所有可能的风格在我们的样式表?
这个想法是为了拥有一个规则,作者可以选择他们想要的任何样式。跨网站的样式风格是常见的,足以让这些成为样式表中的一部分样式。如果一个风格太具体,那么我们就会依赖于@style
(样式属性)。换句话说,我们宁愿修改标记而不是样式表。主要目的是创建一个规则表,解决各种设计模式。比如一个元素的float
的基本规则可以添加一个helper
类名来完成。
/**
* one liner with ellipsis
* 1. we inherit hyphens:auto from body, which would break "Ell" in table cells
*/
.Ell {
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
-webkit-hyphens: none; /* 1 */
-ms-hyphens: none;
-o-hyphens: none;
hyphens: none;
}
/**
* kinda line-clamp
* two lines according to default font-size and line-height
*/
.LineClamp {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-size: 13px;
line-height: 1.25;
max-height: 32px;
_height: 32px;
overflow: hidden;
}
/**
* reveals an hidden element on :hover or :focus
* visibility can be forced by applying the class "RevealNested-on"
* IE8+
*/
:root .NestedHidden {
opacity: 0;
}
:root .NestedHidden:focus,
:root .RevealNested:hover .NestedHidden,
:root .RevealNested-on .NestedHidden {
opacity: 1;
}
这种规模如何?
我们刚刚发布了一个全新的My Yahoo,在很大程度上依赖于这种技术。这是它与雅虎其他产品的对比(gzip压缩后):
我们样式表大约是17.9kb大小(约3kb是可调整的),它是可共享的(与样式表的其他属性)。原因是,没有任何规则包含了内容。
结束
因为表像的类名一直被视为“界外”,我们、社区没有真正调查他们的使用需要。事实上,在这个名字的最佳实践,我们已经驳回了每一个机会去发掘自己潜在的好处。
在雅虎,@renatoiwa,@StevenRCarlson和我正在开发的项目使用了这个新的CSS架构。【中文版本,可以点击这里阅读】。代码似乎是可预测、可重用、可维护和可扩展的。到目前为止,这些都是我们所经历的结果:
- 少臃肿:我们可以不添加一行样式到样式表中创建整个模块。
- 快速开发:样式由与内容无关的类控制,因此我们可以复制和粘贴现有模块。
- 自由的RTL接口:使用
start
和end
关键词有很大意义。它为我们省去了为上下文RTL编写额外的样式规则。 - 好的缓存:大量的CSS可以跨产品和属性共享。
- 非常小的维护(CSS方面):只有一套小样式规则在随着时间变化。
- 抽象少:没有必要在一个样式表中找出一个模板的样式规则。这是所有的标记。
- 第三方开发:第三方可以把我们一个模板无需附加样式表(或样式块)应用到项目中。没有自定义规则,意味着第三方没有打破规则,没有恰当的名称空间。
注意,如果维护而言,维护CSS方面总比维护HTML方面容易,那么很简单,我们可以在CSS方面不做样式清理。但如果我们必须保持简洁,那么我们同样面对一些痛苦的事情。
最后注意
在几个星期前,我在一次聚会中听到Colt McAnlis说“工具,而不是规则”,快速搜索这个词返回这个:
我们都需要接受新知识、新方法、新的最佳实践,我们需要能够分享他们。
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
如需转载,烦请注明出处:
英文原文:http://coding.smashingmagazine.com/2013/10/21/challenging-css-best-practices-atomic-approach/
中文译文:htpp://www.w3cplus.com/css/challenging-css-best-practices-atomic-approach.html
http://www.w3cplus.com/css/challenging-css-best-practices-atomic-approach.html
最后
以上就是多情红牛为你收集整理的挑战最佳CSS实战的全部内容,希望文章能够帮你解决挑战最佳CSS实战所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复