之前说了什么是 CSS ,也介绍了 CSS 的盒模型,下面理所当然地要进入 CSS 的核心内容,定位与布局。其实说完这个部分,CSS 就没什么东西可说了,剩下的都是些细枝末节或者很直观的东西。对,把最抽象的这部分理解了, CSS 就没有任何难度可言了。
如果你的制图习惯比较良好(良好的意思是有比较完整地执行这里:http://hao.uisdc.com 的规则),有好好对图层进行分组,那么你就已经对你的设计稿完成了最初步的切版工作。按照你切的版,把元素一个个码好,你的页面就搞定了。然而实际上的页面并不是像PSD设计稿那么安分,它有可能这个部分要一直固定在屏幕顶端,那个部分的内容时多时少,因此才要学会 CSS 的“布局语言”。
常规流
我们通常讲的块级元素与行内元素的默认表现,就是它们在常规流中的表现。有一个名为display的 CSS 属性可以修改它们的表现形式。在默认情况下,块级元素的display属性值为block,行内元素的属性值为inline,如果你把某个a元素的display属性值改成block,那么这个a元素就会像一个块级元素一样表现自己了。另外还有一个比较特殊的属性值为inline-block,顾名思义是像行内元素那样排列的块级元素,一般情况下,在想要并列排列某些块级元素的时候,就可以把它们的display属性值改成inline-block(无奖问答:为什么不直接改成inline呢?)
相对定位
一般的教程会把相对定位和绝对定位一起放在浮动的前面或者后面,而我选择这么安排内容的原因之一是我想要强调相对定位的元素仍然在常规流中(事实上W3C标准 http://www.w3.org 也是如此安排目录的)。
position:relative的元素就拥有了相对定位的能力,而用户可以通过上下左右(top、bottom、left、right)四个属性值(但是通常只使用top和left,因为这里允许使用负数,right = -left)来在视觉上“推走”这个元素。相对定位最大的特点就是,元素的本体还在那里,而用户看到的则未必(上下左右都不设置或者为0的时候,元素仍旧在那里),定位方式是“相对于原位置定位”,因此被称为相对定位。而其真正在定位上的应用,通常不是在大框架的布局,而是一些小地方、小细节的微调,而其更常见的用法,会在下面再次提到。
当然一个超级普通毫无特色常规流块级元素根本无法满足我们对丰富布局的需求,所以出现了人间大杀器——float。
浮动
当我们将某个元素的float属性改为left或者right的时候,这个元素就成为了一个浮动的块级元素。
首先它仍然是一个块级元素(如果它原本是一个内联元素,那么此时它也变成了块级元素)——拥有padding、border、margin,可以设置宽高。其次它浮起来了:
它脱离了常规流
它的宽度变成了它内容的宽度
它向着你规定的方向挤成一堆
这些事意味着什么呢:
浮动元素的宽度变成了其内容所需的最小宽度。如果这个元素里面还有一个常规块级元素呢?那就要看这个常规块级元素多宽咯(它没定义宽度,那还是100%)。
浮动元素后面的常规元素看不见他(因为他们不在同一个“流”里了),浮动元素的父元素也看不见他(视而不见),只有行框看得见——文字会绕着它们排列。
浮动元素会按着所规定的方向一个接一个水平排列,如果水平位置不够则换到下一行,如果水平位置和垂直位置都还有剩,则会优先往上放。
浮动元素与父元素、浮动元素之间的内外边界不会相交。也就是说,浮动元素以及其父元素的padding、margin区域都不会重叠。
浮动元素的顶边不会超过源代码中它前面出现元素所生成行框的顶。
几乎所有关于浮动布局可能出现的问题,都可以在上面这几条中找到原因。举个栗子:
两列布局
微博就是最典型的两列布局(新版V6的登录后首页变成三列了,不过用户页面仍然是两列…),这种两列式的布局解决方法很简单,两个固定宽度的div,一起向左浮动,或者一个向左、一个向右。
而在很多游戏网站中,为了尽可能利用大屏幕的优势,而把页面设计成左边有一个固定宽度的导航,右侧全屏占满,在这种情况下,上面的写法就不成立了。不管两个元素如何浮动,宽度都没有办法正好撑满整个屏幕,虽然 CSS 中的width(宽度) 属性可以使用百分比的值,但是当你将其设为100%的时候,它又掉下来了。此时最好的做法是将左边栏(第一个 div)设为浮动,并且给一个固定的宽度(比如200px)。此时两个 div 元素在同一高度上,但是右侧的 div 看不到左侧的那个,内容仍然从左上角开始显示,此时只要给这个 div 的margin-left赋值为200px,就可以将右侧div的左边200px空出来,这样两列布局的基本就完成了。
清除浮动(Clear-fix)
有些人觉得Clear fix被翻译为清除浮动并不合适,因为实际上浮动仍然还在(元素仍然漂浮着),而这个术语的本意也应该是“清除浮动所造成的不良影响”,不过在中文圈子里,从 clearfix 方法出生伊始,它就被叫做清除浮动了…所以也没办法啦╮(╯▽╰)╭。
它所修正的不良影响,主要是针对上面的第二条。浮动元素的父元素看不到它:如果某个块级元素里的所有子元素都是浮动的,那么这个元素自身就不会有高度,在需要设置背景和边框的时候,这种问题总像幽灵般如影随形。解决方法也很成熟:
另外还有一个“真正的”清除属性——clear,在上面的示例中也出现了,这个属性规定了该元素的左侧或右侧是否可以与浮动元素相邻——如果规定的方向有浮动元素,那么这个元素就会向下排列(到底是有多讨厌人家…)
绝对定位
还有一种比较特殊的定位方式,被称为绝对定位,事实上我们PS文件中的图层都是绝对定位。position:absolute的元素就成为了一个绝对定位元素,相对定位是相对于元素自身,而绝对定位也是针对元素自身而言——跟自身原本绝对没关系。
绝对定位的元素完全脱离了常规流,可以说是“哪个元素都看不见它”。而它仍然需要一个定位的“原点”,W3C规定离绝对定位元素最近的position属性为relative、absolute或fixed的祖先元素的内容框的左上角(有一个特例,就是该祖先元素为行内元素的时候,这里不展开说明了,基本遇不到),作为该元素绝对定位的原点。因此,其实,相对定位元素(position:relative)通常都被用于创建绝对定位元素的包含块(containing block),如果你有一个绝对定位元素,而它的位置跟你预想的不对,那就是其定位基准出问题了。而其定位方式一样,是通过上下左右的值来规定的。
固定定位
position:fixed的元素就是固定定位元素,本质上它也是一种绝对定位,这种元素会固定于浏览器窗口的固定位置,很多网站顶端的固定导航、右下角的固定广告等等都是通过这种方式定位的。
定位关系
如果某个元素是绝对定位元素(position为absolute或fixed),则float属性对其无效,同时元素变为块级元素。
而当某个元素的position不为static(position:static即为最普通的常规流中的元素)时,它们彼此之间就有可能发生重叠(就像PS图层一样,图层重叠是很常见的)。
在源代码中后出现的元素会覆盖先出现的元素
浮 动元素会覆盖常规流元素
绝对定位元素会覆盖浮动元素
使用z-index可以无视上述三条规则z-index属性可以规定图层之前的层叠顺序,其数值越大,该元素越靠“前”(叠在所有图层的最上面),如果你发现某个元素无论如何都覆盖不了,检查一下它的z-index属性值,也许就能找到答案。
Flexible Box(伸缩盒模型)
display:flex的元素就会应用伸缩盒模型,它是 CSS 中真正为布局而生的模型。现在关于这个模型的相关文章还很少,而且各种问题也很多,因为从09年到现在,它经历了3个大的版本变化,而这涉及到了大量手机及IE的版本兼容问题,导致很多网站都不愿意采取这种布局方式。
使用这种模型布局进行布局最炫酷的一点是,我们不用再费力计算宽度然后为元素规定宽度,所有的宽度根据所有可用空间及内容进行分配,这样对于个数不固定的元素也可以实现完美分配。空间分配方式有两种:
1.按照盒的宽度比例分配
2.按照剩余空间比例分配
如果上面的说明有点不清楚,点这里(http://bennettfeely.com)有一个DEMO,可以通过改变左边各项属性的值看到其结果。如果你们的项目只针对最新的iPhone(iOS7及以上),你可以考虑拗你们的前端去尝试使用这个模型来布局(我曾亲测过绝大多数网上流传的兼容代码,全军覆没,主要国内有UC浏览器这个大杀器)。
后
display规定了该元素所应用的模型,position规定了该元素的定位方式,二者共同构成了 CSS 定位与布局的基础。另外W3C也提出了伸缩盒模型用于满足复杂多变的布局需求,并且开始推荐厂商实现,如果各位有需要,在将来我可以单独开一篇文章讲这部分内容。
定位与布局在整个 CSS 当中是最难掌握的,这里我提到内容也只是最容易发生的问题,对于初入代码门的设计师来说,基本上是够用了。但是很多前端工程师(不仅是处女座的)多少都会有一些代码洁癖,对代码中的嵌套包含关系也很在意,比如某位大神的这篇文章(www.zhangxinxu.com)中提到的代码层级关系与内容层级之间的联系,不愿意仅仅为了布局而增加一个额外的元素,这种时候精通各种 CSS 布局方式及其特点就显得很有必要了。各位可以根据自己的程度选择自己想要深入到何处~
最后关于相关的教程,除了W3C School的定位系列(www.Vevb.com)之外,我还推荐CSDN的说说标准系列(http://bbs.csdn.net)。前者应用型很强还带有很多示例,适合初学者以应用为目的的基础学习,后者则是推荐给那些想要进阶为前端工程师的人,深入了解 W3C 对盒模型及定位的定义,同时也有很多示例代码可供学习。
新闻热点
疑难解答