css进阶:flex

Flexbox

CSS 提供了许多工具和属性,可用于在网页上定位元素。Codecademy 的课程**「盒模型(box model)」「CSS display」**介绍了一些基本的布局技术。

在本课程中,你将学习弹性盒布局(Flexible Box Layout,简称 flexbox) ,这是一种可以极大简化元素定位的工具。

Flexbox 布局的两个重要组成部分:

  1. Flex 容器(flex container): 页面上的某个元素,它包含flex 项目(flex items)
  2. Flex 项目(flex items): Flex 容器的所有直接子元素。

重要区别:本课程中介绍的某些属性适用于flex 容器 ,而其他属性适用于flex 项目,这一点需要特别注意!

如何定义一个 Flex 容器?

只需将某个元素的 display 属性设置为 flexinline-flex,该元素就会成为 Flex 容器

一旦一个元素成为 Flex 容器,就可以使用多个属性来控制其子元素的行为。

本课程将介绍以下 Flexbox 属性:

justify-content
align-items
flex-grow
flex-shrink
flex-basis
flex
flex-wrap
align-content
flex-direction
flex-flow

Flexbox 是一个强大且优雅的工具,它可以轻松解决许多以往难以处理的布局问题。

display: flex

Flex 容器是创建响应式网页 的有力工具,它可以根据屏幕大小的变化自动调整布局。Flex 容器的子元素(flex items)会根据其父容器的大小和位置进行调整,从而实现灵活的布局。

任何元素都可以成为 Flex 容器

如何定义一个 Flex 容器?

要让某个元素成为 Flex 容器 ,需要将它的 display 属性设置为 flex

css 复制代码
div.container {
  display: flex;
}

在上面的示例中,所有 class="container"div 元素都是 Flex 容器

如果它们包含子元素,这些子元素就会自动成为 Flex 项目(flex items)

Flex 容器的影响

  • 具有 display: flex;div 仍然是块级元素(block-level) ,不会与其他元素出现在同一行。
  • 但是,它的子元素不会自动换行 ,而是会按照 flex 规则排列。

在接下来的练习中,我们将详细讲解 flex 布局如何影响子元素的排列方式

inline-flex

在上一个练习中,我们观察到:当我们给 div(一个块级元素)设置 display: flex; 时,它仍然是块级元素
但如果我们希望多个 Flex 容器在同一行内显示,该怎么办?

通常,我们可以使用 display: inline;div 变为行内元素。但在 Flexbox 中,我们可以使用 display: inline-flex; ,它允许我们创建既是 Flex 容器,又是行内元素的布局。

示例 1:两个 inline-flex 容器

html 复制代码
<div class='container'>
  <p>我是 Flex 容器中的文本!</p>
  <p>Flex 容器的子元素是 Flex 项目!</p>
</div>
<div class='container'>
  <p>我也是 Flex 项目!</p>
  <p>我也是!</p>
</div>
css 复制代码
.container {
  width: 200px;
  height: 200px;
  display: inline-flex;
}
  • 这里有两个 div.container,默认情况下,它们会占满整行(块级元素的默认行为)。

  • 但是,当 display: inline-flex; 时,它们会在页面足够宽的情况下并排显示,而不是像块级元素那样换行。

  • p 元素仍然是块级元素,因此在 container 内是垂直排列的。

示例 2:子元素超出父容器

html 复制代码
<div class='container'>
  <div class='child'>
    <h1>1</h1>
  </div>
  <div class='child'>
    <h1>2</h1>
  </div>
</div>
css 复制代码
.container {
  width: 200px;
}

.child {
  display: inline-flex;
  width: 150px;
  height: auto;
}

解析:

  • child 容器的总宽度 = 150px + 150px = 300px,超出了 container 容器的 200px。
  • inline-flex 默认会让子元素缩小,以适应父容器的大小
  • 这个行为与 flex-shrink 相关,后面的课程会进一步讲解如何控制子元素的缩放。

justify-content

在之前的练习中,当我们将父容器的 display 值设置为 flexinline-flex 时,所有子元素(即 flex 项目)默认都会移动到父容器的左上角。这是 flex 容器及其子元素的默认行为。

我们可以指定 flex 子元素在主轴(从左到右)的排列方式。关于轴的更多内容,我们将在后续练习中学习。

为了控制子元素从左到右的排列方式 ,我们可以使用 justify-content 属性。

css 复制代码
.container {
 display: flex;
 justify-content: flex-end;
}

在上面的示例中,我们将 justify-content 设置为 flex-end,这会使所有 flex 子元素向右对齐。

justify-content 的 5 个常用值:

  1. flex-start ------ 所有子元素从左侧开始依次排列,元素之间不会有额外的间距。

  2. flex-end ------ 所有子元素从右侧开始依次排列,元素之间不会有额外的间距。

  3. center ------ 所有子元素居中对齐,没有额外的间距。

  4. space-around ------ 所有子元素之间的间距相等,并且两端的间距是中间间距的一半,导致元素之间的间距比两侧的间距大一倍。

  5. space-between ------ 所有子元素的间距相等 ,但两端不会有额外的间距,即第一个元素紧贴左边,最后一个元素紧贴右边。

额外说明:

  • "没有额外的间距" 意味着 marginborder 仍然有效,但不会在元素之间添加额外的空间。

  • justify-content 只影响子元素的排列方式,不会改变每个子元素的大小。

align-items

在上一个练习中,你学习了如何使用 justify-content水平方向(主轴) 上排列 flex 容器中的子元素。同样的,我们也可以使用 align-items 在垂直方向(交叉轴) 上对齐 flex 子元素。

align-items 属性用于垂直方向上调整 flex 子元素的排列方式。

css 复制代码
.container {
 align-items: baseline;
}

在上面的示例中,align-items 被设置为 baseline,这意味着所有子元素的文本基线(baseline) 会对齐。

align-items 的 5 个常用值:

  1. flex-start ------ 所有元素对齐到父容器顶部

  2. flex-end ------ 所有元素对齐到父容器底部

  3. center ------ 所有元素的中心会对齐到父容器的垂直中间位置。

  4. baseline ------ 所有元素的文本基线(baseline) 会对齐。适用场景 :当子元素有不同的字体大小、行高或内容高度时,可以使用 baseline 让它们的文本对齐,而不是顶部或底部对齐。

  5. stretch ------ 默认值 ,元素会拉伸 ,填充整个父容器的高度(如果子元素有固定 height,则不会被拉伸;如果没有设置 height 或者有 min-height,则会拉伸)。

说明:

  • 这些值决定了子元素在 交叉轴(cross axis,默认是垂直方向) 上的排列方式。

  • 在 flex 布局中,默认的交叉轴是从上到下的方向。

  • 你可能对 min-heightmax-height 不太熟悉,但你应该用过 heightwidthmin-heightmax-heightmin-widthmax-width 这些属性可以确保元素的大小不会小于最小值,也不会超过最大值

flex-grow

练习 3 中,我们了解到当 flex 容器 太小时,所有 flex 项目(flex items) 会按比例缩小。然而,如果父容器的空间大于必要的大小,默认情况下 flex 项目不会自动伸展

flex-grow 属性 允许我们指定 flex 项目是否应该增长以填充容器 ,并且可以控制 哪些项目应该按比例增长得更多或更少

html 复制代码
<div class='container'>
  <div class='side'>
    <h1>我是 flex 容器的一侧!</h1>
  </div>
  <div class='center'>
    <h1>我是 flex 容器的中心!</h1>
  </div>
  <div class='side'>
    <h1>我是 flex 容器的另一侧!</h1>
  </div>
</div>
css 复制代码
.container {
 display: flex;
}

.side {
 width: 100px;
 flex-grow: 1;
}

.center {
 width: 100px;
 flex-grow: 2;
}

在上面的示例中:

  • .container 被设置为 display: flex; ,因此它的三个子元素(.side.center)会排列在同一行

  • 如果 .container 的宽度超过 300px (默认子元素的总宽度:100px + 100px + 100px),那么 多余的空间将会按照 flex-grow 进行分配

    • .sideflex-grow: 1;,表示它们会平均分配部分额外空间。
    • .centerflex-grow: 2;,表示它会比 .side 多吸收一倍的空间

例如,如果 .container 额外多出 60px 的空间

  • .center 会吸收 30px(2 份)。

  • 每个 .side 各吸收 15px(1 份)。

额外说明

  • 如果某个元素设置了 max-width ,即使它有 flex-grow 也不会超过最大宽度,即它不会继续增长超出 max-width 限制。

  • 之前学习的 align-itemsjustify-content 等属性是作用在父级 flex 容器 上的,而 flex-grow 是我们学习的第一个作用在 flex 子元素上的属性

flex-shrink

就像 flex-grow 属性可以按比例扩展 flex 项目 一样,flex-shrink 属性可以用于指定哪些元素会收缩以及它们收缩的比例

flex-shrink 介绍

  • 当 flex 容器的空间不足以容纳所有 flex 项目时,flex 项目会按比例缩小。
  • 默认情况下 ,即使没有显式声明 flex-shrink,flex 项目也会缩小,因为 flex-shrink 的默认值是 1
  • 但 flex 项目 不会自动增长 ,除非明确设置了 flex-grow,因为 flex-grow 的默认值是 0
html 复制代码
<div class='container'>
 <div class='side'>
   <h1>我是 flex 容器的一侧!</h1>
 </div>
 <div class='center'>
   <h1>我是 flex 容器的中心!</h1>
 </div>
 <div class='side'>
   <h1>我是 flex 容器的另一侧!</h1>
 </div>
</div>
css 复制代码
.container {
 display: flex;
}

.side {
 width: 100px;
 flex-shrink: 1;
}

.center {
 width: 100px;
 flex-shrink: 2;
}
  • flex-shrink: 1; 表示 .side 会按默认比例缩小
  • flex-shrink: 2; 表示 .center 会缩小的比例是 .side 的两倍

例如,如果 .container 的内容总宽度超出了 60px

  • .center 会缩小 30px(2 份)。

  • 每个 .side 各缩小 15px(1 份)。

额外说明

  1. flex-growflex-shrink 都不会影响 margin,也就是说,即使元素缩小或增长,它的外边距(margin)仍然保持不变。
  2. min-widthmax-width 的优先级高于 flex-shrinkflex-grow ,如果元素的 min-width 设定了最小宽度,即使 flex-shrink 设定了较高的收缩比例,该元素也不会小于 min-width 设定的值。
  3. flex-shrink 只有在 父容器空间不足时才会生效 ,也就是说,当页面窗口变小或者 flex 容器的宽度减少时,才会触发 flex-shrink 计算。

例子:

css 复制代码
.top.side {
  flex-shrink: 2;
}

效果:

可以看到两边的收缩程度是中间的二倍

css 复制代码
.middle.side {
  flex-shrink: 0;
}

可以看到两边不收缩

css 复制代码
.bottom.center {
   flex-shrink: 2;
}

可以看到中间的收缩程度是两边的二倍

flex-basis

在前两个练习中,div 的尺寸是通过 CSS 设置的高度和宽度来决定的。另一种指定 div 宽度的方式是使用 flex-basis 属性。flex-basis 允许我们在弹性项目(flex item)伸展或收缩之前,先指定它的默认大小。

html 复制代码
<div class='container'>
  <div class='side'>
    <h1>Left side!</h1>
  </div>
  <div class='center'>
    <h1>Center!</h1>
  </div>
  <div class='side'>
    <h1>Right side!</h1>
  </div>
</div>
css 复制代码
.container {
  display: flex;
}

.side {
  flex-grow: 1;
  flex-basis: 100px;
}

.center {
  flex-grow: 2;
  flex-basis: 150px;
}

在上面的示例中,如果 .container 容器的宽度刚好合适(350 像素,再加上一些 外边距(margin)边框(border) 的额外空间),那么 .side 这个类的 div 宽度会是 100 像素,而 .center 这个类的 div 宽度会是 150 像素。

如果 .container 容器的宽度更大,.center 这个 div 会比 .side 这个 div 吸收更多的额外空间,其比例为 2:1。

如果我们还给这些 div 指定了 flex-shrink 的值,那么相同的规则也适用于元素缩小时的情况。

  • flex-basis 用于指定弹性项目的 初始大小 ,即在 flex-growflex-shrink 影响它之前,它默认的宽度(在 flex-direction: row 时)或高度(在 flex-direction: column 时)。

  • 它类似于 width,但在 flexbox 布局下有更高的优先级。

属性 作用范围 受 Flexbox 影响 默认值 优先级
width 所有布局(block/inline/float/Flexbox) ❌ 不受 flex-growflex-shrink 影响 auto (在 Flexbox 下优先级低于 flex-basis
flex-basis 仅在 Flexbox 中生效 ✅ 受 flex-growflex-shrink 影响 auto (如果 flex-basiswidth 都设置,flex-basis 优先)

flex简写属性

flex 简写属性 提供了一种方便的方式来指定元素如何 伸展(grow)收缩(shrink) ,同时简化所需的 CSS 代码。

使用 flex 属性可以在 一行代码 中声明 flex-growflex-shrinkflex-basis

注意flex 属性与 display: flex 中的 flex 值不同

css 复制代码
.big {
 flex-grow: 2;
 flex-shrink: 1;
 flex-basis: 150px;
}

.small {
 flex-grow: 1;
 flex-shrink: 2;
 flex-basis: 100px;
}
  • big 类的元素 small 类的元素增长得更快 ,因为 flex-grow: 2

  • small 类的元素 big 类的元素收缩得更快 ,因为 flex-shrink: 2

简写:

css 复制代码
.big {
 flex: 2 1 150px;
}

.small {
 flex: 1 2 100px;
}

flex 属性的顺序 : 1️⃣ flex-grow

2️⃣ flex-shrink

3️⃣ flex-basis

  • 省略flex-basis
css 复制代码
.big {
 flex: 2 1;
}

这里省略了 flex-basis ,它的默认值是 auto(基于元素内容或 width)。

  • 省略 flex-shrink
css 复制代码
.small {
  flex: 1 20px;
}

这里省略了 flex-shrink ,但指定了 flex-basis: 20px

  • 你可以设置 flex-grow + flex-basis (如 1 20px)。

  • 但不能 只设置 flex-shrink + flex-basis ,因为 flex 的第二个值如果是 px,浏览器会认为它是 flex-basis

在浏览器中:

  • 窗口变宽

    • 顶部外侧的 div 宽度达到 100px 后,它们比中间的 div 增长得更快
    • 底部中间的 div 宽度达到 100px 后,它比外侧 div 增长得更快
  • 窗口变窄

    • 顶部中间的 div 缩小到 50px 后,它开始 比外侧 div 收缩得更快
    • 底部外侧的 div 缩小到 75px 后,它们开始 比中间的 div 收缩得更快

flex-wrap

有时候,我们不希望内容缩小以适应容器,而是希望 当空间不足时,子元素能够换行

这可以通过 flex-wrap 属性 来实现。

flex-wrap 的取值

作用
wrap 换行 :当子元素无法放入同一行时,它们会 自动换到下一行
wrap-reverse 反向换行 :与 wrap 类似,但 行的顺序是反向的(例如,原本在上面的行会变到下面)。
nowrap 不换行 (默认值):所有子元素会 强制保持在同一行,即使空间不足也不会换行。
html 复制代码
<div class="container">
  <div class="item">
    <h1>We're going to wrap!</h1>
  </div>
  <div class="item">
    <h1>We're going to wrap!</h1>
  </div>
  <div class="item">
    <h1>We're going to wrap!</h1>
  </div>
</div>
css 复制代码
.container {
  display: inline-flex;
  flex-wrap: wrap;
  width: 250px;
}

.item {
  width: 100px;
  height: 100px;
}
  • .container 容器 宽度是 250px

  • .item 元素 每个 100px ,三个 item300px ,超过了 250px 的容器宽度。

  • 由于 flex-wrap: wrap; 设置,第三个 item 会自动换行,出现在下面一行。

  • flex-wrap 必须在 flex 容器上声明 ,而 不能用于单个 flex 子元素

效果:

如果给.container加上justify-content: space-around

align-content 属性

当元素 换行(flex-wrap: wrap; 后,一个 Flex 容器可能会有多行子元素

在之前的学习中,我们使用了 align-items垂直对齐 单行flex 项目。

如果 flex 容器 有多行内容 ,可以使用 align-content 来调整各行在容器内的上下间距

align-content 的常见取值

作用
flex-start 所有行都靠近父容器的顶部,行与行之间没有额外间距。
flex-end 所有行都靠近父容器的底部,行与行之间没有额外间距。
center 所有行居中排列,行与行之间没有额外间距。
space-between 行与行之间均匀分布第一行在顶部,最后一行在底部,行之间的间距相等。
space-around 行均匀分布顶部、底部和行之间的间距相等
stretch(默认) 如果未设置 height,所有行将拉伸以填充整个父容器的高度

代码示例:

html 复制代码
<div class="container">
  <div class="child">
    <h1>1</h1>
  </div>
  <div class="child">
    <h1>2</h1>
  </div>
  <div class="child">
    <h1>3</h1>
  </div>
  <div class="child">
    <h1>4</h1>
  </div>
</div>
css 复制代码
.container {
  display: flex;
  width: 400px;
  height: 400px;
  flex-wrap: wrap;
  align-content: space-around;
}

.child {
  width: 150px;
  height: 150px;
}
  • .container 宽度为 400px ,但 每个 .child150px ,最多只能放 两个 child 在同一行

  • 因此,会换行形成两行

  • align-content: space-around; 使 两行均匀分布在容器内

  • 顶部、底部和两行之间的间距相等(即,行间距是顶部和底部间距的两倍)。

  • align-content 只适用于 flex-wrap: wrap;flex 容器 ,如果 nowrap(默认),这个属性无效。

  • 它对单行无效 ,单行的垂直对齐应该使用 align-items

效果:

flex-direction 属性

到目前为止,我们只讨论了 水平排列(横向)和垂直换行(纵向)的 flex 项目

前面提到过,flex 容器有两个轴

  • 主轴(main axis) :默认是 水平方向 ,用于控制 justify-contentflex-wrapflex-growflex-shrink 等属性的表现。
  • 交叉轴(cross axis) :默认是 垂直方向 ,用于控制 align-itemsalign-content 等属性的表现。

主轴和交叉轴是 可以互换的 ,我们可以使用 flex-direction 属性来改变它们的方向。

例如,如果 flex-direction 的值是 column,那么 主轴将变为垂直方向 ,所有 flex 项目将按照 从上到下 的顺序排列,而不是默认的 从左到右

html 复制代码
<div class="container">
  <div class="item">
    <h1>1</h1>
  </div>
  <div class="item">
    <h1>2</h1>
  </div>
  <div class="item">
    <h1>3</h1>
  </div>
  <div class="item">
    <h1>4</h1>
  </div>
  <div class="item">
    <h1>5</h1>
  </div>
</div>
css 复制代码
.container {
  display: flex;
  flex-direction: column;
  width: 1000px;
}

.item {
  height: 100px;
  width: 100px;
}
  • 默认情况下,这 5 个 div 可以在同一行内水平排列 ,但 flex-direction: column; 强制它们按照垂直方向排列

  • justify-contentalign-items 的行为会受到 flex-direction 影响,例如:

    • 如果 flex-direction: row;justify-content 影响 水平方向align-items 影响 垂直方向
    • 如果 flex-direction: column;justify-content 影响 垂直方向align-items 影响 水平方向

效果:

将container(父元素)的height:600px改为height:600px后:

使用flex布局时,子元素会在max-height约束下自适应分配空间

  • 默认情况下,max-height 限制的是父级的最大高度,子元素会自然适应

  • 如果子元素 height 是固定的,则不会随父级 max-height 变化,可能会溢出或浪费空间。

将父元素的align-items设置为center后:

flex-flow

flex 这样的简写属性一样,flex-flow 也是一个简写属性,用于同时声明 flex-wrapflex-direction 属性。

css 复制代码
.container {
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
}

在上面的示例中,我们用了两行代码来实现的效果,其实可以用一行代码完成:

css 复制代码
.container {
  display: flex;
  flex-flow: column wrap;
}

在上面的示例中,flex-flow 声明的第一个值是 flex-direction,第二个值是 flex-wrap。所有 flex-directionflex-wrap 的取值都可以用于 flex-flow

注意: flex-flow 属性是应用在 flex 容器 上的。

嵌套flexbox

到目前为止,我们在同一页面上使用了多个 flex 容器来探索 flex 项目的定位。实际上,我们也可以在 flex 容器内部再嵌套 flex 容器。

html 复制代码
<div class='container'>
  <div class='left'>
    <img class='small' src='#'/>
    <img class='small' src='#'/>
    <img class='small' src='#' />
  </div>
  <div class='right'>
    <img class='large' src='#' />
  </div>
</div>
css 复制代码
.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

.left {
  display: inline-flex;
  flex: 2 1 200px;
  flex-direction: column;
}

.right {
  display: inline-flex;
  flex: 1 2 400px;
  align-items: center;
}

.small {
  height: 200px;
  width: auto;
}

.large {
  height: 600px; 
  width: auto;
}

在上面的示例中,左侧的 div.left)内包含三张小图片,这些图片会 从上到下排列右侧的 div.right)包含一张大图片,位于页面的右侧

  • .leftflex-basis 较小 ,但在额外空间分配时会 伸展得更多
  • .rightflex-basis 较大 ,但在额外空间分配时会 伸展得较少
  • 这两个 div 既是 flex 容器,又是 flex 项目
  • 它们的 父容器(.container 定义了它们的排列方式,而 它们自身也可以影响内部 flex 子元素的排列方式

我们将使用相同的格式来布局右侧的简单页面。

你已经学会了 Flexbox 最重要的属性。Flexbox 既是一门艺术,也是一门科学;你可以用它轻松地布局多个元素。现在,你已经掌握了使用 Flexbox 进行布局所需的一切知识,并可以在自己的项目中开始使用它了。

  • display: flex 将元素变成一个 块级 容器,并且其子元素会成为 Flex 项目
  • display: inline-flex 允许多个 Flex 容器在 同一行 内并排显示。
  • justify-content 用于 沿主轴 排列和分布子元素。
  • align-items 用于 沿交叉轴 进行对齐。
  • flex-grow 用于指定 子元素如何按比例扩展 以填充主轴上的剩余空间。
  • flex-shrink 用于指定 子元素在主轴上如何按比例缩小
  • flex-basis 用于指定 子元素的初始大小 ,它与 flex-growflex-shrink 共同决定元素的最终尺寸。
  • flexflex-growflex-shrinkflex-basis 的简写,可在一个声明中设置多个属性。
  • flex-wrap 指定 如果 Flex 容器空间不足 ,子元素是否应该 换行
  • align-content 用于 沿交叉轴 调整 多行 内容的间距。
  • flex-direction 用于指定 主轴和交叉轴的方向
  • flex-flowflex-wrapflex-direction 的简写,可以在 一行代码 中同时设置这两个属性。
  • 嵌套 Flex 容器 :可以在 Flex 容器的子元素再次声明 display: flexdisplay: inline-flex ,从而实现 嵌套布局

现在,让我们应用你学到的一些属性,在浏览器中排列网页的某个部分吧!

相关推荐
LaoZhangAI18 分钟前
【2025最新】Claude免费API完全指南:无需信用卡,中国用户也能用
前端
hepherd37 分钟前
Flask学习笔记 - 模板渲染
前端·flask
LaoZhangAI37 分钟前
【2025最新】Manus邀请码免费获取完全指南:5种稳定渠道+3个隐藏方法
前端
经常见38 分钟前
浅拷贝与深拷贝
前端
前端飞天猪43 分钟前
学习笔记:三行命令,免费申请https加密证书📃
前端
关二哥拉二胡44 分钟前
前端的 AI 应用开发系列二:手把手揭秘 RAG
前端·面试
斯~内克1 小时前
前端图片加载性能优化全攻略:并发限制、预加载、懒加载与错误恢复策略
前端·性能优化
奇怪的知识又增长了1 小时前
Command SwiftCompile failed with a nonzero exit code Command SwiftGeneratePch em
前端
Maofu1 小时前
从React项目 迁移到 Solid项目的踩坑记录
前端
薄荷味1 小时前
ubuntu 服务器安装 docker
前端