【译】掌握 Flexbox 的终极指南:从烤肉串到鸡尾酒香肠的布局哲学

🔗 原文链接:An Interactive Guide to Flexbox

👨‍💻 原作者:Josh W. Comeau

📅 发布时间:2022年11月22日,最后更新:2025年5月9日
⚠️ 关于本译文

本文基于 Josh W. Comeau 的原文进行忠实翻译,力求准确传达原作者的技术观点和逻辑结构。

🎨 特色亮点:

  • 保持原文的完整性和技术准确性
  • 采用自然流畅的中文表达,避免翻译腔
  • 添加画外音板块,提供译者的补充解读和实践心得
  • 使用生动比喻帮助理解复杂概念

💡 画外音说明: 文中标注为画外音的部分是译者基于实际开发经验添加的拓展解释,旨在帮助读者更好地理解和应用这些概念,不代表原作者观点。

🖼️ 关于交互式示例: 本文中的图片和交互式演示以截图和GIF动图形式呈现。如需体验完整的交互式功能,建议前往原文进行实际操作。

🚀 简介

Flexbox 是一种非常强大的布局模式。当我们真正理解它如何工作时,就能构建出能自动响应、按需重排列的动态布局。

例如,看看这个例子:

这个演示深受 Adam Argyle 那个令人惊艳的 "4 layouts for the price of 1" CodePen 的启发。它没有使用任何媒体查询或容器查询。它并非通过设置任意断点,而是使用流体原则来创建一个能无缝流动的布局。

相关 CSS 代码:

css 复制代码
form {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 16px;
}
.name {
  flex-grow: 1;
  flex-basis: 160px;
}
.email {
  flex-grow: 3;
  flex-basis: 200px;
}
button {
  flex-grow: 1;
  flex-basis: 80px;
}

我记得以前看到这种演示时完全懵逼。我知道 Flexbox 的基础,但这玩意儿看起来简直像魔法!✨

在这篇博文里,我想精炼你对 Flexbox 的心智模型。 我们会通过学习每个属性来建立对 Flexbox 算法的直觉。无论你是 CSS 新手,还是用了好几年 Flexbox 的老手,我打赌你都会学到不少东西!

走起!🎉

⚠️ Content warning(内容警告)

在本教程后面我会用到一个与食物相关的比喻。🍖


📚 Flexbox 简介

CSS 由许多不同的布局算法组成,官方称它们为"布局模式(layout modes)"。每种布局模式都是 CSS 中的一个小子语言。默认的布局模式是流式布局(Flow layout),但我们可以通过在父容器上改变 display 属性来启用 Flexbox。

当我们把 display 切换为 flex 时,就创建了一个flex 格式化上下文(flex formatting context)。这意味着默认情况下,所有子元素都会依据 Flexbox 布局算法被摆放。

🔔画外音

这里作者用了一个很形象的比喻,把不同的布局模式比作不同的"子语言",这确实很贴切。每种布局模式都有自己的规则和特性,就像不同的编程语言一样。)

每个布局算法都是为了解决特定问题而设计的。默认的"Flow"布局是为了创建数字文档(digital documents);它本质上就是类似 Microsoft Word 的布局算法。标题和段落垂直堆叠,而像文本、链接和图片之类的内容则在这些块级元素内部静静存在。

那么,Flexbox 解决的是什么问题?Flexbox 专注于在一行或一列中排列一组项目,并给我们大量控制这些项目分布和对齐方式的能力。正如名字所示,Flexbox 是关于"灵活性"的。我们可以控制项目是否增长或收缩、如何分配多余空间,等等。

Is it still relevant?(它仍然适用吗?)

你可能会想:既然 CSS Grid 在现代浏览器中已经得到了很好的支持,Flexbox 是否已过时?

CSS Grid 是一个很棒的布局模式,但它解决的问题与 Flexbox 不同。我们应该都学会这两种布局模式,并在合适的场景使用合适的工具。

当涉及到动态、流体的 UI(在垂直或水平方向排列的列表)时,Flexbox 仍然是王者。在本指南里我们会看到一个例子 ------ 分解的煎饼(deconstructed pancake),这并不容易用 CSS Grid 来完成。

说实话,即便我同时熟悉 Grid 和 Flexbox,我仍然经常选择 Flexbox!


🔄 Flex direction(方向)

如前所述,Flexbox 的重点是控制元素在行或列中的分布。默认情况下,子元素会在一行里并排放置,但我们可以通过 flex-direction 将其改为列:

  • flex-direction: row 时,主轴(primary axis)水平运行,从左到右。
  • flex-direction: column 时,主轴垂直运行,从上到下。

在 Flexbox 中,一切都基于主轴(primary axis)。算法并不关心垂直/水平行/列这些表面概念------所有规则都是围绕主轴和垂直于主轴的交叉轴(cross axis)构建的。

这很酷。当我们掌握了 Flexbox 的规则后,就可以在水平布局和垂直布局之间无缝切换。所有规则会自动适配。这个特性是 Flexbox 所独有的。

子元素默认会按照下面两条规则进行定位:

  • 主轴:子元素会聚拢在容器的起点。
  • 交叉轴:子元素会拉伸以填满整个容器。

在 Flexbox 中,我们决定主轴是水平还是垂直运行。这是所有 Flexbox 计算的基础。


🎯 Alignment(对齐)

我们可以使用 justify-content 来改变子元素沿主轴的分布:

当谈到主轴时,我们通常不会单独考虑对齐一个子元素,而是考虑整组元素的分布。

我们可以把所有项目堆到某个位置(flex-startcenterflex-end),也可以把它们分散(space-betweenspace-aroundspace-evenly)。

对于交叉轴,我们用 align-items

有趣的是......align-itemsjustify-content 有一些相同的选项,但并不完全一致。

为什么不共享相同选项?我们稍后会揭开这个谜团,但在那之前,我需要再分享一个对齐相关的属性:align-self

justify-contentalign-items 不同,align-self 应用于子元素,而不是容器。它允许我们改变某个特定子元素沿交叉轴的对齐方式:

align-self 拥有与 align-items 相同的值。事实上,它们改变的是完全相同的东西。align-items 是语法糖,一个便捷的写法,会自动把对齐设置应用到所有子元素上。

没有 justify-self*。要理解为什么没有,就得深入 Flexbox 算法了。


🍖 Content vs. items(内容组 vs 单个项目)

根据到目前为止学到的内容,Flexbox 可能显得有些任意。为什么是 justify-contentalign-items,而不是 justify-itemsalign-content

更进一步,为什么有 align-self,但没有 justify-self

这些问题指向了 Flexbox 中一个非常重要且常被误解的点。为了解释这一点,我要用一个比喻。

在 Flexbox 中,项目沿主轴分布。默认情况下,它们会并排排列。我可以画一条直线,把所有子元素都"串"起来,就像串烤肉串(kebab)一样:

交叉轴则不同。一条垂直线只会穿过其中一个子元素。它更像是一组鸡尾酒小香肠(cocktail wieners,一口大小的热狗/维也纳香肠):

这里有一个显著的差别。对交叉轴而言,每个项目可以沿着自己的签子独立移动,而不会影响其他项目

但对主轴而言,所有项目被同一根大签子串着,一个项目在主轴上移动会挡到别的项目。试想拖动中间那块往左右移动:

🔔画外音

这个烤肉串和鸡尾酒小香肠的比喻真的很巧妙!它完美地解释了为什么主轴和交叉轴的行为如此不同。主轴上的项目必须作为一个整体来考虑,而交叉轴上的项目可以独立调整。

这是主轴 / 交叉轴之间最根本的区别。当我们在交叉轴上谈论对齐时,每个项目都可以单独移动;而在主轴上,我们只能以组(group)的方式来考虑如何分配空间。

这就是为什么没有 justify-self 。如果让中间那块设置 justify-self: flex-start,那意味着什么?前面已经有个别的项目在那儿了!

带着这些背景,我们给下面四个术语下一个准确的定义:

  • justify --- 在主轴上定位某些东西。
  • align --- 在交叉轴上定位某些东西。
  • content --- 可被分配的内容组。
  • items --- 能被单独定位的单个项目。

所以:我们有 justify-content 来控制主轴上这一组内容的分布;我们有 align-items 来控制每个项目在交叉轴上的定位。这是我们用来管理 Flexbox 布局的两个主要属性。

没有 justify-items 的原因与没有 justify-self 的原因相同:在主轴上,我们必须把项目当作内容组来考虑,而不是单个项目。

align-content 呢?实际上,Flexbox 中确实存在 align-content!我们会在讨论 flex-wrap 属性时讲到它。


💡 Hypothetical size(假设尺寸)

让我们谈谈一个让我醍醐灌顶的认识。

假设我写了下面的 CSS:

css 复制代码
.item {
  width: 2000px;
}

一个理性的人可能会说:"好吧,我们会得到一个 2000 像素宽的元素。"但这在任何情况下都成立吗?

我们来测试一下:

有意思吧?

这两个元素有完全相同的 CSS:每个都设置了 width: 2000px。但第一个元素比第二个要宽很多!

区别在于布局模式。第一个元素在流式布局下渲染,在流式布局中,width 是一个硬性约束 。当我们设置 width: 2000px 时,我们就会得到一个 2000 像素宽的元素,即使它得突破视口边界。

而在 Flexbox 中,width 属性被以不同的方式实现。它更像是一个建议,而不是硬性约束

规范为此有一个名称:假设尺寸(hypothetical size) 。它是一个元素在理想世界中会是什么大小的度量------也就是没有任何限制时的尺寸。

可惜现实往往不同。在这个例子里,限制因素是父容器没有足够空间容纳一个 2000px 的子元素。因此,子元素的尺寸会被缩小以适配。

这是 Flexbox 哲学的核心。东西是流动且灵活的,会根据世界的约束做出调整。

🔔画外音

这个概念真的很重要!很多开发者会困惑为什么设置了 width 但元素没有按预期显示。理解"假设尺寸"这个概念,就能明白 Flexbox 的灵活性本质!
Inputs for the algorithms(算法的输入)

我们倾向于把 CSS 看成属性的集合,但我认为这是不准确的心智模型。正如我们看到的,width 属性的行为会根据使用的布局模式不同而不同!

相反,我更喜欢把 CSS 看成一组布局模式。每个布局模式是一个算法,可以实现或重新定义每个 CSS 属性。我们通过写 CSS 声明(键/值)来给算法提供输入(就像给函数传参)。算法会决定如何使用这些输入。

换句话说,我们写的 CSS 是这些算法的输入。若要真正熟悉 CSS,仅仅学属性名称是不够的;我们要学习算法如何使用这些属性。

这也是我在课程《CSS for JavaScript Developers》中采取的核心理念。不是让你记一堆难懂的 CSS 片段,而是把语言的引擎盖掀开,让你了解所有布局模式是如何工作的。


📈 Growing and shrinking(增长与收缩)

到目前为止,我们看到了 Flexbox 算法的某些内置灵活性(比如假设尺寸)。但要真正理解 Flexbox 的流动性,我们需要讨论三个属性:flex-growflex-shrinkflex-basis

下面逐一讲解这些属性。

📐 flex-basis

老实说:很长一段时间我并不太懂 flex-basis 的真正含义。😅

简单来说:在一个 Flex 行(Flex row)中,flex-basis 的作用和 width 一样;在一个 Flex 列(Flex column)中,flex-basis 的作用和 height 一样。

如前所述,Flexbox 中的一切都以主轴/交叉轴为基准。例如,justify-content 会沿主轴分配子元素,它在主轴为水平或垂直时表现一致。

widthheight 并不遵循这个规则:width 总是影响水平尺寸,它不会在 flex-directionrow 切到 column 时自动变成 height

因此,Flexbox 的作者引入了一个通用的"尺寸"属性 flex-basis。它类似于 widthheight,但被钉在主轴方向上(和 Flexbox 的其它属性一致)。它允许我们为元素在主轴方向设定假设尺寸,无论主轴是水平还是垂直。

试试这个效果:每个子元素都设了 flex-basis: 50px,但你可以调整第一个子元素的值来观察差异。

width 一样,flex-basis 更像是建议而不是硬约束。当空间不足以让所有元素按其设定尺寸显示时,算法会让它们妥协以避免溢出。

Not exactly the same(并非完全相同)

在通常情况下,在 Flex 行中 widthflex-basis 可以互换使用,但也有例外。例如,width 会以不同方式影响替换元素(replaced elements 例如图片)与 flex-basis;另外,width 能把元素缩小到低于其最小尺寸,而 flex-basis 则不能。

虽然这些细节超出了本文的讨论范围,但我还是想提一下,因为你可能会遇到这两个属性产生不同效果的边缘情况。

📈 flex-grow

默认情况下,在 Flex 环境下,元素会缩小到它们在主轴方向上的最小舒适大小。这样常常会产生多余空间。

我们可以用 flex-grow 指定这些空间该如何被消耗:

flex-grow 的默认值是 0,这意味着增长是需要显式启用的。如果我们想让某个子元素吞噬容器中的多余空间,就必须明确告诉它。

如果多个子元素同时设置了 flex-grow,那么额外空间将按它们的 flex-grow 值按比例分配。

举例说明会更直观。把每个子元素的 flex-grow 值增减试试:

上图解释如下:第一个子元素想要 3 个单位的额外空间,而第二个子元素想要 2 个单位。这意味着单位总数是 5(3 + 2)。每个子元素都会按比例获得那部分额外空间。

🔔画外音

flex-grow 的比例分配机制真的很巧妙!它让布局变得非常灵活,我们可以精确控制每个元素应该获得多少额外空间。

📉 flex-shrink

在我们到目前为止看到的大多数例子都是容器有额外空间。但如果子元素对容器来说太大怎么办?

来试试缩小容器看看发生什么:

有意思吧?两个元素都被缩小了,但它们是按比例缩小的。第一个元素总是第二个元素宽度的 2 倍。

友情提醒:flex-basis 在 Flex 行中起到的作用与 width 一样。我们这里用 flex-basis,因为这是约定俗成的用法,但如果用 width,结果也是一致的!

flex-basiswidth 设定了元素的假设尺寸。虽然 Flexbox 算法可能会把元素缩小到低于这个建议尺寸,但默认情况下,它们会一起按比例缩放,从而保持它们之间的比例关系。

但如果我们不希望元素按比例缩小怎么办?这就是 flex-shrink 的作用所在。

花几分钟时间戳这个演示。看看你是否能弄清楚这里发生了什么。我们将在下面探索。

好的,让我们来具体分析一下:我们有两个子元素,每个都有 250px 的假设尺寸。容器需要至少 500px 宽才能让这些子元素按假设尺寸显示。

现在假设我们将容器缩小到 400px。显然,我们不能把 500px 的内容硬塞进 400px 的空间里!我们面临着 100px 的赤字。元素们总共需要放弃 100px 才能适配。

flex-shrink 属性让我们决定如何分配这个赤字。

就像 flex-grow 一样,它也是按比例工作的。默认情况下,两个子元素都有 flex-shrink: 1,所以每个子元素承担一半的赤字。它们各自放弃 50px,实际尺寸从 250px 缩小到 200px。

现在,假设我们将第一个子元素的 flex-shrink 调到 3:

我们仍然有 100px 的总赤字。通常情况下,每个子元素会承担一半,但因为我们调整了 flex-shrink,第一个元素最终承担 3/4(75px),第二个元素承担 1/4(25px)。

注意绝对值并不重要,关键在于比例关系。如果两个子元素都设为 flex-shrink: 1,每个子元素会承担总赤字的一半。如果两个子元素都设为 flex-shrink: 1000,每个子元素会承担总赤字的 1000/2000。无论哪种情况,最终结果都是相同的。

收缩和比例

在我们刚才看的示例中,两个 Flex 子元素具有相同的假设尺寸(250px)。在计算如何收缩它们时,我们可以仅凭 flex-shrink 来计算。

不过,正如我们之前看到的,收缩算法也会尽力保持兄弟元素之间的比例。如果第一个子元素是第二个子元素大小的 2 倍,它会收缩得更积极。

因此,完整的计算会同时考虑每个子元素的相对 flex-shrink 值以及它们相对的尺寸。
🔔画外音

这里作者用了一个很形象的比喻------"不能将 500px 的内容塞进 400px 的袋子里",这让我们更容易理解为什么需要 flex-shrink 来分配"赤字"。

我曾对 flex-shrink 有过一个顿悟:我们可以把它看作是 flex-grow 的"反向版本"。它们是同一枚硬币的两面:

  • flex-grow 控制当元素比容器小(有额外空间)时,如何分配剩余空间。
  • flex-shrink 控制当元素比容器大(需要收缩)时,如何移除空间。

这意味着这两个属性在任一时刻只有一个会生效:若有额外空间,flex-shrink 不起作用;若子元素过大以至需要缩小,flex-grow 不起作用。

我喜欢把它想成两个不同的世界 ------ 你不是在"地球",就是在"颠倒世界"。每个世界都有自己的规则。

🛡️ 防止收缩

有时,我们不希望某些 Flex 子元素被缩小。

这种情况我在处理 SVG 图标和形状时经常遇到。看下面的简化示例:

当容器变窄时,我们的两个圆会被压成难看的椭圆。如果我们希望它们保持圆形,该怎么办?

可以把 flex-shrink: 0 设置上去:

当把 flex-shrink 设为 0,就等于从收缩过程中"退出来"。Flexbox 算法会把 flex-basis(或 width)视作一个硬性最小限制。

下面是这个示例的完整代码(以下只是部分截图,感兴趣请直接查看原文):

更简单的方法?

我在课程里教这个概念时,有人会问:为什么我们要用 flex-shrink,而不是用更简单的方法?

css 复制代码
.item.ball {
  min-width: 32px;
}

几年前我会同意这个想法。如果设了最小宽度,元素就不会被缩小到下面去!我们通过添加一个硬限制来替代 width / flex-basis 的软限制。

但我现在觉得在很多情形下,把 flex-shrink: 0 设上去才是更直接、更明了的解决方案。当然,min-width 在 Flexbox 算法中仍然有重要作用!下面我们继续讲它。

⚠️ 最小尺寸陷阱

这里还有一件超级重要的事。可能是本文中最有帮助的一点!

假设我们在做一个流体的电商搜索表单:

当容器收窄到某个点,内容会溢出!

但为什么会这样?默认 flex-shrink1,而我们并没有移除它,所以搜索输入框应该可以按需缩小才对!但它偏偏不肯再缩。

这是因为,除了假设尺寸(hypothetical size),Flexbox 算法还关心另一个尺寸:最小尺寸(minimum size)

Flexbox 算法不会把子元素缩小到它的最小尺寸以下。内容会溢出而不是继续缩小,不管你把 flex-shrink 调得多大!

文本输入在不同浏览器有默认的最小尺寸(大约 170px--200px),这就是上面那个问题的根源。

在其他情况下,限制因素可能是元素内部的内容。例如,尝试调整这个容器的大小:

对于包含文本的元素,最小宽度等于最长不可换行字符串的长度。

好消息是:我们可以用 min-width 改写最小尺寸。

如果直接在 Flex 子元素上设置 min-width: 0px,我们告诉 Flexbox 算法覆盖"内建"的最小宽度。由于我们把它设为 0px,元素就可以按需收缩到任意小。

同样的技巧在 Flex 列中也适用(使用 min-height),不过这个问题在列方向出现得没那么频繁。

谨慎使用

值得注意的是,内建的最小尺寸是有用的------它作为一种护栏,防止发生更糟糕的事情。

比如说:当我们对包含文本的 Flex 子元素直接应用 min-width: 0px 时,事情可能会变得更糟

能力越大,责任越大,min-width 在 Flexbox 中是一个特别强大的属性。它不止一次让我摆脱困境,但我总是小心确保我没有让事情变得更糟。 总结一句话:min-width 是一把锋利的刀,用对了能救急,滥用就会把页面肢解。用它时要小心!
画外音

这个"最小尺寸陷阱"真的是很多开发者都会遇到的坑!特别是当使用 flex-shrink 但元素仍然不收缩时,往往就是因为最小尺寸的限制。理解这个概念能解决很多布局问题。


📏 间距

近年来对 Flexbox 最大的体验改进之一就是 gap 属性的加入:

gap 允许我们在每个 Flex 子元素之间创建间距。这对像导航头部这样的场景特别适用:

gap 是 Flexbox 语言中相对较新的补充,但自 2021 年初以来已在现代浏览器中得到广泛实现


🎯 自动边距

还有一个与间距相关的技巧想要分享。它从 Flexbox 早期就存在,但相对冷门,当我第一次发现时简直震惊。

margin 通常用于在特定元素周围添加空间。在某些布局模式(如流式布局和定位布局)中,它甚至可以用来居中元素(margin: auto)。

在 Flexbox 中,自动外边距更有意思:

我们之前看到 flex-grow 能吞噬多余空间,把它分配给子元素。

自动外边距会吞噬多余空间,但把它应用到元素的外边距上。它让我们能精确控制多余空间该分配到哪里。

常见的头部布局是:左侧是 logo,右侧是一些导航链接。下面是利用自动外边距实现该布局的方式(请到原文查看完整实现):

把公司 Logo 放在列表的第一个项,通过给它 margin-right: auto,把所有额外空间收集到第一个和第二个项之间,从而把导航推到右侧。

我们可以在浏览器开发工具中看到发生了什么:

当然还有很多其他方法可以解决这个问题:把导航链接分组到自己的 Flex 容器,或者用 flex-grow 让第一个列表项增长。但我个人很喜欢自动外边距的方案。它把多余空间当成资源,让我们决定把资源放到哪儿。

画外音

自动边距真的是一个很巧妙的技巧!它让我们可以精确控制额外空间的分布,这在很多布局场景中都非常有用。


🔄 换行

呼!到现在为止我们已经覆盖了很多内容。最后还有一个重要的收获要分享。

到目前为止,所有项目都在单行/单列里并排。flex-wrap 属性允许我们改变这一点。

看下面的例子:

大多数时候,当我们需要二维布局时,我们会去用 CSS Grid。但 Flexbox 加上 flex-wrap 仍然有它的用途!这个例子展示了"分解的煎饼(deconstructed pancake)"布局:在中等尺寸屏幕上,3 个项目会堆成一个倒三角形。

当我们设置 flex-wrap: wrap 时,项目不会被缩小到低于它们的假设尺寸 ------ 起码当换行到下一行/列是可行选项时不会被缩小。

但等等!我们的烤肉串 / 鸡尾酒香肠比喻呢?

flex-wrap: wrap 时,我们不再有那根可以串住每个项目的单一主轴线。实际上,每行(或每列)都变成了它自己的小型 Flex 容器。不是一根大串,而是每一行各有一根小串:

我们学过的规则在这个缩小的范围内依旧适用。比如 justify-content 会在每行内分配项目。

但是......那 align-items 在有多行时会怎样?交叉轴可能会穿过多行项!

想一想会发生什么。当你有答案(或至少有了猜想)后,再去验证看看:

每一行现在都是自己的迷你 Flexbox 环境。align-items 会让每个项目在包围该行的隐形盒子内上下移动。

但如果我们想要对行本身进行对齐怎么办?那时就用 align-content

总结如下:

  • flex-wrap: wrap 让我们有两行项目。
  • 在每行内部,align-items 让每个单独的子元素上下移动。
  • 放大视角看,我们有多行处于同一个 Flex 上下文中!交叉轴现在会穿过多行。因此我们不能单独移动某一行,我们要以组(content)的形式分配它们的位置。
  • 使用我们前面定义的术语:这时我们处理的是 content(内容),而不是 items(项目)。而又因为这是在交叉轴上,所以使用 align-content

画外音

这里又回到了我们之前学到的内容组 vs 单个项目的概念!当有多行时,我们需要用 align-content 来对齐行组,而不是单个项目。这完美地展示了 Flexbox 概念的一致性。


🎉 恭喜完成!

我想承认一些事情:这是一个密集的教程。 我们已经深入兔子洞,除非你已经是 Flexbox 专家,否则我预计你的头会有点晕。😅

就像 CSS 中的很多东西一样,Flexbox 在你刚开始时可能看起来很简单,但当你超越基础时,复杂性会迅速上升。

结果,我们中的许多人在 CSS 方面遇到了早期的高原期。我们知道足够的知识来完成工作,但这是一个持续的挣扎。这种语言感觉摇摇欲坠和不可预测,就像一座古老的绳桥,随时可能断裂。当它断裂时,我们向问题投掷随机的 StackOverflow 片段,希望有什么能帮助。

这确实很糟糕,因为 CSS 是大多数前端开发工作中很重要的一部分!

事实是,CSS 实际上是一种深度健壮和一致的语言。 问题是我们大多数人的心智模型是不完整和不准确的。当我们花时间建立对语言的正确直觉时,一切都会豁然开朗,CSS 变成了绝对令人愉快使用的语言。✨

我为了解决这个问题,做了一个综合课程,叫《CSS for JavaScript Developers》

如果你觉得这篇博文有帮助,你会喜欢那门课。课程采用类似的方法,但覆盖整个 CSS 语言,并配有练习和项目,确保你能真正掌握新技能。课程专门为使用 JS 框架(如 React/Angular/Vue)的人设计。80% 的内容聚焦 CSS 基础,另外还展示了如何把这些基础整合到现代 JS 应用中、如何组织 CSS、以及其它实务内容。

如果你在 CSS 上挣扎,建议去看看。掌握 CSS 会极大提升你的开发效率,特别是当你同时熟悉 HTML 和 JS 时。三者合一,会让你更容易进入开发状态,真正享受构建应用的过程。💖


🎁 彩蛋:解析演示

在本教程开始时,我们看到了那个 4 layouts for the price of 1 的演示。

现在我们已经学了 Flexbox 算法的很多细节,你能弄懂它是怎么工作的吗?欢迎在代码中试验:

让我们逐步解析它是如何实现的(以下是一个将近 5min 的视频,无法在掘金展示,请大家进原文查看):

以上的代码示例和讲解视频请大家点进原文查看!

感谢你的阅读!这篇博文花了我很多功夫,我非常高兴它终于发布了!希望你觉得有用。💖

相关推荐
Lee川2 小时前
从异步迷雾到优雅流程:JavaScript异步编程与内存管理的现代化之旅
javascript·面试
晴殇i4 小时前
揭秘JavaScript中那些“不冒泡”的DOM事件
前端·javascript·面试
绝无仅有4 小时前
Redis过期删除与内存淘汰策略详解
后端·面试·架构
绝无仅有4 小时前
Redis大Key问题排查与解决方案全解析
后端·面试·架构
AAA梅狸猫5 小时前
Looper.loop() 循环机制
面试
AAA梅狸猫5 小时前
Handler基本概念
面试
Wect6 小时前
浏览器缓存机制
前端·面试·浏览器
掘金安东尼6 小时前
Fun with TypeScript Generics:玩转 TS 泛型
前端·javascript·面试
掘金安东尼6 小时前
Next.js 企业级落地
前端·javascript·面试
掘金安东尼7 小时前
React 性能优化完全指南 2026
前端·javascript·面试