CSS 布局

209 阅读10分钟

CSS 布局

简介

CSS 中有多种布局方法,实现页面布局的主要方法是设定 display 属性的值,该属性可以控制元素在页面上的显示方式。文档流中所有的内容都有一个 display 的值,用作元素的默认行为方式。这里列举几种常见的方法

  • 正常流
  • 弹性盒
  • 网格
  • 多列布局
  • 浮动
  • 定位
  • 响应式设计

正常流

正常流(Normal flow,又称文档流)是 CSS 布局的基础,即当没有对元素应用浮动(floats)、定位(positioning)或者现代布局技术(如 Flexbox 或 Grid)时,浏览器默认的布局方式。正常流分为两个方面:块级元素(block-level elements)布局和行内元素(inline-level elements)布局。

  1. 块级元素布局:

块级元素在正常流中独占一行,并在其上下生成新行。它们沿着垂直方向一个接一个地排列,按照它们在 HTML 文档中出现的顺序。宽度默认填满其父元素的剩余水平空间,但可以通过设置 widthmax-width 来修改。高度由内容、内边距(padding)和边框(border)决定,可以使用 heightmin-height 进行调整。常见的块级元素有 <div><p><h1>-<h6><ul><ol><li> 等。

  1. 行内元素布局:

行内元素在正常流中与其他行内元素一起排列在同一行上,从左到右。如果容器的宽度不足以容纳所有行内元素,那么它们会自动换行。行内元素的宽度和高度由内容、内边距和边框决定,不能直接设置 widthheight 属性。常见的行内元素有 <span><a><img><em><strong> 等。

对于网页内的大部分元素,正常流完全可以创建所需要的布局,因此一个结构良好的 HTML 文档是非常必要的。当遇到复杂布局问题时,也可以通过下列布局技术覆盖默认的布局行为:

  1. Display

使用 display 属性可以控制元素的显示类型。如:block, inline, inline-block 或其他新增的布局方式(如:CSS Grid 和 Flexbox)。

  1. Float

使用 float 属性设置元素向左 (float: left) 或向右 (float: right) 浮动,浮动元素会脱离正常文档流,并根据空间自动调整位置。然后,其他元素将沿着被浮动元素的边缘排列。 然而,当一个父元素包含浮动的子元素时,通常会发生高度塌陷现象,这意味着父元素不会自动扩展其高度以适应浮动子元素。结果就是页面布局出现错误,可能导致相邻的元素发生重叠,这时就需要清除浮动。清除浮动 (Clearfix) 是一个常用技术,用于消除浮动元素对其父元素和其他元素的影响。

以下是一个经典的 clearfix 解决方案:

.clearfix::after {
  content: "";
  display: table;
  clear: both;
}

要使用 clearfix,只需将它添加到包含浮动元素的父元素的类(class)上,父元素的高度将自动扩展以适应浮动的子元素,从而解决高度塌陷问题。

<div class="parent clearfix">
  <div class="child" style="float: left;"></div>
  <div class="child" style="float: left;"></div>
</div>
  1. Positioning

使用 position 属性,允许你精准设置盒子中的盒子的位置;可以将元素定位到相对于其正常位置、相对于其最近的定位祖先元素或相对于视口的特定位置;有四个值:static(默认值)、relativeabsolutefixed,使用 toprightbottomleft 属性设置具体的偏移。

  1. Table

表格的布局方式可以用在非表格内容上,使用 display: table 可以将元素布局为表格,这在某些场景下非常实用。tabletable-rowtable-cell 分别对应 HTML 的 <table><tr><td> 元素。

  1. Multi-column layout

使用多列布局方法,可以将内容分为多个列,就像报纸或杂志上的文本那样。将 column-countcolumn-gap 属性分别设置为所需的列数和列间距。

弹性盒

弹性盒子(Flexible Box,简称 Flexbox)是一种 CSS 布局模型,用于在一维空间(即行或列)内更灵活地对齐和分布元素,Flexbox 能够自动调整元素的大小和顺序,使其适应不同屏幕尺寸和分辨率。Flexbox 是一个强大且灵活的布局工具,特别适用于响应式设计和对齐方式复杂的场景。要使用 Flexbox,需要将 display 属性设置为 flexinline-flex(行内弹性盒子)。

.container {
  display: flex;
}

Flexbox 模型分为 弹性盒(flex container)、 弹性子项(flex item)、主轴(main axis)和 交叉轴(cross axis);

设置了 display: flex 的父元素称为弹性盒,而在弹性盒中表现为弹性盒子的元素称之为弹性子项;主轴是沿着 flex 元素放置的方向延伸的轴(如页面上的横向的行、纵向的列);交叉轴是垂直于 flex 元素放置方向的轴。

在布局时可以使用以下 Flexbox 属性来进行控制:

  1. flex-direction 指定主轴的方向,决定了弹性子项如何排列。可选值有 row(默认值,水平排列)、row-reversecolumn(垂直排列)和 column-reverse

  2. justify-content:控制沿主轴的对齐方式。可选值有 flex-start(起点对齐,这是默认值)、flex-end(终点对齐)、center(居中对齐)、space-between(两侧对齐,子项之间间距相等)、space-around(每个子项两侧间距相等)和 space-evenly(子项之间和两边边界的间距相等)。

  3. align-items:控制沿交叉轴的对齐方式。可选值有 stretch(默认值,拉伸占满容器高度)、flex-start(起点对齐)、flex-end(终点对齐)、center(居中对齐)和 baseline(基线对齐)。

  4. flex-wrap:控制是否以多行(或多列)方式排列子项。可选值有 nowrap(默认值,不换行)和 wrap(换行)。

  5. align-content:当存在多行(或多列)时,控制行(或列)之间的对齐方式。可选值有 stretch(默认值,拉伸占满容器高度)、flex-start(起点对齐)、flex-end(终点对齐)、center(居中对齐)、space-between(两侧对齐,行之间间距相等)、space-around(每行两侧间距相等)和 space-evenly(行之间和容器边界的间距相等)。

对于每个弹性子项,还可以设置以下属性:

  1. order:控制子项的排列顺序。默认值为 0,数字越小,排列越靠前。

  2. flex-grow:设置子项的扩展比例。默认值为 0,表示不扩展。若所有子项的 flex-grow 相同,则它们将平均分配剩余空间;若值不同,则按照比例分配剩余空间。

  3. flex-shrink:设置子项的收缩比例。默认值为 1,表示子项会根据比例收缩以适应容器。若值为 0,则表示子项不收缩。

  4. flex-basis:设置子项的基础尺寸,在此基础上进行扩展和收缩。默认值为 auto,表示使用子项的实际尺寸。

  5. align-self:允许单独设置某个子项在交叉轴上的对齐方式,覆盖容器的 align-items 设置。可选值与 align-items 相同。

网格

CSS 网格布局(CSS Grid Layout)是一个用于 web 的二维布局系统,可以把内容按照行与列的格式进行排版。这种布局方式有助于简化复杂的页面设计,轻松地实现一些复杂的布局,并提高响应式设计效率。

网格是由一系列水平及垂直的线构成的一种布局模式。一个网格通常具有许多的列(column)与行(row),以及行与行、列与列之间的间隙,这个间隙一般被称为沟槽(gutter);根据网格,我们能够将设计元素进行排列,帮助我们设计一系列具有固定位置以及宽度的元素的页面,使我们的网站页面更加统一。

创建一个 CSS 网格布局,需要先将一个父容器元素的 display 属性设置为 grid

.container {
  display: grid;
}

同时可以使用一些关键的 CSS 属性来定义网格布局

  1. grid-template-columnsgrid-template-rows: 用于定义网格的列和行大小。可以用像素、百分比或者 fr(用于描述剩余空间的单位)来设置网格轨道(grid track)的尺寸。例如:grid-template-columns: 1fr 200px 3fr; 定义了一个三列网格,第一列和第三列分别占据剩余空间的 1/4 和 3/4,而第二列宽度固定为 200px。

  2. grid-column-gapgrid-row-gap: 用于设置网格间距。例如:grid-column-gap: 16px; grid-row-gap: 16px;。还可以用 grid-gap 这个简化属性同时设置行和列的间距,如:grid-gap: 16px 24px;(这里,16px 为行间距,24px 为列间距)。

  3. grid-template-areas: 这个属性用于为网格项定义区域名称并映射到网格布局中。例如:

.container {
  grid-template-areas:
    "header header header"
    "sidebar content content"
    "footer footer footer";
}

可以利用 grid-area 属性将网格项目分配给相应的区域:

.header {
  grid-area: header;
}
.sidebar {
  grid-area: sidebar;
}
.content {
  grid-area: content;
}
.footer {
  grid-area: footer;
}
  1. justify-itemsalign-items:控制所有网格项沿水平轴(主轴)和垂直轴(交叉轴)的对齐方式。可用值包括 startendcenterstretch(默认值,使元素填满整个网格单元)。

  2. justify-contentalign-content:当网格容器的大小大于网格内容时,这两个属性用于控制整个网格在容器里的位置。

针对单个网格项,可以使用以下属性进行布局:

  1. grid-column-startgrid-column-endgrid-row-startgrid-row-end:这些属性定义了网格项的起始和结束位置。例如:grid-column-start: 2; grid-column-end: 4; 表示该项从第二列开始,并延伸至第四列。

  2. grid-columngrid-row:这是简化属性,它们分别用于设置网格项的列起始/结束位置和行起始/结束位置。例如:grid-column: 2 / 4;(与上述示例等效)。

  3. grid-area:用于设置网格项的行和列起始/结束位置,或将网格项分配到 grid-template-areas 中定义的区域。

多列布局

CSS 多列布局(Multi-column Layout)是一种让文本或其他内容自动流动并跨越多列的布局方法,这种布局方式类似于报纸或杂志中的排版,使得阅读长篇文字更加舒适

可以使用以下 CSS 属性来实现多列布局:

  1. column-count:指定布局中的列数。例如,设置 column-count: 3; 将文本分为三列。
.container {
  column-count: 3;
}
  1. column-width:定义每一列的理想宽度。浏览器将尽量满足这个要求,但具体宽度可能会有所调整以适应容器的宽度。例如,设置 column-width: 200px; 将尝试确保每列宽度至少为 200px。
.container {
  column-width: 200px;
}

注意:column-countcolumn-width 可以同时使用,但如果它们产生冲突(即给定的宽度和数量无法适应容器大小),浏览器将优先考虑 column-count

  1. column-gap:定义相邻列之间的间距。可以使用像素、百分比等单位。例如,设置 column-gap: 20px; 将在列之间保持 20px 的间距。
.container {
  column-gap: 20px;
}
  1. column-rule:在相邻列之间绘制一条分隔线。这个属性是一个简写,可设置分隔线的宽度、样式和颜色。例如:column-rule: 1px solid #ccc; 将添加一条 1px 宽且颜色为灰色的实线。
.container {
  column-rule: 1px solid #ccc;
}
  1. columns:这是一个简写属性,用于同时设置 column-countcolumn-width。例如:columns: 3 200px; 将尝试创建三列,每列宽度至少为 200px。
.container {
  columns: 3 200px;
}

创建一个多列布局,只需将上述属性应用到包含文本或内容的父容器上。示例:

<div class="container">
  <p>只需将上述属性应用到父容器上</p>
</div>
.container {
  columns: 3 200px;
  column-gap: 20px;
  column-rule: 1px solid #ccc;
}

上面用例将把段落文本分成三列,每列至少宽 200px,列间距为 20px,并在列之间添加一个分隔线。