一、布局的基本概念
多栏布局有三种基本的实现方案:固定宽度、流动、弹性。
- 固定宽度布局的大小不会随用户调整浏览器窗口大小而变化,一般是900 到1100像素宽。其中960 像素是最常见的,因为能够被16、12、10、8、6、5、4 和3 整除,不仅容易计算等宽分栏的数量,而且计算结果也能得到没有小数的像素数。流行的CSS 布局框架960 Grid(http://www.960.gs),就是基于960 像素宽的网格创建的
- 流动布局的大小会随用户调整浏览器窗口大小而变化。这种布局能够更好地适应大屏幕,但同时也意味着放弃对页面某些方面的控制,比如随着页面宽度变化,文本行的长度和页面元素之间的位置关系都可能变化。今天,越来越多的浏览器都支持CSS 媒体查询了。这就让基于浏览器窗口宽度提供不同的CSS 样式成为可能。在这种形势下,适应各种屏幕宽度的可变固定布局,正逐步取代流动布局。这种可变的固定布局能够适应最大和最小的屏幕,业界称之为响应式设计
- 弹性布局与流动布局类似,在浏览器窗口变宽时,不仅布局变宽,而且所有内容元素的大小也会变化,让人产生一种所有东西都变大了的感觉。到目前为止,还没见过设计得非常好的弹性布局,主要是因为它太过复杂了
布局高度与布局宽度:多数情况下,布局中结构化元素(乃至任何元素)的高度是不必设定的。与高度不同,需要精细地控制布局宽度。
二、三栏——固定宽度的布局
从一个简单的居中的单栏固定布局开始。
<div id="wrapper"> <article> <! -- 这里是一些文本元素 --> </article> </div>
布局相关的CSS 如下:
#wrapper {width:960px; margin:0 auto; border:1px solid;} article {background:#ffed53;}
下面,再向外包装里添加一个导航元素,让它作为第二栏:
<div id="wrapper"> <nav> <!-- 无序列表 --> </nav> <article> <! -- 文本 --> </article> </div>
#wrapper {width:960px; margin:0 auto; border:1px solid;} nav { width:150px; float:left; } nav li { /*去掉列表项目符号*/ list-style-type:none; } article { width:810px; float:left; background:#ffed53; }
采用同样的方法,可以添加第三栏(或任意多个栏)。
<div id="wrapper"> <nav> <!-- 无序列表 --> </nav> <article> <! -- 文本 --> </article> <aside> <! -- 文本 --> </aside> </div>
#wrapper {width:960px; margin:0 auto; border:1px solid;} nav { width:150px; float:left; background:#dcd9c0; } nav li { list-style-type:none; } article { width:600px; float:left; background:#ffed53; } aside { width:210px; float:left; background:#3f7ccf; }
接下来添加页眉和页脚:
<div id="wrapper"> <header> <!-- 标题 --> </header> <nav> <!-- 无序列表 --> </nav> <article> <! -- 文本 --> </article> <aside> <! -- 文本 --> </aside> <footer> <!-- 文本 --> </footer> </div>
我们希望页眉和页脚与布局同宽,而且它们默认就与布局同宽,在此只简单地为它们设定了背景色,以便能看到它们在哪儿。
header {background:#f00;} footer {background:#000;}
到目前为止,为HTML 标记应用的CSS 如下(没多少文本样式)。
* {margin:0; padding:0;} #wrapper {width:960px; margin:0 auto; border:1px solid;} header {background:#f00;} nav { width:150px; float:left; background:#dcd9c0; } nav li { list-style-type:none; } article { width:600px; float:left; background:#ffed53; } aside { width:210px; float:left; background:#3f7ccf; } footer {clear:both; background:#000;}
目前布局中的两个主要问题。首先,内容与各栏边界紧挨在一起,太拥挤;其次,每栏高度由文本多少决定,而如果每栏都与布局一样高则更好。
为栏设定内边距和边框
只要一调整各栏中的内容,布局就可能超过容器宽度,而右边的栏就可能滑到左边的栏下方。一般来说,两种情况下可能会发生这种问题。
- 为了让内容与栏边界空开距离,为栏添加水平外边距和内边距,或者为了增加栏间距,为栏添加外边距,导致布局宽度增大,进而浮动栏下滑。
- 在栏中添加大图片,或者没有空格的长字符串(如长URL),也会导致栏宽超过布局宽度。同样,这种情况下右边的栏也会滑到左边的栏下方。
下面就来试试添加内边距,增大内容与栏边界的距离。从中间一栏开始。
article { width:600px; float:left; background:#ffed53; padding:10px 20px; }
解决的方法有以下三种:
- 从设定的元素宽度中减去添加的水平外边距、边框和内边距的宽度和。
- 在容器内部的元素上添加内边距或外边距。
- 使用CSS3 的box-sizing 属性切换盒子缩放方式,比如section {box-sizing:border-box;}。 应用box-sizing 属性后,给section 添加边框和内边距都不会增大盒子,相反会导致内容变窄。
1. 重设宽度以抵消内边距和边框
比如给600 像素宽的栏又添加了20 像素的内边距,为了抵消增加的内边距,可以把栏宽减少40 像素而设定为560 像素。这样,右边的栏就能归位。问题在于,每次只要调整内、外边距就要重设布局宽度,有点烦人。
2. 给容器内部的元素应用内边距和边框
没有宽度的元素在水平方向上会适应其父元素,其内容会随着外边距、边框和内边距的增加而减少。与其为容器中的元素添加边距,不如在栏中再添加一个没有宽度的div,让它包含所有内容元素,然后再给这个div 应用边框和内边距。
<article> <div class="inner"> <!-- 文本 --> </div> </article> 接下来不仅能给内部div 应用内边距,还能给它应用外边距和边框。 article { width:6oopx; float:left; padding:10px 20px; background:#ffed53; } article .inner { margin:10px; border:2px solid red; padding:20px; }
总之,由此可以得出一个结论:如果布局中的栏是浮动的,而且都设定了宽度,你就根本不要去动它!要动,就把内容放在内部div 里,动这个div。
接下来我们去掉中间栏的外边距、边框和内边距,给其他两栏也添加内部div,然后只给这三栏加上内边距。
<div id="wrapper"> <header> <!-- header text --> </header> <nav> <div class="inner"> <ul> <!-- 链接 --> </ul> </div> </nav> <article> <div class="inner"> <!-- 文本 --> </div> </article> <aside> <div class="inner"> <!-- 文本 --> </div> </aside> <footer> <!-- 文本 --> </footer> </div>
接下来我们就利用这个div 为三个栏中的内容创造间距。此外,还居中了页脚中的内容。
nav .inner {padding:10px;} article .inner {padding:10px 20px;} aside .inner {padding:10px;} footer {text-align:center}
3. 使用box-sizing:border-box
这是最简单的一个办法。只要在三个浮动的栏的CSS 规则中分别加上box-sizing:border-box 声明,再给栏添加内边距(和边框)就不会导致盒子的宽度变化了。此时,既不用调整栏宽去抵消增加的内边距,也不用使用内部div。添加内边距的结果就是内容收缩。以下就是简洁清晰的没有内部div 的标记。
<div id="wrapper"> <header> <!-- 标题 --> </header> <nav> <ul> <!-- 链接 --> </ul> </nav> <article> <!-- 文本 --> </article> <aside> <!-- 文本 --> </aside> <footer> <!-- 文本 --> </footer> </div> 而以下就是CSS 规则。 * {margin:0; padding:0;} #wrapper {width:960px; margin:0 auto; border:1px solid #000;overflow:hidden;} header {background:#f00;} nav { box-sizing:border-box; width:150px; float:left; background:#dcd9c0; padding:10px 10px; } /*去掉列表项目符号*/ nav li {list-style-type:none;} article { box-sizing:border-box; width:600px; float:left; background:#ffed53; padding:10px 20px; } aside { box-sizing:border-box; width:210px; float:left; background:#3f7ccf; padding:10px 10px; } footer {clear:both; background:#000;}
三、三栏——固定宽度的布局
实现中栏流动布局有两种方法。一种是在中栏改变大小时使用负外边距定位右栏,另一种是使用CSS3 让栏容器具有类似表格单元的行为。
1. 用负外边距实现
实现三栏布局且让中栏内容区流动(不固定)的核心问题,就是处理右栏的定位,并在中栏内容区大小改变时控制右栏与布局的关系。
Web 开发人员Ryan Brill 给出的解决方案是控制两个外包装(通过ID 值为wrapper)容器的外边距。其中一个wrapper包围所有三栏,另一个wrapper只包围左栏和中栏。
<div id="main_wrapper"> <header> <!-- 页眉--> </header> <div id="threecolwrap">/*三栏外包装(包围全部三栏)*/ <div id="twocolwrap">/*两栏外包装(包围左栏和中栏)*/ /*左栏*/ <nav> <!-- 导航 --> </nav> /*中栏*/ <article> <!-- 区块 --> </article> </div>/*结束两栏外包装(twocolwrap)*/ /*右栏*/ <aside> <!-- 侧栏 --> </aside> </div>/*结束三栏外包装(threecolwrap)*/ <footer> <!-- 页脚 --> </footer> </div>
相应的CSS如下:
* {margin:0; padding:0;} body {font:1em helvetica, arial, sans-serif;} div#main_wrapper{ min-width:600px; max-width:1100px; /*超过最大宽度时,居中布局*/ margin:0 auto; /*背景图片默认从左上角开始拼接*/ background:url(images/bg_tile_150pxw.png) repeat-y #eee; } header { padding:5px 10px; background:#3f7ccf; } div#threecolwrap { /*浮动强制它包围浮动的栏*/ float:left; width:100%; /*背景图片右对齐*/ background:url(images/bg_tile_210pxw.png) top right repeat-y; } div#twocolwrap { /*浮动强制它包围浮动的栏*/ float:left; width:100%; /*把右栏拉到区块外边距腾出的位置上*/ margin-right:-210px; } nav { float:left; width:150px; background:#f00; padding:20px 0; } /*让子元素与栏边界保持一定距离*/ nav > * {margin:0 10px;} article { width:auto; margin-left:150px; /*在流动居中的栏右侧腾出空间*/ margin-right:210px; background:#eee; padding:20px 0; } /*让子元素与栏边界保持一定距离*/ article > * {margin:0 20px;} aside { float:left; width:210px; background:#ffed53; padding:20px 0; } /*让子元素与栏边界保持一定距离*/ aside > * {margin:0 10px;} footer { clear:both; width:100%; text-align:center; background:#000; }
三栏中的右栏是210像素宽。为了给右栏腾出空间,中栏article 元素有一个210 像素的右外边距。包围左栏和中栏的两栏wrapper上有210 像素的负右外边距,会把右栏拉回article 元素右外边距创造的空间内。中栏aticle 元素的宽度是auto,因此它仍然会力求占据浮动左栏剩余的所有空间。一方面中栏article 元素的右外边距在两栏wrapper内为右栏腾出了空间,另一方面两栏wrapper的负右外边距又把右栏拉到了该空间内。
人造栏技术
左栏的背景图片加在了div#main_wrapper 上。右栏的背景图片加在了div#threecolwrap 上,而且让它沿该div 的右侧垂直拼接。中栏的背景色也加在了div#main_wrapper 上,这个背景色实际上是整个布局的背景色。
2. 用CSS单元格实现
表格由三个元素构成。一个表格外包装<table>,包含着表格行
<tr>和表格数据<td>,比如下面这个例子。
<table> <tr> <td>Cell 1</td> <td>Cell 2</td> <td>Cell 3</td> </tr> <tr> <td>Cell 1</td> <td>Cell 2</td> <td>Cell 3</td> </tr> </table>
CSS 可以把一个HTML 元素的display 属性设定为table、table-row 和table-cell。通过这种方法可以模拟相应HTML 元素的行为。而通过CSS 把布局中的栏设定为table-cell 有三个好处。
- 单元格(table-cell)不需要浮动就可以并排显示,而且直接为它们应用内边距也不会破坏布局。
- 默认情况下,一行中的所有单元格高度相同,因而也不需要人造的等高栏效果了。
- 任何没有明确设定宽度的栏都是流动的。
因此,要实现一个三栏流动中栏布局,只需要以下标记:
<nav><!-- 内容 --></nav> <article><!-- 内容 --></article> <aside><!-- 内容 --></aside>
和以下CSS:
nav {display:table-cell; width:150px; padding:10px; background:#dcd9c0;} article {display:table-cell; padding:10px 20px; background:#ffed53;} aside {display:table-cell; width:210px; padding:10px; background:#3f7ccf;}
四、多行多栏布局
这个布局的标记如下。
<div id="container"> <header> <h1>Full-width content</h1> </header> <nav> <p>Navigation menus go here</p> </nav> <section id="branding"> <img src="images/grand_canyon.jpg" alt="Grand Canyon" /> </section><!-- branding 结束 --> <section id="feature_area"> <article> <div class="inner"> <p>Lorem Ipsum text</p> </div> </article> <!-- 省略另外两个 article 元素 --> </section><!-- feature_area 结束--> <section id="promo_area"> <article> <div class="inner"> <p>Lorem Ipsum text</p> </div> </article> <!-- 省略另外三个 article 元素 --> </section><!-- promo_area 结束--> <footer> <p>This is the footer.Visit <a href="http://www.everyinch.net">Everyinch.net</a> for more CSS information and updates.</p> </footer> </div>
转载请注明:陈童的博客 » 使用CSS进行页面布局的方法