Skip to content

精通 CSS - 高级 Web 标准解决方案 8. 布局

所有 CSS 布局技术的根本都是 3 个基本概念:定位浮动外边距操纵

8.1 计划布局

布局时先做一些计划可以避免很多问题。

  1. 先把页面规划为大的结构性区域,比如容器、页眉、内容区域和页脚。
  2. 然后,将注意力转移到内容区域本身,开始建立网格结构。
  3. 最后,在各个内容区域中寻找不同的布局结构。

结构设计完之后,可以开始关注不同类型的内容。
查看每个内容块的结构,看看不同的类型中是否有共同的模式。
找出模式并确定命名规约之后,最好马上开始定义将使用的元素。

8.2 设置基本结构

典型的三列博客模板。

html
<body>
    <div class="wrapper">
        <div class="header">
            <!-- Your header content goes here -->
        </div>

        <div class="content">
            <!-- Your content content goes here -->
        </div>

        <div class="footer">
            <!-- Your footer content goes here -->
        </div>
    </div>
</body>

使用外边距让设计居中

设置主体 div 的宽度,并将水平外边距设置为 auto

css
.wrapper {
    width: 920px;
    margin: 0 auto;
}

8.3 基于浮动的布局

基于浮动的布局是最容易使用的,也是最可靠的。只需设置希望定位的元素的宽度,然后将它们向左或向右浮动。

因为浮动的元素不再占据文档流中的任何空间,它们就不再对包围它们的块框产生任何影响。为了解决这个问题,需要对布局中各个点上的浮动元素进行清理。非常常见的做法是浮动几乎所有东西,然后在整个文档的“战略点”(比如页脚)上进行一次或两次清理。还可以使用溢出方法清理某些元素的内容。

8.3.1 两列的浮动布局

html
<div class="content">
    <div class="primary">
        <!-- main content goes here -->
    </div>

    <div class="secondary">
        <!-- navigation and secondary content goes here -->
    </div>
</div>

为每个列设置想要的宽度,然后将次要内容向左浮动,将主要内容向右浮动。

css
/* 将主要内容向右浮动 */
.content .primary {
    width: 650px;
    padding-right: 20px;
    float: right;
    display: inline;
}
/* 将次要内容向左浮动 */
.content .secondary {
    width: 230px;
    float: left;
    display: inline;
}
/* 清除浮动 */
.content {
    overflow: hidden;
}

8.3.2 三列的浮动布局

和两列布局唯一的差异是在内容 div 中添加了两个新的 div:一个用于主内容,一个用于次要内容。

html
<div class="content">
    <div class="primary">
        <div class="primary">
            <!-- primary primary content goes here -->
        </div>
        <div class="secondary">
            <!-- secondary primary content goes here -->
        </div>
    </div>
    <div class="secondary">
        <!-- navigation and secondary content goes here -->
    </div>
</div>
css
.content .primary .primary {
    width: 400px;
    float: left;
    display: inline;
}
.content .prmary .secondary {
    width: 230px;
    float: right;
    display: inline;
}

8.4 固定宽度、流式和弹性布局

上面的两个布局都是固定宽度的布局。该布局比较常见,因为开发人员可以精确的定位元素的位置。
但缺陷也很明显,因为尺寸是固定的,导致无法适配各种分辨率的屏幕。另外更改浏览器的文本字号时可能会导致页面不易阅读。

8.4.1 流式布局

尺寸使用百分比而不是像素来设置。

问题:在窗口较窄时,行会变的非常窄。窗口太大时,也会导致行太宽,也同样不适合阅读。

css
/* 以整个页面宽度为基准计算出百分比 */
.wrapper {
    width: 76.8%;
    margin: 0 auto;
    text-align: left;
    /* 为了确保窗口过大或过小时页面文本也适合阅读,最好以 em 为单位设置最大和最小宽度 */
    max-width: 125em;
    min-width: 62em;
}
.content .primary {
    width: 72.82%;
    float: right;
    display: inline;
}
.content .secondary {
    width: 25%;
    float: left;
    display: inline;
}
/* 以主要内容的宽度为基准计算百分比 */
.content .primary .primary {
    width: 59.7%;
    float: left;
    display: inline;
}
.content .primary .secondary {
    width: 34.33%;
    padding-right: 2.63%;
    float: right;
    display: inline;
}

8.4.2 弹性布局

弹性布局相对于字号(而不是浏览器宽度)来设置元素的宽度。以 em 为单位设置宽度。

问题:不能充分利用可用空间。另外字号增大时整个布局会加大,进而导致水平滚动条出现。需要在容器 div 上设置 max-width

将固定宽度布局转换为弹性布局是相对简单的任务。技巧是要设置基字号,让 1em 大致相当于 10px
大多数浏览器上的默认字号是 16px,10px 大约是 16px 的 62.5%,所以在主题上将字号设置为 62.5% 。

css
body {
    font-size: 62.5%;
    text-align: center;
}
.wrapper {
    width: 92em;
    max-width: 95%;
    margin: 0 auto;
    text-align: left;
}
/* 内部宽度仍然使用百分比 */
.content .primary {
    width: 72.82%;
    float: right;
    display: inline;
}
.content .secondary {
    width: 25%;
    float: left;
    display: inline;
}
.content .primary .primary {
    width: 59.7%;
    float: left;
    display: inline;
}
.content .primary .secondary {
    width: 34.33%;
    padding-right: 2em;
    float: right;
    display: inline;
}

现代浏览器很多都已支持页面缩放了。

8.4.3 流式和弹性图像

使用流式或单行布局,固定宽度的图像会对设计产生强烈的影响。

对于需要跨越大区域的图像,比如站点页眉或品牌区域中的图像,可以考虑率使用背景图像而不是图片元素。

css
#branding {
    height: 171px;
    background: url(/img/branding.png) no-repeat left top;
}
html
<div id="branding"></div>

如果图像需要用作页面上的图像元素,需要将宽度设置为 100% 并且将 overflow 设置为 hidden

css
#branding {
    width: 100%;
    overflow: hidden;
}
html
<div id="branding">
    <img src="/img/branding" width="1600" height="171" />
</div>

对于常规内容图片,你可能希望它们可以水平和垂直伸缩。

css
.news img {
    /* 设置图片的宽度为百分比,这样就可以实现自动伸缩 */
    width: 25%;
    /* 设置最大宽度,以避免图像失真 */
    max-width: 200px;
    float: left;
    display: inline;
    padding: 2%;
}
.news p {
    width: 68%;
    float: right;
    display: inline;
    padding: 2% 2% 2% 0;
}

8.5 faux 列

每个区域由于内部元素的高度各不相同,会导致背景色没有渲染到整列。
对策是在一个占据布局最大高度的元素(比如一个容器 div)上应用重复的背景图像。

css
#wrapper {
    background: #fff url(/img/nav-bg-fixwd.gif) repeat-y left top;
}

对于流式或弹性布局时,则需要多张背景图片分别按照百分比进行定位。

css
.wrapper {
    background: #fff url(/img/secondary-faux-column.gif) repeat-y 25% 0;
}
.inner-wrapper {
    background: #fff url(/img/primary-faux-column.gif) repeat-y 72.82% 0;
}

8.6 高度相等的列

使用表格很容易实现这种效果,但是 CSS 中实现需要一点技巧。

html
<div class="wrapper">
    <div class="box">
        <p>狩魔猎人</p>
        <p>...</p>
        <div class="bottom"></div>
    </div>
    <div class="box">
        <p>秘术师</p>
        <p>...</p>
        <div class="bottom"></div>
    </div>
    <div class="box">
        <p>圣教军</p>
        <p>...</p>
        <div class="bottom"></div>
    </div>
</div>
css
.wrapper {
    width: 100%;
}
.box {
    width: 250px;
    margin-left: 20px;
    float: left;
    display: inline;
    padding: 20px;
    background: #89ac10 url(/img/top.gif) no-repeat left top;
}

这会产生 3 个高度不一致的列。

这种技术的关键是给每个框设置大的底内边距,然后用数值相似的负外边距消除这个高度。

css
.wrapper {
    width: 100%;
    overflow: hidden;
}
.box {
    width: 250px;
    padding-left: 20px;
    padding-right: 20px;
    padding-top: 20px;
    padding-bottom: 520px;
    margin-bottom: -500px;
    margin-left: 20px;
    floatL left;
    display: inline;
    background: #89ac10 url(/img/top.gif) no-repeat left top;
}

为了把列的底边定位在正确的位置,需要让它们与容器元素的底部对齐。
为此,首先把容器的 position 设置为 relative。然后把 bottomposition 设置为 absolute,把它们的 bottom 属性设置为 0。

css
.wrapper {
    width: 100%;
    overflow: hidden;
    position: relative;
}
.bottom {
    position: absolute;
    bottom: 0;
    height: 20px;
    width: 290px;
    background: url(/img/bottom.gif) #89ac10 bottom left no-repeat;
    margin-left: -20px;
}

8.7 CSS 3 列

CSS 3 也可以创建等高文本列,这要通过 column-countcolumn-widthcolumn-gap 属性实现。

html
<p>狩魔猎人</p>
<div class="col">
    <p>...</p>
</div>
css
.col {
    -moz-column-count: 3;
    -moz-column-width: 14em;
    -moz-column-gap: 2em;
    -moz-column-rule: 1px solid #ccc;
    -webkit-column-count: 3;
    -webkit-column-width: 14em;
    -webkit-column-gap: 2em;
    -webkit-column-rule: 1px solid #ccc;
    column-count: 3;
    column-width: 14em;
    column-gap: 2em;
    column-rule: 1px solid #ccc;
}

8.8 CSS 框架与 CSS 系统

CSS 框架 的目标是简化 CSS 的使用,帮助用户方便地创建各种常用的布局,而不需要编辑底层的 CSS。如 YUI Griids、Blueprint 和 960 等。
但其也有缺点,会改变编写标记的方式,破坏变现和意义的分离;要求在设计中必须使用特定的网格结构。

CSS 系统 实际上是一个工具箱,其中包含可重用的样式和标记模式,可以用它开发站点专用的框架。
工具箱可以包含全局 reset、排版样式和表单处理,以及登录表单、日历表格和导航列表等常用 HTML 组件的标记模式。然后再开发作为定制框架使用的系统。

附 1. 引用

  1. 《精通 CSS - 高级 Web 标准解决方案(第 2 版)》 - Andy Budd, Simon Collison, Cameron Moll 著;陈剑瓯 译。

本书后面还有 3 章,分别讲了 bug 的发现与修复方法 和 两个作者写的示例及其用到的一些未来可能会实装的 CSS 特性(由于这本书买的比较早,现在看来常用的浏览器都已经支持这些新的特性了)。
这里就不再继续写了。有兴趣的同学可以买书看一下。

9. bug 和 修复 bug
10. 实例研究:Roma Italia
11. 实例研究:Climb the Mountains

Page Layout Max Width

Adjust the exact value of the page width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the page layout
A ranged slider for user to choose and customize their desired width of the maximum width of the page layout can go.

Content Layout Max Width

Adjust the exact value of the document content width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the content layout
A ranged slider for user to choose and customize their desired width of the maximum width of the content layout can go.