CSS常用布局技巧汇总 | 青训营

234 阅读16分钟

CSS布局

在前端实际应用开发中免不了会遇到大量的UI布局问题,本次的文章总结了常用的CSS布局技巧,希望可以对大家的开发有些许帮助。

什么是CSS布局?

在开始前,我们先来介绍一下什么是CSS布局。

CSS 页面布局技术允许我们拾取网页中的元素,并且控制它们相对正常布局流、周边元素、父容器或者主视口/窗口的位置。

简而言之,CSS布局决定了页面上各个元素的摆放方式,以及它们在不同屏幕尺寸和设备上的呈现效果。其最终目标便是创建一个有组织美观易于导航响应式的页面。

CSS布局涉及的主要概念和技术包括:

  • 盒模型:每个HTML元素都是一个盒子,包含内容、内边距、边框和外边距。盒模型定义了这些部分的尺寸和间距。

  • 流动布局:默认情况下,HTML元素会在页面上从左到右、从上到下依次排列。这种排列方式称为流动布局。

  • 定位:通过定位属性(如position)可以将元素相对于其正常流位置进行移动。常见的定位方式有相对定位、绝对定位和固定定位。

  • 浮动:浮动元素会从正常的流动布局中脱离出来,使其他元素可以环绕在其周围。浮动通常用于创建多列布局。

  • Flexbox布局Flexbox是一种弹性盒模型,通过display: flex和相关属性,可以实现在一维空间内的灵活布局,使元素沿主轴和交叉轴排列。

  • Grid布局Grid布局是二维网格系统,通过display: grid和相关属性,可以实现复杂的布局,将页面划分为行和列,进行精确的定位和对齐。

  • 响应式设计:随着不同屏幕尺寸和设备的出现,布局需要能够适应不同的视口。响应式设计通过媒体查询和弹性单位(如百分比、emrem)来实现元素的自适应排列和尺寸。

  • 层叠顺序:通过z-index属性,可以控制元素的层叠顺序,使某些元素位于其他元素之上或之下。

  • 媒体查询:媒体查询允许根据不同的媒体特性(如屏幕宽度、设备类型等)应用不同的样式,以实现响应式布局。

在实际的应用开发中,我们会用到各种各样的布局技巧,本文将着重介绍几个常用的布局技巧。

浮动布局(float)

属性简介

CSS中,浮动布局是一种早期用于创建多列布局的技术。虽然由于其一些缺点和复杂性,其基本已被如FlexboxGrid的现代布局方式取代了。不过在某些特定的情况下,还是可以利用浮动布局的属性快速实现一些简单的业务需求。

以下简要介绍一些与浮动布局相关的属性:

  • float: 用于指定元素应该浮动在其容器的左侧或右侧,可以取值为 "left"、"right" 或 "none"。
  • clear: 用于控制元素在浮动元素旁边显示的方式。可以取值为 "left"、"right"、"both" 或 "none"。

应用实例

这是一个基于浮动的多栏布局示例,通过设置三个栏目的宽度为33.33%和浮动来实现。这种布局适用于创建简单的多列布局,比如新闻网站的导航和内容区域。

<div class="column1">左侧栏</div>
<div class="column2">主内容区</div>
<div class="column3">右侧栏</div>
.column1,.column2,.column3 {
    float: left;
    width: 33.33%;
    box-sizing: border-box;
    border: 1px solid #ccc;
    padding: 10px;
}

image.png

此外,可以通过设置clear属性来清除浮动,以下为clear属性作用在不同元素下的效果展示:

.column2 {
    clear: left;
}

image.png

.column3 {
    clear: left;
}

image.png

在最后,还是强烈建议使用更现代的布局技术,如FlexboxGrid,来创建更灵活和可维护的布局。这些技术提供了更直观和强大的布局能力,以及更少的副作用和兼容性问题。

弹性盒子布局(flexbox)

属性介绍

弹性盒子布局(Flexbox)是一种用于在一维空间内进行布局的CSS技术,可以方便地创建灵活的、响应式的布局结构。以下是弹性盒子布局的一些主要属性:

  • display: flex;

    • 通过将容器的 display 属性设置为 flex,将容器变为弹性盒子容器,其子元素将成为弹性盒子项目。
  • flex-direction: row | row-reverse | column | column-reverse;

    • 定义弹性盒子内子元素的排列方向。
    • row(默认):从左到右排列(水平排列)。
    • row-reverse:从右到左排列(水平排列)。
    • column:从上到下排列(垂直排列)。
    • column-reverse:从下到上排列(垂直排列)。
  • flex-wrap: nowrap | wrap | wrap-reverse;

    • 定义是否允许子元素换行。
    • nowrap(默认):不换行,子元素会在一行内尽可能排列。
    • wrap:允许子元素换行,溢出容器的子元素会在新行上排列。
    • wrap-reverse:允许子元素换行,但反向排列。
  • justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;

    • 定义子元素在主轴上的对齐方式。
    • flex-start(默认):靠主轴起始边对齐。
    • flex-end:靠主轴末尾边对齐。
    • center:在主轴上居中对齐。
    • space-between:在子元素之间均匀分布空间,首个子元素靠主轴起始边,末尾子元素靠主轴末尾边。
    • space-around:在子元素周围均匀分布空间,包括首尾子元素两侧的空间。
    • space-evenly:在子元素周围以相等的间距分布空间。
  • align-items: flex-start | flex-end | center | baseline | stretch;

    • 定义子元素在交叉轴上的对齐方式。
    • flex-start:靠交叉轴起始边对齐。
    • flex-end:靠交叉轴末尾边对齐。
    • center:在交叉轴上居中对齐。
    • baseline:按照第一行文本的基线对齐。
    • stretch(默认):子元素在交叉轴上被拉伸以填充容器。
  • align-content: flex-start | flex-end | center | space-between | space-around | stretch;

    • 定义多根轴线的对齐方式(当有多行或列的情况下)。
    • flex-start:靠交叉轴起始边对齐。
    • flex-end:靠交叉轴末尾边对齐。
    • center:在交叉轴上居中对齐。
    • space-between:在轴线之间均匀分布空间。
    • space-around:在轴线周围均匀分布空间。
    • stretch(默认):轴线被拉伸以填充容器。
  • flex: none | [flex-grow] [flex-shrink] [flex-basis];

    • 缩写属性,用于定义弹性盒子项目的放大比例、缩小比例和初始大小。
    • flex-grow:定义项目的放大比例,默认为0,不放大。
    • flex-shrink:定义项目的缩小比例,默认为1,允许缩小。
    • flex-basis:定义项目的初始大小,默认为auto,即根据内容决定。

应用实例

以下示例展示了使用弹性盒子布局创建一个自适应的水平项目列表,项目之间平均分布,适用于导航栏、按钮组等。

<div class="container">
    <div class="item">项目1</div>
    <div class="item">项目2</div>
    <div class="item">项目3</div>
</div>
.container {
    display: flex;
    justify-content: space-between;/* 在容器内,项目沿主轴上均匀分布,两端留有空白间距 */
    align-items: center;/* 在容器内,项目在交叉轴上居中对齐 */
    border: 1px solid #ccc;
}
.item {
    flex: 1;/* 弹性盒子项目会根据剩余空间等比例分配剩余空间 */
    margin: 10px;
    padding: 20px;
    border: 1px solid #ccc;
}

image.png

通过设置flex-direction属性可以改变排列方向(需注意此时主轴方向变换,justify-content不再表示水平方向,而应表示为垂直方向排列规则)。

.container {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    border: 1px solid #000;
}

image.png

设置flex-wrap属性进行换行,在同行(列)剩余空间不足摆放多一个时可以进行自动换行,同时设置flex动态尺寸(这里我们默认设置为1,表示等分),实现响应式布局。

.container {
    display: flex;
    justify-content: space-between;
    flex-wrap:wrap;
    border: 1px solid #000;
}
.item {
    flex: 1;
    margin: 10px;
    padding: 20px 100px;
    border: 1px solid #000;
    text-align: center;
}

image.png

由于其简单高效的布局功能,Flexbox可以说是实际开发中最受欢迎的高级布局技巧了,利用好Flexbox可以实现高效布局并且兼具响应式的特点。

网格布局(grid)

属性介绍

在网页中创建复杂的二维布局时,Grid布局是一个不错的选择。Grid布局将一个容器分割成行和列,然后将内容放置到这些行和列中,从而创建灵活的网格式布局。以下简要介绍一些与网格布局相关的属性:

  • display: grid;

    • 通过将容器的 display 属性设置为 grid,将容器变为网格容器,其子元素将成为网格项目。
  • grid-template-columns 和 grid-template-rows:

    • 用于定义网格的列和行的大小和数量。
    • grid-template-columns:指定列的大小和数量。
    • grid-template-rows:指定行的大小和数量。
    • 例如:grid-template-columns: 100px 200px 1fr; 表示有三列,分别为 100px、200px 和剩余空间的一等分。
  • grid-gap 或 grid-row-gap 和 grid-column-gap:

    • 用于设置网格项目之间的间距。
    • grid-gap:同时设置行和列之间的间距。
    • grid-row-gap:设置行之间的间距。
    • grid-column-gap:设置列之间的间距。
  • grid-template-areas:

    • 允许通过指定区域名称的方式来定义网格布局。
    • 通过创建一个区域名称的矩阵,然后在网格项目中使用 grid-area 属性来引用这些区域名称,从而构建布局。
  • grid-auto-columns 和 grid-auto-rows:

    • 用于设置没有被显示定义的隐式网格轨道的大小。
    • grid-auto-columns:定义未显示定义的列的大小。
    • grid-auto-rows:定义未显示定义的行的大小。
  • grid-auto-flow: row | column | dense;

    • 定义网格项目如何自动排列。
    • row:按照行顺序自动排列。
    • column:按照列顺序自动排列。
    • dense:尽可能紧凑地填充空白单元格。
  • grid-column 和 grid-row:

    • 用于将网格项目放置到指定的行和列上。
    • 通过指定起始和结束的网格线编号或区域名称来定义位置。
  • justify-items 和 align-items:

    • 分别定义网格项目在单元格内的水平和垂直对齐方式。
  • justify-content 和 align-content:

    • 分别定义网格容器的内容在容器内的水平和垂直对齐方式。

应用实例

这个示例使用网格布局在容器中创建了一个三列项目布局,简单展示了Grid布局的基本功能。Grid布局适用于呈现项目、产品展示等。

<div class="grid-container">
    <div class="grid-item">1</div>
    <div class="grid-item">2</div>
    <div class="grid-item">3</div>
    <div class="grid-item">4</div>
    <div class="grid-item">5</div>
    <div class="grid-item">6</div>
</div>
.grid-container {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr; /* 3列,中间列宽度是其他列的两倍 */
    grid-template-rows: 100px 200px;/*  声明行的高度  */
    grid-gap: 20px;/*  同时声明行间隙和列间隙  */
}
.grid-item {
    display: grid;
    padding: 20px;
    border: 1px solid #000000;
    justify-items: center; /* 在单元格内水平居中对齐 */
    align-items: center; /* 在单元格内垂直底部对齐 */
}

image.png

除此之外我们也可以通过设置grid-columngrid-row等属性为元素分割区域。

<div class="grid-container">
    <header>header</header>
    <aside>aside</aside>
    <article>article</article>
    <footer>footer</footer>
</div>
.grid-container {
   display: grid;
   grid-template-columns: repeat(3,1fr);
   grid-template-rows: 100px 200px;
   grid-gap: 20px;
}
header,aside,article,footer {
   padding: 20px;
   border: 1px solid #000;
}
header {
  grid-column: 1 / 4; /* 跨越整个网格的第1列到第4列 */ 
  grid-row: 1; /* 占据第1行 */
}
article {
   grid-column: 2/4;
   grid-row: 2;
}
aside {
   grid-column: 1/2;
   grid-row: 2;
}
footer {
   grid-column: 1 / 4;
   grid-row: 3;
}

image.png

同时,在属性的声明时,我们也可以使用minmax()repeat()函数及auto-fill属性实现响应式布局。

.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  grid-auto-rows: minmax(100px, auto);
  grid-gap: 20px;
}

image.png

虽然在实际开发中很多人可能会因为上手难度更低选择Flexbox,但是单论能力的话,Grid布局可以说是最强的。如果大家对Grid布局感到兴趣,并想深入学习,[推荐](最强大的 CSS 布局 —— Grid 布局 - 掘金 (juejin.cn))

定位布局(position)

属性介绍

定位布局允许你从正常的文档流布局中取出元素,并使它们具有不同的行为,例如放在另一个元素的上面,或者始终保持在浏览器视窗内的同一位置。

定位布局在实现对话框、提示框等弹出式元素时作用显著,且在一些特殊的排版场景下必不可少。以下列举了主要的定位属性:

  • 静态定位(Static): 这是元素的默认定位方式,元素按照文档流正常排列。静态定位的元素不会受到定位属性的影响。
  • 相对定位(Relative): 相对定位使元素相对于其正常位置进行定位,但不会影响其他元素的布局。可以通过设置 toprightbottomleft 属性来调整元素的位置。
  • 绝对定位(Absolute): 绝对定位使元素相对于最近的已定位祖先元素(非静态定位)进行定位。如果没有定位的祖先元素,元素将相对于文档的初始点进行定位。绝对定位的元素不会占据正常的文档流空间,通过设置 toprightbottomleft 属性来精确定位。
  • 固定定位(Fixed): 固定定位使元素相对于浏览器视口进行定位,即使页面滚动,该元素也会保持在固定位置。可以通过设置 toprightbottomleft 属性来进行定位。
  • 粘性定位(Sticky): 粘性定位是相对定位和固定定位的结合,元素在滚动时表现为相对定位,但当滚动达到特定阈值时,元素会变为固定定位。这在创建导航栏等效果时非常有用。

其中相对定位(relative)不会脱离文档流(元素依然占据原本的空间

<div class="container">
    <div class="item">1</div>
    <div class="item positioned">2</div>
    <div class="item">3</div>
</div>
.container {
    position: relative;
    display: flex;
    justify-content: space-between;
    flex-wrap:wrap;
    border: 1px solid #000;
}
.item {
    flex: 1;
    margin: 10px;
    padding: 20px 100px;
    border: 1px solid #000;
    text-align: center;
}
.positioned {
    position: relative;
    top: 10px;
    left: 10px;
    background: #ccc;
}

image.png

而绝对定位(absolute)和固定定位(fixed)会脱离文档流(元素不会占据布局的空间),其中后两者的区别在于绝对定位相对于最近的已定位祖先元素(此处为container元素)。

.positioned {
    position: absolute;
    top: 10px;
    left: 10px;
    background: #ccc;
}

image.png

而固定定位对于浏览器视口进行定位。

.positioned {
    position: fixed;
    top: 10px;
    left: 10px;
    background: #ccc;
}

image.png

此外粘性定位则可以在相对定位和绝对定位之间进行转换。

<header>导航栏</header>
<div class="container">
    <div>内容</div>
</div>
.container {
    position: relative;
    height: 150vh;
    overflow: visible;
    border: 1px solid #000;
}

header {
    width: 100%;
    height: 50px;
    position: sticky;
    top: 0px;
    background: #ccc;
}

相对定位: image.png

绝对定位: image.png

过度使用定位可能会导致布局混乱,因此在实际项目中需要谨慎使用(能使用Flexboxgrid布局解决的问题就不要使用定位布局)。

层叠(z-index)

定位布局还有一个重要的属性:z-index(层叠),用于控制元素在堆叠上下文中的垂直层次关系。当元素发生重叠时,z-index 可以确定哪个元素位于另一个元素之上或之下。

使用z-index的一些要领::

  • 值的范围和含义: z-index 属性接受整数值和 auto 值。整数值越大,元素在堆叠上下文中就越靠近顶部,而负值会使元素移动到堆叠上下文的底部。auto 值表示元素的堆叠顺序由其在文档流中的位置决定。
  • 在定位元素中使用: z-index 通常在定位(position: absoluteposition: relativeposition: fixed)元素中使用。定位元素才能参与堆叠上下文,非定位元素的 z-index 设置不会产生效果。
  • 父子关系: 父元素的 z-index 值会影响其子元素。子元素的 z-index 值相对于父元素而言,这意味着即使子元素的 z-index 较高,但如果父元素的 z-index 较低,那么子元素仍然无法覆盖父元素之外的其他内容。
  • 层叠上下文: 每个元素都会创建一个层叠上下文。具有较高 z-index 值的层叠上下文会覆盖具有较低 z-index 值的层叠上下文中的内容。层叠上下文的形成受到多种因素的影响,包括定位属性、透明度、过渡等。
  • 相对层叠顺序: z-index 只在相同的层叠上下文中才有意义。不同层叠上下文的元素无论其 z-index 值如何,都无法跨越不同层叠上下文中的元素。

以下示例演示了如何使用z-index属性和定位来创建叠放效果,如此应用可以使前景元素浮在背景元素上方,从而产生立体感。

<div class="back">背景元素</div>
<div class="front">前景元素</div>
.back {
    z-index: 1;
    position: relative;
    background-color: #f2f2f2;
    padding: 20px;
    margin: 10px;
}
.front {
    z-index: 2;
    position: relative;
    top: -20px;
    left: 20px;
    background-color: #fff;
    padding: 10px;
    border: 1px solid #ccc;
}

image.png

虽然,z-index可以很好地控制元素在垂直层叠上下文中的显示顺序,但是过度使用和不正确的使用可能会导致预期之外的结果。因此,在使用z-index前,一定要理解元素之间的关系,以便正确地控制页面元素的显示层次。

媒体查询(@media)

媒体查询允许开发者根据设备的特性和屏幕尺寸应用不同的样式规则,创建响应式的网页设计,以适应不同设备和视口尺寸,从而提供更好的用户体验。

媒体查询的主要思想是根据媒体特性设置条件,如果这些条件满足,就会应用特定的样式规则。常见的媒体特性包括屏幕宽度、高度、设备方向、分辨率、媒体类型等。以下简单介绍使用媒体查询的步骤:

  1. 在样式表中定义媒体查询: 使用@media规则来定义媒体查询,指定要应用样式的条件。
  2. 设置媒体查询条件:@media规则内部,使用媒体特性和相关值来设置应用样式的条件。例如,可以根据最大宽度或最小分辨率来设置条件。
  3. 在条件满足时应用样式: 在满足媒体查询条件时,样式规则就会生效,从而实现适应不同设备和屏幕尺寸的布局和外观变化。

以下示例展示了如何通过媒体查询在小屏幕设备上调整盒子的颜色,以确保内容在不同屏幕尺寸下的展示效果。

<div class="container">
    <div class="box">盒子内容</div>
</div>
.box {
    width: 100%;
    padding: 20px;
    border: 1px solid #ccc;
}
@media screen and (max-width: 768px) {
    .box {
        background-color: #ccc;
    }
}

当屏幕宽度小于768px时:

image.png

当屏幕宽度大于768px时:

image.png

媒体查询是构建响应式设计的关键工具,使开发者能够根据不同的设备和屏幕尺寸提供适当的样式和布局,以确保网页在各种环境下都能良好地呈现。为了更好地进行响应式开发中,学会媒体查询的技能必不可少。