CSS流体(自适应)布局下宽度分离原则

CSS流体(自适应)布局下宽度分离原则

一、简短的前言

之前曾作有“页面重构鑫三无准则之无宽度准则”一文,属于流体布局系列中的偏理论性的文章,本文也是这种性质的,可谓是“无宽度准则”一文的延续。

“无宽度准则”是说内部元素不要定宽,但是,除非你的页面是像google的产品页面一样都是100%自适应的,那么页面的终归会有一个固定的宽度值,一般出现在页面的结构部分(主宽度,侧栏,中栏)、以及等宽列表部分,而这些就是本文要讨论的对象。

跳出围墙,enjoy it!

二、何为宽度分离?

所谓“宽度分离”,就是CSS中的width属性不与影响宽度的border/padding(有时候包括margin)属性共存。

即不能出现以下的些组合:

{width:200px; border:1px solid #ccc;}

或者是:

{width:200px; padding:20px;}

三、为何要宽度分离

“宽度分离”可以让你延年益寿,家庭和睦!您可能会觉得我马屁的好处比脑白金还要响亮,不急,看完我下面的分析您再下定论。

首先为什么会长寿?因为在“宽度分离原则”下,您不需要1像素1像素的去计算宽度,不必去劳心劳神地去估量这里的padding值应该多少像素才不会撑开布局,不必去琢磨这里的margin值为多少列表才可以正好一行显示5个。不就是写个页面嘛,最后搞得像做果蝇DNA提取实验一样,目不转睛,全神贯注,脑细胞犹如刚领的薪水,迅速消耗。折腾到最后,发现唯独该死的IE6下居然布局错位,一颗满心期待的心顿时冷却到了冰点。唉,要知道心累才是真的累,小说以及电视剧里面的悲情角色多半都是心力交瘁而死的。在“宽度分离原则”下,相比前面的些折腾,写页面的感觉就像是躺在绿油油的草地上享受柔和的春风;又像是在悠远质朴的街头与孩童们一起嬉闹玩耍。我不说也应该看出来了,一个是不停地折腾,一个是惬意的享受。要知道,我们一生中大概有8~9年的时间是在工作的(24小时不停),要是工作的时候总是劳心劳神地折腾,估计早死个个把月是不成问题的。

再说家庭和睦。在“宽度分离原则”下(结合“无宽度原则”),像错位这种性质的bug是不可能会出现的。没有了在宽度上的纠缠不清,没有了修改样式bug这类杂碎的活儿,于是,我们工作就会变得很轻松。页面刷刷地写完,没有错位,没有bug,而且以后无论怎么折腾也不会出类似的bug,关键布局重用性高(宽度分离可重用,内部自适应——也是任意重用)。然后剩下的就是端上一杯咖啡,边慢慢品味咖啡的浓香,边悠然自得得看看微博,这工作,多轻松惬意。

但是,如果你是一根筋地像砌砖头式的写页面,宽度相关属性不分离,啊哦,你有得忙了:写页面的时候宽度要去计算,还要去反复调试,还要兼顾浏览器的兼容性问题,我想想都觉得麻烦,耗时间;后来又出来了个类似的功能,就是宽度不一样,不得已,新功能页面宽度重新计算,样式重写,得,又是折腾;页面好不容易出来了,但是,后来需求要改,即使很小的改动,宽度啊什么的也要重新计算;好不容易改好了,结果上线后发现某些地方的布局有bug。辛辛苦苦加班加点写页面赶工期上线,谁知最后还因些小bug还被经理批:就这几个破页面,折腾这么久,还有问题。首先,这每天加班,人体力上肯定折损很大,你说这晚上回家,老婆大人想寻求安慰,你却提不起劲,啧啧,我只能说“遗憾”儿子;其次,这辛苦工作最后还是被训的份,这心里头肯定不是滋味,回家说不定就因为女友大人的不断的唠唠叨叨给恼火,然后吵架什么的就来了。所以说“宽度分离”可以让家庭和睦。

四、继续为何要宽度分离

上面的解释可能由于自己的思维一下子没刹住车,略夸张并带了点玩笑的性质,其实,意思就是说:“宽度分离”无计算,扩展性强,容错性强,可以让写页面更轻松。
这里,我要好好解析下为什么“宽度分离”扩展性强同时可以让写页面更轻松。

Part1: 我们应该都知道:当一件事情很多人可以作决定,恰恰这些人又同时做决定的时候,这件事情最后往往是做不好,一团乱的。举个例子:

某篮球队没有教练,场上的5个人都有说话权,结果到关键时候,暂停处理关键球的时候,后卫说这球应打到外线博三分,而小前锋却说这球要求稳,突破先取两分……此时该听谁的?于是暂停时间结束,大家脑中还是混乱一篇,不知究竟该怎么做。于是,最后的结果往往是:被人家紧逼——发球失误——直接被抢断。如果此时只有一人能说话,无论是部署配合,还是确定2分还是3分策略,效果都要比现在好很多。

在举个更贴近我们工作的例子。举例对象就是可亲可敬的设计师们,我之前在微博上看过一个关于平面设计师的连环漫画,如果是针对网页设计师,我想故事应该这样发展:设计师加班加点设计出了一个页面,结果产品经理一看,觉得这里不行得改一改。好吧,本着敬业精神,于是又加班加点改好了。回头给前端老大看了下,觉得那里不行,实现成本太高,要改,于是任劳任怨的设计师又去加班加点改好了。后市场总监也来看了下设计图,觉得这广告位设计不行,得改……于是,繁华都市夜空下的办公楼里又出现了那个熟悉的孤独的背影。

设计师之所以会有如此的悲哀就是因为:很多人可以决定设计师的设计内容,恰恰这些人又同时对设计师的设计指手画脚。于是,出现了不断折腾的局面。

OK,现在来看看CSS中的width属性。我们都知道,CSS中影响宽度属性的不只是width属性,还有border属性,以及padding属性。例如:

.test { width: 200px; border: 2px solid #ccc; padding: 20px; }

则此.test下的div实际宽度是200 + 2 * 2 + 20 * 2244像素。

这里的width属性就像是设计师,border属性就是产品经理,padding就是技术经理。当这些属性都是混在一起,就像是所有人都对设计师指手画脚一样,最后的结果就是折腾、混乱,公公背媳妇过河——吃力不讨好。

Part2: 我们也应该都知道:很多事情关注的重点应该是在结果上,而不是过程,这样我们会变得非常轻松。

就像中医治病一样,不必管到底是什么物质在体内与疾病作斗争,病好了才是王道。我再举两个例子:
第一个是称重量。在还没有电子称的时候,我们要使用单标尺机械称称100斤的小麦该怎么称?

显然,这里,我们应该关注的是最终的结果——100斤。所以,我们先把称(坨+标尺)调到50公斤的位置,然后不断地加小麦,直到标尺开始悬空,此时就是100斤了。

当然,我们还有一种关注过程的做法,我称之为“称体重”做法,具体如下:机械称上放入一定量的小麦,然后称一下质量,发现是86斤;于是又向里面添加了点,再称,96斤;于是,又放入一定量的小麦,再次去移动标尺测重量,结果102斤,过了;然后,又去掉一点,再称,这次终于100斤了。

前者就近似于本文所说的“宽度分离”做法,无需计算,只关心结果;而后者就是需要计算的做法了。

第二个例子就比较贴近我们的工作了,就是工作任务制。这是很多公司对于技术人员的一种管理制度,也就是“你只要在规定的时间内完成规定的任务,期间随便你做什么我都不管”。这就是典型的只关心结果,这种做法的好处是:开发人员可以享受到很大的自由,对于做技术的人来讲,这是种莫大的恩赐,至少对于我来讲是这样子的,于是工作更开心更高效;对于管理人员讲,工作就相对轻松了很多,不必每天去监督关注下属工作进度如何如何,只要在期限结束的时候验收就可以了。工作轻松了,自然也有更多的精力在其他方面折腾了,谄笑

例如,前端老大要求你5个页面2天时间给我整好了。于是老大只要关心2天后你页面是否出来,至于期间你是不停地和美女前台打情骂俏还是玩《愤怒的小鸟》一个通宵还是加班加点连澡都来不及洗都不管boss的事情,boss只关心结果。这与“宽度分离”原则是一致的,我们放眼的是最终的宽度,至于内部怎么折腾屁事都不相干,由于我们只关心一个东西——最终宽度,所以我们会非常轻松。

Part3: 我们也应该知道水是流动的,其会自动填满放置它的容器。

在页面制作与CSS中,所以的div标签默认都是流动的,如水流般会自动填满整个容器。然而,很多属性会阻断这种流动性,例如浮动,绝对定位以及宽度(width)属性。所以,流体布局中应该尽可能的避免浮动,绝对定位以及宽度。然而,本文的前提就是针对有些必不可少的宽度,这些width属性就像是一个限定了尺寸的盒子。虽然width属性会阻断流动,但是会影响宽度的border属性以及padding属性却不会阻断div标签的流动性。试想下,一个盒子里如果只有流动的水流,这个盒子永远不要担心会被撑爆,因为水流只会受限于盒子,反过来则是不行的。也就是说将width属性与border/padding属性分离的话,就不用担心里面的内容(里面的内容需遵循“无宽度准则”)会因为宽度溢出撑开布局而造成错位了。这让我们只关心“最终宽度”没有了后顾之忧。//zxx:容错性强

同时,由于水流可以盛放与任何容器中,所以,一旦“水流”形成,几乎就可以无限制重用。同时,这个尺寸的容器也是可以放置其他的水流的。//zxx:重用性强

按照这里的分析,“宽度分离”实际上类似于化学上的“固液分离”。

五、如何宽度分离

举个以前曾列举过的例子,如下图:
要实现效果的图片 张鑫旭-鑫空间-鑫生活

要实现上图所示的效果,您会怎么做?我大胆估计了下,考虑到最少的HTML代码,您可那会有如下的样式:

.box{width:430px; padding:20px; border:1px solid #ddd;}

HTML如下:

<div class="box">
    <strong>温馨提示</strong><br />
    团购成功后,消费凭证将发送到手机:<strong class="cr">132 0803 3621</strong>,凭短信去商家消费。
</div>

显然上面的做法是不符合“宽度分离”原则的,如果宽度分离,则应该样式如下:

.box{width:470px;}
.box_in{padding:20px; border:1px solid #ddd;}

HTML如下:

<div class="box">
   <div class="box_in">
        <strong>温馨提示</strong><br />
        团购成功后,消费凭证将发送到手机:<strong class="cr">132 0803 3621</strong>,凭短信去商家消费。
    </div>
</div>

对比前后就可以看出“宽度分离”的实现其实就是以牺牲一层标签为代价,将width属性放在外层标签上,其余的放在内层标签上。这里看似多了层标签,实际上权衡下来,裨益相对于损耗要大很多很多。

说到这里,我忍不住要岔点别的话题,关于写意与写实
我之前就提过,写页面就是一种创作,可以融入自身的艺术气息,表达自己的情感、个性。说到艺术创作,就离不开“写意”与“写实”。比如绘画,就有抽象派和写实派。
抽象派作品 张鑫旭-鑫空间-鑫生活 绘画写实派作品 张鑫旭-鑫空间-鑫生活

又比如诗词,亦有写意与写实,拿李白的《静夜思》举例,如果是“床前明月光,李白睡得香”,那么就是写实;如果是“床前明月光,疑是地上霜”那就是写意。

就连武侠中也有“无招胜有招”这种类似的概念。

如果只是照着设计图一个框子一个框子的套,那只能说是“写实”。“写实”的最高境界就是写出的的页面与设计图1像素都不差,各个浏览器下都1像素不差,如果你是这样的,那去腾讯吧,那里适合你。而我个人更强调“写意”,细节上的极致,结构上的洒脱,简单轻松自由无限的感觉。流体布局显然更强调“写意”,其自适应特性本身就带有种洒脱的气质,写流体布局页面犹如写诗般,寥寥数语,情境顿生,不刻板,不拘泥。具有诗人情怀的人才能写出真正诗意的页面;刻板的人只能写刻板的页面,这类人更适合去折腾C++。

我突然想到了一个东西,几年前貌似讨论很热的“栅格化布局”,说实话,我对这玩意真是一点都不感冒,甚至有些嗤之以鼻。我这人天生就不是个循规蹈矩的人,对需要套用(40×n)- 10 = W这类公式的东西是很不喜欢的。公式的好处在于统一与规范,这在定宽布局(如950像素宽度)上的还是颇有裨益的。然而,公式的本身就意味着限制,你不可能跳出这个圈圈的。网页设计不同于平面,上百年下来都是一个尺寸的纸张。在宽屏日益普及的今天,950~980像素见尺寸的页面还能坚挺多久?如果要改动,是否还要遵循“格栅化布局”?还去套用(40×n)- 10 = W的宽度公式?所谓无为而治、无欲则刚。《海贼王》中路飞桑曾说过:“我才不要成为最强的人呢,我要成为大海上可以自由驰骋的人!”可见自由才是最强大的。

我平身最讨厌的就是被限制,所以我成为一个个流体布局控也就不奇怪了,不鸟“栅格化布局”也就容易理解了。

六、宽度分离的简单例子

首先看一个分离的例子,京东商城的首页底部区域,有一个灰边框圈住的服务相关的内容,如下图所示:
京东商城底部的灰色框框内容 张鑫旭-鑫空间-鑫生活

//zxx:虽然京东商城的页面在宽屏下有1200像素的宽度,但是其并不是自适应布局,而是普屏和宽屏下的两套不同的结构宽度样式而已。相比较自适应布局,此技术难度和要考虑的因素要小很多。

我们用小bug(我对firebug的昵称)看下此处的CSS代码,可以看到宽度分离了,即最外层标签仅仅只有width属性:
最外层仅宽度 张鑫旭-鑫空间-鑫生活

而影响宽度的border属性以及padding属性全部写在了内部的标签上:
border和padding属性写在了里面的标签上 张鑫旭-鑫空间-鑫生活

如果从精简HTML,较少DOM层级的角度考虑,我们其实一层标签就可以搞定了,如下:

#service{width:1158px; padding:20px 20px 10px;border:1px solid #E6E6E6;overflow:hidden;zoom:1;margin-bottom:10px;}

但是为什么京东的做法却不是如此呢,而是要将其分离出来呢?

好吧,我可能明知故问了,上面我已经浪费了很多口水,哦,不对,是浪费了很多次的打键盘来讲原因:
其一,不要去计算了。多省心啊,直接1200像素,否则还要1200 - 20 * 2 - 1 * 2 = 1158去计算,诶呦呦呦,这多闹心啊!
其二,重用性高了。你瞧,这.w{width:1200px}很多地方都可以使用,如果不分离出来,oh, my lady gaga, 一个模块一段宽度相关样式,这纯粹属于闲得蛋疼没事找事。
其三,维护方便了。你说要是以后这padding值要改成左右15像素的,如果是宽度分离的写法,只要修改padding属性就可以了。分离的思想就是:我只关注最最外面的宽度,里面你随便怎么折腾都不干我屁事。要是以后要修改最外框的宽度为1260像素,就直接修改width:1200pxwidth:1260px就可以了,因为自适应部分已经分离出来了,如流水般自适应外部的容器。但是,倘若是使用一层标签,CSS是width+border+padding这种暧昧不清的写法,当我们修改padding的时候,不仅要改padding属性,同时width属性的值还要重新计算与修改,属性相互关联,牵一发而动全身。

下面再看一个没有分离的例子。对于页面的主div结构而言,不知是有意还是无意,国内领先的网站都会将宽度与边框和内边距属性剥离出来,然而,在内部结构元素,或是列表布局的时候,情况就不一样了。京东商城有这样子的问题(不多),淘宝网也有(较多较严重,正好当教材使用),这里就拿淘宝网举例。

先说一个我百思不得其解的问题,见下面的截图:
淘宝网首页奇怪的宽度属性 张鑫旭-鑫空间-鑫生活

还有下面的类似的问题:
淘宝网首页莫名其妙的宽度问题 张鑫旭-鑫空间-鑫生活

上面两张图高亮的宽度属性真是让我无言以对,我试着从各个角度找理由,haslayout?模块化开发副产物?但是最后我只能得到的结论是:写category.css的应该是个刚毕业的新手。请原谅我有意的冒犯,只因自己太纠结,为什么这里要添加一个毫无意义,反而带来诸多糟粕的width属性呢?谁能给我个答案?……

罢了,这不是这里讨论的重点。我们来看看列表布局中有关“宽度分离”的例子,首先见下截图:
淘宝网首页的列表问题 张鑫旭-鑫空间-鑫生活

显然,这里的列表CSS有悖本文的主题“宽度分离原则”,width属性与含有水平padding值的属性写在了一起,首先不说别的,估计这里的宽度计算与调试估计折腾了不少时间。您可能会想,是不是使用:

.category-item li{
    float:left;
    width:228px; /*修改宽度*/
    height:21px;
    margin-bottom:5px;
    overflow:hidden;
}

嘿嘿,不是的!对于等宽列表而言,虽然宽度分离可以较少一些后期维护的工作量,但是,如果还是定值的话计算还是不可避免的,因为你需要做“总宽/3”的计算,例如684 / 3 = ?。所以,如果是我,不仅会宽度分离,而且宽度会使用百分比而不是定值,因为不需要计算啦。如下CSS:

.category-item li{
    float:left;
    width:33.3%; /*修改宽度*/
    height:21px;
    margin-bottom:5px;
    overflow:hidden;
}

还是那句话,我只关心结果,你父标签宽度多少与我没有任何关系,我只知道我是等宽列表,而且一行三个,所以,我的宽度百分比就是100 / 3 = 33.3%,至于里面怎么内讧,外面怎么凌乱都不管我的事,我只关心结果,与我相关的结果,我最终的宽度。

本实例中,实际上是里面是不需要再包裹一层标签的,因为里面已经有h4标签和span标签供使用了,按照“精简高效的CSS命名准则/方法”的观点是不推荐直接使用.category-item h5这样的选择器,但是,这是淘宝网,人家已经用了,不用白不用,所以,我们可以把padding-left的10像素可以margin-left:10px;以写在.category-item h5上,而padding-right的26像素可以以margin-right:26px;的形式(或省略)写在.category-item li span上,这样既实现了宽度分离(自适应于父标签,同时内部元素又自适应于自身,而且没有了计算,后期维护也更容易了),又没有多余的层级。

实际上,考虑到更高的重用性,属性:

{
    float:left;
    width:33.3%; 
}

应该独立分离出来,命名应采用面向属性的命名方式。但是,淘宝网首页就是个独立的页面,与其他页面老死不相往来,所以,这样子的样式分离就没有必要了。

七、最后点总结

你想页面刷刷地以迅雷不及掩耳的速度写完吗?你想写的页面无需调试鲜有兼容性问题吗?你想让你的页面再怎么折腾布局都不会乱吗?你想让你的页面以后改动起来就像在无人的电梯里放屁那样轻松吗?你想让的页面加载起来闪都不闪一下吗?你想每天有大把的时间喝咖啡、上微博同时还工资不断涨吗?

跟你讲,听我的,遵循宽度分离原则,以上都可以实现,准错不了。但是,注意这里的但是,您需要认认真真去看看我之前写的关于流体布局思想的些东西,去体会CSS分离的思想,CSS合并的思想,理解关于CSS命名的思想,尤其要明白“无宽度准则”说的什么意思,然后再来使用这里的无宽度准则,再加上你一定的写页面的经验(1千张应该差不多了,)。否则,就单单这里一篇文章,只能一定程度上提高你写页面的速度和页面的质量,仅仅是一点点的量变而已。

有必要说下,我所写的CSS偏理论方面的一系列文章相互间都是关联的,用一个不太恰当的此代替的话,可以说是一个体系,一个自己摸索总结形成的CSS理论体系。单独一篇文章或许是偏执,但是所有文章结合在一起你将会看到另外一个完整的世界,犹如《阿凡达》的潘多拉世界一样。我的这类文章具有极强的个人特质,具有一定的反叛与嘲讽,与主流的CSS做法总是有出入的,所以难免会刺痛一些固步于自己CSS世界里的一些人的自尊心。

我是非常非常欢迎也非常非常期望任何人以任何形式(例如评论)进行真诚的交流。海纳百川,有容乃大,您的看法与见解可以让我看到自己的不足和需要提高的地方,这对于我来讲是最最需要的。但是,如果您只是粗略的扫视文章内容,然后过来指手画脚,反而只会暗自被我嘲笑而已。

本文的“宽度分离”原则其实不单单针对流体布局的,固定宽度的布局依旧适用,但是,习惯于固定布局的人往往缺少流体布局的意识,“宽度分离”的潜力发挥有限,因而才以“流体布局”为题。

最后,感谢您的阅读,希望本文的内容能够对您的学习有所帮助。

posted @ 2017-01-13 09:57  茹孟凯  阅读(334)  评论(0编辑  收藏  举报