这是用户在 2024-10-29 10:33 为 https://www.joshwcomeau.com/css/interactive-guide-to-flexbox/ 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?
Skip to content 跳至内容
JoshWComeau

An Interactive Guide to Flexbox
Flexbox 互动指南

Filed under 归入
CSS
on 关于
in
November 22nd, 2022.
2022 年 11 月 22 日
Nov 2022.
Last updated 最后更新
on 关于
in
August 24th, 2024.
2024 年 8 月 24 日
Aug 2024.
Introduction

Flexbox is a remarkably powerful layout mode. When we truly understand how it works, we can build dynamic layouts that respond automatically, rearranging themselves as-needed.
Flexbox 是一种非常强大的布局模式。当我们真正了解了它的工作原理后,就能构建自动响应的动态布局,并根据需要重新排列。

For example, check this out:
例如,看看这个:

600
Drag me! 拖着我

This demo is heavily inspired by Adam Argyle’s incredible “4 layouts for the price of 1”(opens in new tab) codepen. It uses no media/container queries. Instead of setting arbitrary breakpoints, it uses fluid principles to create a layout that flows seamlessly.
本演示深受 Adam Argyle 令人难以置信的"4 布局1价格" (在新标签页打开)codepen 的启发。它没有使用媒体/容器查询。它没有设置任意的断点,而是利用流体原理创建了一个流畅的布局。

Here's the relevant 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;
}

I remember running into demos like this and being completely baffled. I knew the basics of Flexbox, but this seemed like absolute wizardry!
我记得自己在观看这样的演示时,完全摸不着头脑。我知道 Flexbox 的基本原理,但这似乎是绝对的魔法!

In this blog post, I want to refine your mental model for Flexbox. We'll build an intuition for how the Flexbox algorithm works, by learning about each of these properties. Whether you're a CSS beginner, or you've been using Flexbox for years, I bet you'll learn quite a bit!
在本篇博文中,我希望完善您的 Flexbox 心智模型。我们将通过了解这些属性中的每一个,建立对 Flexbox 算法工作原理的直观认识。无论你是 CSS 初学者,还是使用 Flexbox 多年的老手,我打赌你都能学到不少东西!

Let's do this! 我们开始吧

Link to this headingIntroduction to Flexbox Flexbox 简介

CSS is comprised of many different layout algorithms, known officially as “layout modes”. Each layout mode is its own little sub-language within CSS. The default layout mode is Flow layout, but we can opt in to Flexbox by changing the display property on the parent container:
CSS 包含多种不同的布局算法,正式名称为 "布局模式"。每种布局模式都是 CSS 中的一种子语言。默认的布局模式是流式布局,但我们可以通过更改父容器上的display属性,选择使用 Flexbox:

Hello 您好
to 
the 
world 世界
Primary Axis 主轴
Primary Axis 主轴
display: 显示:

When we flip display to flex, we create a “flex formatting context”. This means that, by default, all children will be positioned according to the Flexbox layout algorithm.
当我们将显示方式翻转为 Flex 时,我们会创建一个 "Flex 格式上下文"。这意味着,默认情况下,所有子代都将按照 Flexbox 布局算法进行定位。

Clippy, the helpful paperclip assistant from Microsoft Word Each layout algorithm is designed to solve a specific problem. The default “Flow” layout is meant to create digital documents; it's essentially the Microsoft Word layout algorithm. Headings and paragraphs stack vertically as blocks, while things like text, links, and images sit inconspicuously within these blocks.
每种布局算法都是为解决特定问题而设计的。默认的 "Flow "布局旨在创建数字文档;它基本上是微软 Word的布局算法。标题和段落以块的形式垂直堆叠,而文本、链接和图片等内容则位于这些块中,并不显眼。

So, what problem does Flexbox solve? Flexbox is all about arranging a group of items in a row or column, and giving us a ridiculous amount of control over the distribution and alignment of those items. As the name suggests, Flexbox is all about flexibility. We can control whether items grow or shrink, how the extra space is distributed, and more.
那么,Flexbox 能解决什么问题呢?Flexbox 就是在一行或一列中排列一组项目,并赋予我们对这些项目的分布和对齐方式的极大控制权。顾名思义,Flexbox 就是灵活性。我们可以控制项目的增长或收缩,以及额外空间的分配等等。

Link to this headingFlex direction 弯曲方向

As mentioned, Flexbox is all about controlling the distribution of elements in a row or column. By default, items will stack side-by-side in a row, but we can flip to a column with the flex-direction property:
如前所述,Flexbox 就是要控制元素在一行或一列中的分布。默认情况下,项目将并排堆叠在一行中,但我们可以使用flex-direction属性翻转到一列中:

Hello 您好
to 
the 
world 世界
Primary Axis 主轴
Primary Axis 主轴
flex-direction: 柔性方向:

With flex-direction: row, the primary axis runs horizontally, from left to right. When we flip to flex-direction: column, the primary axis runs vertically, from top to bottom.
使用 "flex-direction:row"时,主轴是水平的,从左到右。当我们切换到 "flex-direction:(柔性方向)":"column"(列)时,主轴会从上到下垂直运行。

In Flexbox, everything is based on the primary axis. The algorithm doesn't care about vertical/horizontal, or even rows/columns. All of the rules are structured around this primary axis, and the cross axis that runs perpendicularly.
在 Flexbox 中,一切都基于主轴。算法并不关心垂直/水平,甚至行/列。所有规则都是围绕主轴和垂直于主轴的横轴来构建的。

This is pretty cool. When we learn the rules of Flexbox, we can switch seamlessly from horizontal layouts to vertical ones. All of the rules adapt automatically. This feature is unique to the Flexbox layout mode.
这很酷。当我们掌握了 Flexbox 的规则后,就可以从水平布局无缝切换到垂直布局。所有规则都会自动调整。这一功能是 Flexbox 布局模式所独有的。

The children will be positioned by default according to the following 2 rules:
默认情况下,孩子们将根据以下两条规则进行定位:

  1. Primary axis: Children will be bunched up at the start of the container.
    主轴:孩子们将在集装箱的起点处聚集在一起。
  2. Cross axis: Children will stretch out to fill the entire container.
    横轴:孩子们会伸展到填满整个容器。

Here's a quick visualization of these rules:
下面是这些规则的快速可视化示意图:

In Flexbox, we decide whether the primary axis runs horizontally or vertically. This is the root that all Flexbox calculations are pegged to.
在 Flexbox 中,我们决定主轴是横向还是纵向。这是所有 Flexbox 计算的根基。

Link to this headingAlignment 对齐

We can change how children are distributed along the primary axis using the justify-content property:
我们可以使用justify-content属性更改子代沿主轴的分布方式:

Hello 您好
to 
the 
World 世界
Primary Axis 主轴
Primary Axis 主轴
row 行数
flex-start 弹性启动

When it comes to the primary axis, we don't generally think in terms of aligning a single child. Instead, it's all about the distribution of the group.
说到主轴,我们一般不会考虑对齐一个子轴。取而代之的是组的分布。

We can bunch all the items up in a particular spot (with flex-start, center, and flex-end), or we can spread them apart (with space-between, space-around, and space-evenly).
我们可以将所有项目集中在一个特定的位置(使用 "弹性起点"、"弹性 中心"和 "弹性终点"),也可以将它们分散开来(使用 "间距-间距"、" 距-环绕"和 "间距-均匀")。

For the cross axis, things are a bit different. We use the align-items property:
横轴的情况则有些不同。我们使用align-items属性:

Hello 您好
to 
the 
World 世界
Primary Axis 主轴
Primary Axis 主轴
row 行数
flex-start 弹性启动
stretch 伸长

It's interesting… With align-items, we have some of the same options as justify-content, but there isn't a perfect overlap.
有趣的是......对于align-items,我们有一些justify-content 相同的选项,但并不完全重合。

justify-content
align-items
flex-startcenterflex-end

Why don't they share the same options? We'll unravel this mystery shortly, but first, I need to share one more alignment property: align-self.

Unlike justify-content and align-items, align-self is applied to the child element, not the container. It allows us to change the alignment of a specific child along the cross axis:
justify-contentalign-items 不同,align-self适用于子元素,而不是容器。它允许我们改变特定子元素沿横轴的对齐方式:

Hello 您好
to 
the 
world 世界
Primary Axis 主轴
Primary Axis 主轴
row 行数
stretch 伸长

align-self has all the same values as align-items. In fact, they change the exact same thing. align-items is syntactic sugar, a convenient shorthand that automatically sets the alignment on all the children at once.
align-self 的值与align-items 完全相同。事实上,它们改变的是完全相同的东西。align-items语法糖,是一种方便的速记法,可以自动一次性设置所有子代的对齐方式。

There is no justify-self
没有 justify-self *
At least, not in Flexbox. The property is implemented in the Grid layout mode.. To understand why not, we need to dig deeper into the Flexbox algorithm.
.要理解为什么不能,我们需要深入研究 Flexbox 算法。

Link to this headingContent vs. items 内容与项目

So, based on what we've learned so far, Flexbox might seem pretty arbitrary. Why is it justify-content and align-items, and not justify-items, or align-content?
因此,根据我们目前所学到的知识,Flexbox 似乎很武断。为什么是justify-contentalign-items,而不是justify-itemsalign-content

For that matter, why is there an align-self, but not a justify-self??
那么,为什么有 "对齐的自我",却没有 "辩解的自我 "呢?

These questions get at one of the most important and misunderstood things about Flexbox. To help me explain, I'd like to use a metaphor.
这些问题涉及 Flexbox 最重要也是最容易被误解的一点。为了解释清楚,我想用一个比喻来说明。

In Flexbox, items are distributed along the primary axis. By default, they're nicely lined up, side-by-side. I can draw a straight horizontal line that skewers all of the children, like a Meat on a stick. AKA skewers, souvlaki, shish-kabob:
在 Flexbox 中,项目沿主轴分布。默认情况下,它们是并排整齐排列的。我可以画一条水平直线,将所有子项串起来,就像一样

Illustration of a kebab: 3 pieces of meat horizontally skewered on a wooden stick. The stick is labeled 'Primary axis'

The cross axis is different, though. A straight vertical line will only ever intersect one of the children.
但横轴是不同的。一条垂直直线只会与其中一个子线相交。

It's less like a kebab, and more like a group of Bite-sized hot dogs / vienna sausages:

3 separate cocktail wieners, each with their own toothpick skewering them vertically. The toothpicks are labeled 'cross axis'

There's a significant difference here. With the cocktail wieners, each item can move along its stick without interfering with any of the other items:

Drag me! 拖着我

By contrast, with our primary axis skewering each sibling, a single item can’t move along its stick without bumping into its siblings! Try dragging the middle piece side to side:
相比之下,由于我们的主轴向每个兄弟姐妹倾斜,单个物品无法在不撞到兄弟姐妹的情况下沿着主轴移动!试着左右拖动中间部分:

This is the fundamental difference between the primary/cross axis. When we're talking about alignment in the cross axis, each item can do whatever it wants. In the primary axis, though, we can only think about how to distribute the group.
这就是主轴/横轴的根本区别。当我们在横轴上讨论对齐问题时,每个项目都可以为所欲为。而在主轴中,我们只能考虑如何分配

That's why there's no justify-self. What would it mean for that middle piece to set justify-self: flex-start? There's already another piece there!
这就是为什么没有 "证明-自我"中间那块设置为justify-self:flex-start 意味着什么?那里已经有另一块了!

With all of this context in mind, let's give a proper definition to all 4 terms we've been talking about:
有了这些背景,让我们来给我们一直在谈论的这四个术语下一个正确的定义:

  • justify — to position something along the primary axis.
    对齐- 沿主轴定位。
  • align — to position something along the cross axis.
    对齐- 沿横轴定位。
  • content — a group of “stuff” that can be distributed.
    内容--一组可以分发的 "东西"。
  • items — single items that can be positioned individually.
    项目- 可单独定位的单个项目。

And so: we have justify-content to control the distribution of the group along the primary axis, and we have align-items to position each item individually along the cross axis. These are the two main properties we use to manage layout with Flexbox.

There's no justify-items for the same reason that there's no justify-self; when it comes to the primary axis, we have to think of the items as a group, as content that can be distributed.

What about align-content? Actually, this does exist within Flexbox! We'll cover it a little later on, when we talk about the flex-wrap property.

Link to this headingHypothetical size 假设尺寸

Let's talk about one of the most eye-opening realizations I've had about Flexbox.
让我们来谈谈我对 Flexbox 的一个最直观的认识。

Suppose I have the following CSS:
假设我有以下 CSS:

.item {
  width: 2000px;
}

A reasonable person might look at this and say: “alright, so we'll get an item that is 2000 pixels wide”. But will that always be true?
一个理智的人看到这里可能会说:"好吧,我们将得到一个 2000 像素宽的项目"。但事实总是如此吗?

Let's test it: 让我们来测试一下:

Code Playground 代码游乐场

Result 结果

This is interesting, isn't it?
这很有趣,不是吗?

Both items have the exact same CSS applied. They each have width: 2000px. And yet, the first item is much wider than the second!
两个项目都应用了完全相同的 CSS。它们的宽度都是:2000px。然而,第一个项目比第二个项目宽得多!

The difference is the layout mode. The first item is being rendered using Flow layout, and in Flow layout, width is a hard constraint. When we set width: 2000px, we'll get a 2000-pixel wide element, even if it has to burst through the side of the viewport like the Horrifying North American cartoon character known for bursting through walls.
区别在于布局模式。第一个项目是使用 Flow 布局呈现的,而在 Flow 布局中,宽度是一个硬约束。当我们设置width: 2000px 时,我们将得到一个 2000 像素宽的元素,即使它必须像一样从视口的一侧冲出

In Flexbox, however, the width property is implemented differently. It's more of a suggestion than a hard constraint.
但在Flexbox 中,宽度属性的实现方式有所不同。它更像是一种建议,而不是硬性约束。

The specification has a name for this: the hypothetical size. It's the size an element would be, in a perfect utopian world, with nothing getting in the way.
规范对此有一个名称:假设尺寸。这是在一个完美的乌托邦世界,在没有任何阻碍的情况下,一个元素的尺寸。

Alas, things are rarely so simple. In this case, the limiting factor is that the parent doesn't have room for a 2000px-wide child. And so, the child's size is reduced so that it fits.
唉,事情很少这么简单。在这种情况下,限制因素是父代没有空间容纳一个 2000px 宽的子代。因此,缩小了子代的尺寸,使其能够适应。

This is a core part of the Flexbox philosophy. Things are fluid and flexible and can adjust to the constraints of the world.
这是 Flexbox 理念的核心部分。事物是流动的、灵活的,可以根据世界的限制进行调整。

Link to this headingGrowing and shrinking 增长和萎缩

So, we've seen that the Flexbox algorithm has some built-in flexibility, with hypothetical sizes. But to really see how fluid Flexbox can be, we need to talk about 3 properties: flex-grow, flex-shrink, and flex-basis.
因此,我们已经看到 Flexbox 算法具有一定的内置灵活性,可以使用假设的尺寸。但要真正了解 Flexbox 的灵活性,我们还需要了解 3 个属性:flex-growflex-shrink 和 flex-basis

Let's look at each property.
让我们来看看每个属性。

Link to this headingflex-basis 灵活基础

I admit it: for a long time, I didn't really understand what the deal was with flex-basis. 😅
我承认:很长时间以来,我都不太明白弹性基础怎么回事。😅

To put it simply: In a Flex row, flex-basis does the same thing as width. In a Flex column, flex-basis does the same thing as height.
简单地说:在 Flex 行中,flex-basis的作用与宽度相同。在 Flex 列中,flex-basis的作用与高度相同。

As we've learned, everything in Flexbox is pegged to the primary/cross axis. For example, justify-content will distribute the children along the primary axis, and it works exactly the same way whether the primary axis runs horizontally or vertically.
正如我们已经了解到的,Flexbox 中的一切都与主轴/横轴挂钩。例如,justify-content将沿主轴分配子代,而且无论主轴是水平还是垂直,其工作方式都完全相同。

width and height don't follow this rule, though! width will always affect the horizontal size. It doesn't suddenly become height when we flip flex-direction from row to column.
不过,宽度高度并不遵循这一规则!宽度始终会影响水平尺寸。当我们将柔性方向 从行翻转到列时,宽度不会突然变成高度

And so, the Flexbox authors created a generic “size” property called flex-basis. It's like width or height, but pegged to the primary axis, like everything else. It allows us to set the hypothetical size of an element in the primary-axis direction, regardless of whether that's horizontal or vertical.
因此,Flexbox 的作者创建了一个名为flex-basis 的通用 "尺寸 "属性。它类似于宽度高度,但与其他属性一样,与主轴挂钩。它允许我们设置元素在主轴方向上的假定尺寸,而不管是水平方向还是垂直方向。

Give it a shot here. Each child has been given flex-basis: 50px, but you can tweak the first child:
在这里试一试。每个子代都有flex-basis:50px,但你可以调整第一个子代:

Primary Axis 主轴
Primary Axis 主轴
flex-direction: 柔性方向:
350

Like we saw with width, flex-basis is more of a suggestion than a hard constraint. At a certain point, there just isn't enough space for all of the elements to sit at their assigned size, and so they have to compromise, in order to avoid an overflow.
就像我们看到的宽度一样,flex-basis更像是一种建议,而不是硬性约束。在某一点上,没有足够的空间让所有元素都达到指定的大小,因此它们必须妥协,以避免溢出。

Link to this headingflex-grow

By default, elements in a Flex context will shrink down to their minimum comfortable size along the primary axis. This often creates extra space.
默认情况下,Flex 上下文中的元素会沿主轴缩小到最小舒适尺寸。这通常会产生额外的空间。

We can specify how that space should be consumed with the flex-grow property:
我们可以使用flex-grow属性来指定消耗空间的方式:

Extra Space 额外空间
Primary Axis
Primary Axis
flex-direction:
flex-grow:

The default value for flex-grow is 0, which means that growing is opt-in. If we want a child to gobble up any extra space in the container, we need to explicitly tell it so.

What if multiple children set flex-grow? In this case, the extra space is divvied up between children, proportionally based on their flex-grow value.

I think it'll be easier to explain visually. Try incrementing/decrementing each child:

flex-grow:
1
2
flex-grow:
1
2
Primary Axis
Primary Axis

The first child wants 1 unit of extra space, while the second child wants 1 unit. That means the total # of units is 2 (1 + 1). Each child gets a proportional share of that extra space.

Link to this headingflex-shrink 弹性收缩

In most of the examples we've seen so far, we've had extra space to work with. But what if our children are too big for their container?
在我们目前看到的大多数例子中,我们都有额外的空间可以利用。但是,如果我们的孩子对他们的容器来说太大了怎么办?

Let's test it. Try shrinking the container to see what happens:
让我们来测试一下。试着缩小容器,看看会发生什么:

flex-basis 灵活基础
300px
Actual size: 实际尺寸:
300px
Reduced by: 减少:
0%
flex-basis 灵活基础
150px
Actual size: 实际尺寸:
150px
Reduced by: 减少:
0%
Primary Axis 主轴
Primary Axis 主轴
600

Interesting, right? Both items shrink, but they shrink proportionally. The first child is always 2x the width of the second child.
有趣吧?两个项目都会缩小,但它们是按比例缩小的。第一个子项的宽度始终是第二个子项宽度的 2 倍*。
You might see some rounding issues that suggest it's off by a pixel or two. This is likely a flaw with my overengineered demo!

As a friendly reminder, flex-basis serves the same purpose as width. We'll use flex-basis because it's conventional, but we'd get the exact same result if we used width!
友情提示:flex-basis的作用与width 相同。我们使用flex-basis是因为它很传统,但如果我们使用width,也会得到完全相同的结果

flex-basis and width set the elements' hypothetical size. The Flexbox algorithm might shrink elements below this desired size, but by default, they'll always scale together, preserving the ratio between both elements.

Now, what if we don't want our elements to scale down proportionally? That's where the flex-shrink property comes in.

Take a couple of minutes and poke at this demo. See if you can figure out what's going on here. We'll explore below.

flex-basis
250px
flex-shrink
1
Actual size:
250px
Reduced by:
0%
flex-basis
250px
flex-shrink
1
Actual size:
250px
Reduced by:
0%
Primary Axis
Primary Axis
1
600

Alright, so: we have two children, each with a hypothetical size of 250px. The container needs to be at least 500px wide to contain these children at their hypothetical size.

Let's suppose we shrink the container to 400px. Well, we can't stuff 500px worth of content into a 400px bag! We have a deficit of 100px. Our elements will need to give up 100px total, in order for them to fit.

The flex-shrink property lets us decide how that balance is paid.

Like flex-grow, it's a ratio. By default, both children have flex-shrink: 1, and so each child pays ½ of the balance. They each forfeit 50px, their actual size shrinking from 250px to 200px.
弹性增长一样,它也是一个比率。默认情况下,两个子代的flex-shrink 值都是 1,因此每个子代都要支付余额的 1/2。他们各自放弃 50px,实际大小从 250px 缩小到 200px。

Now, let's suppose we crank that first child up to flex-shrink: 3:
现在,让我们假设第一个孩子的挠性收缩率3

Screenshot showing the demo above, locked at 400px wide, with the first child having a flex-shrink of 3

We have a total deficit of 100px. Normally, each child would pay ½, but because we've tinkered with flex-shrink, the first element winds up paying ¾ (75px), and the second element pays ¼ (25px).
我们的总赤字为100px。通常情况下,每个子元素需要支付 ½ 的费用,但由于我们使用了柔性收缩,第一个元素需要支付 ¾ 的费用(75px),第二个元素需要支付 ¼ 的费用(25px)。

Note that the absolute values don't matter, it's all about the ratio. If both children have flex-shrink: 1, each child will pay ½ of the total deficit. If both children are cranked up to flex-shrink: 1000, each child will pay 1000/2000 of the total deficit. Either way, it works out to the same thing.
注意,绝对值并不重要,关键是比例。如果两个孩子的 "弹性收缩 "都是:1,那么每个孩子将支付总赤字的 1/2。如果两个孩子的 "弹性收缩"都是1000,那么每个孩子将支付赤字总额的 1000/2000。无论哪种方式,结果都是一样的。

I had an epiphany a while back about flex-shrink: we can think of it as the “inverse” of flex-grow. They're two sides of the same coin:

  • flex-grow controls how the extra space is distributed when the items are smaller than their container.
  • flex-shrink controls how space is removed when the items are bigger than their container.

This means that only one of these properties can be active at once. If there's extra space, flex-shrink has no effect, since the items don't need to shrink. And if the children are too big for their container, flex-grow has no effect, because there's no extra space to divvy up.

I like to think of it as two separate realms. You're either on Earth, or in the The evil alternative dimension from Stranger Things. Each world has its own rules.

Link to this headingPreventing shrinking

Sometimes, we don't want some of our Flex children to shrink.

I notice this all the time with SVG icons and shapes. Let's look at a simplified example:

Primary Axis 主轴
Primary Axis 主轴
600

When the container gets narrow, our two circles get squashed into gross ovals. What if we want them to stay circular?
当容器变窄时,我们的两个圆形就会被挤压成毛茸茸的椭圆形。如果我们想让它们保持圆形呢?

We can do this by setting flex-shrink: 0:
我们可以通过设置flex-shrink: 0 来实现:

Primary Axis 主轴
Primary Axis 主轴
flex-shrink: 柔性收缩:
600

When we set flex-shrink to 0, we essentially “opt out” of the shrinking process altogether. The Flexbox algorithm will treat flex-basis (or width) as a hard minimum limit.
当我们将flex-shrink设置为 0 时,我们基本上就完全 "退出 "了收缩过程。Flexbox 算法会将flex-basis(或宽度)视为硬性的最小限制。

Here's the full code for this demo, if you're curious:
如果你好奇,这里有这个演示的完整代码:

Flex Shrink ball demo 柔性收缩球演示

Result 结果

Link to this headingThe minimum size gotcha 最小尺寸难题

There's one more thing we need to talk about here, and it's super important. It may be the single most helpful thing in this entire article!
在这里,我们需要谈一件事,而且这件事超级重要。它可能是整篇文章中最有帮助的一件事!

Let's suppose we're building a fluid search form for an e-commerce store:
假设我们要为一家电子商务商店创建一个流体搜索表单:

500

When the container shrinks below a certain point, the content overflows!
当容器缩小到某一点以下时,内容就会溢出!

But why?? flex-shrink has a default value of 1, and we haven't removed it, so the search input should be able to shrink as much as it needs to! Why is it refusing to shrink?
flex-shrink的默认值是1,我们也没有删除它,所以搜索输入应该可以根据需要缩小!为什么它拒绝缩小?

Here's the deal: In addition to the hypothetical size, there's another important size that the Flexbox algorithm cares about: the minimum size.

The Flexbox algorithm refuses to shrink a child below its minimum size. The content will overflow rather than shrink further, no matter how high we crank flex-shrink!

Text inputs have a default minimum size of 170px-200px (it varies between browsers). That's the limitation we're running into above.

In other cases, the limiting factor might be the element's content. For example, try resizing this container:

The longest word in this item is “sesquipedalian”.
This one has no long words.
Primary Axis
Primary Axis 主轴
600

For an element containing text, the minimum width is the length of the longest unbreakable string of characters.
对于包含文本的元素,最小宽度为最长的不可断开字符串的长度。

Here's the good news: We can redefine the minimum size with the min-width property.
好消息是我们可以使用min-width属性重新定义最小尺寸。

min-width: 最小宽度:
500

By setting min-width: 0px directly on the Flex child, we tell the Flexbox algorithm to overwrite the “built-in” minimum width. Because we've set it to 0px, the element can shrink as much as necessary.
通过直接在 Flex 子元素上设置min-width: 0px,我们可以告诉 Flexbox 算法覆盖 "内置 "的最小宽度。因为我们将其设置为 0px,所以元素可以根据需要缩小。

This same trick can work in Flex columns with the min-height property (although the problem doesn't seem to come up as often).
同样的技巧在使用最小高度属性的 Flex 列中也能奏效(不过这个问题似乎不常出现)。

Link to this headingGaps 差距

One of the biggest Flexbox quality-of-life improvements in recent years has been the gap property:
近年来,Flexbox 对生活质量的最大改进之一就是间隙属性:

Primary Axis 主轴
Primary Axis 主轴
flex-direction: 柔性方向:
0px

gap allows us to create space in-between each Flex child. This is great for things like navigation headers:
间隙允许我们在每个 Flex 子项之间创建空间。这非常适合导航标题等内容:

Primary Axis 主轴
Primary Axis 主轴
justify-content: justify-content:
0px

gap is a relatively new addition to the Flexbox language, but it's been implemented across all modern browsers(opens in new tab) since early 2021.
间隙是 Flexbox 语言的一个相对较新的补充,但自 2021 年初以来,它已在所有现代浏览器 (在新标签页中打开)中实现

Link to this headingAuto margins 自动边距

There's one other spacing-related trick I want to share. It's been around since the early days of Flexbox, but it's relatively obscure, and it blew my mind when I first discovered it.
我还想分享一个与空间相关的技巧。它在 Flexbox 早期就已经存在了,但相对来说比较隐晦,第一次发现它时大吃一惊

The margin property is used to add space around a specific element. In some layout modes, like Flow and Positioned, it can even be used to center an element, with margin: auto.
margin属性用于在特定元素周围添加空间。在某些布局模式下,如 "流"(Flow)和 "定位"(Positioned),它甚至可以用来将元素居中,即 margin:auto

Auto margins are much more interesting in Flexbox:
在 Flexbox 中,自动边距要有趣得多:

Primary Axis 主轴
Primary Axis 主轴
margin-left: margin-left:
margin-right: 右边距

Earlier, we saw how the flex-grow property can gobble up any extra space, applying it to a child.
前面,我们看到了flex-grow属性如何吞噬多余空间,并将其应用于子代。

Auto margins will gobble up the extra space, and apply it to the element's margin. It gives us precise control over where to distribute the extra space.
自动边距会吞噬多余的空间,并将其应用到元素的边距中。这样我们就能精确控制多余空间的分布位置。

A common header layout features the logo on one side, and some navigation links on the other side. Here's how we can build this layout using auto margins:
常见的页眉布局是一边是徽标,另一边是一些导航链接。下面我们就来看看如何使用自动页边距构建这种布局:

Code Playground 代码游乐场

Result 结果

The Corpatech logo is the first list item in the list. By giving it margin-right: auto, we gather up all of the extra space, and force it between the 1st and 2nd item.
Corpatech徽标是列表中的第一个列表项。通过margin-right:auto,我们收集了所有多余的空间,并将其强制放在第一项和第二项之间。

We can see what's going on here using the browser devtools:
我们可以使用浏览器开发工具查看这里发生了什么:

Screenshot showing the above playground with an orange rectangle representing margin between the first item and the others

There are lots of other ways we could have solved this problem: we could have grouped the navigation links in their own Flex container, or we could have grown the first list item with flex-grow. But personally, I love the auto-margins solution. We're treating the extra space as a resource, and deciding exactly where it should go.
我们还有很多其他方法可以解决这个问题:我们可以将导航链接分组到自己的 Flex 容器中,或者使用flex-grow 增加第一个列表项。但就我个人而言,我喜欢自动边距解决方案。我们将多余的空间视为一种资源,并决定它应该放在哪里。

Link to this headingWrapping 包装

Phew! We've covered a lot of stuff so far. There's just one more big takeaway I want to share.
呼!到目前为止,我们已经讲了很多内容。我还想分享一个重要的收获。

So far, all of our items have sat side-by-side, in a single row/column. The flex-wrap property allows us to change that.
到目前为止,我们的所有项目都是并排放置在一行/一列中。flex-wrap属性允许我们改变这种情况。

Check it out: 来看看

flex-wrap: 柔性缠绕:
600
flex-basis 灵活基础
180px
Actual size 实际尺寸
180px
flex-basis 灵活基础
180px
Actual size 实际尺寸
180px
flex-basis 灵活基础
180px
Actual size 实际尺寸
180px
Primary Axis 主轴
Primary Axis 主轴

Most of the time when we work in two dimensions, we'll want to use CSS Grid, but Flexbox + flex-wrap definitely has its uses! This particular example showcases the “deconstructed pancake”(opens in new tab) layout, where 3 items stack into an inverted pyramid on mid-sized screens.
大多数情况下,当我们在二维空间中工作时,我们会希望使用 CSS 网格,但 Flexbox +flex-wrap绝对有其用武之地!这个例子展示了"解构薄饼" (在新标签页打开)布局,在中型屏幕上,3 个项目堆叠成一个倒金字塔。

When we set flex-wrap: wrap, items won't shrink below their hypothetical size. At least, not when wrapping onto the next row/column is an option!
当我们设置了flex-wrap: wrap 时,项目就不会缩小到假设尺寸以下。至少,在可以选择换行/换列的情况下不会!

But wait! What about our kebab / cocktail weenie metaphor??
但是,等等!我们的烤肉串/鸡尾酒腊肠的隐喻是什么?

With flex-wrap: wrap, we no longer have a single primary axis line that can skewer each item. Effectively, each row acts as its own mini flex container. Instead of 1 big skewer, each row gets its own skewer:
有了flex-wrap: wrap,我们就不再需要一条主轴线来串联每个项目了。实际上,每一行都是自己的小型柔性容器。每一行都有自己的串行线,而不是一个大串行线:

Two kebabs, each with two pieces of chicken

All of the rules we've learned so far continue to apply, within this reduced scope. justify-content, for example, will distribute the two pieces on each stick.
例如,justify-content 将在每根棍子上分配两个棋子。

But hmm... How does align-items work, now that we have multiple rows? The cross axis could intersect multiple items now!
但是...现在我们有了多行,如何对齐项目呢?现在横轴可以与多个项目相交!

Take a moment to consider. What do you think will happen when we change this property? Once you have your answer (or at least an idea), see if it's right:
花点时间考虑一下。如果我们改变这个属性,你认为会发生什么?一旦你有了答案(或至少有了一个想法),看看它是否正确:

Primary Axis 主轴
Primary Axis 主轴
align-items: align-items:

Each row is its own mini Flexbox environment. align-items will move each item up or down within the invisible box that wraps around each row.
每一行都是自己的迷你 Flexbox 环境。align-items将在环绕每一行的隐形框内上下移动每个项目。

But what if we want to align the rows themselves? We can do that with the align-content property:
但如果我们想对齐行本身呢?我们可以使用align-content属性来实现:

Primary Axis 主轴
Primary Axis 主轴
flex-start 弹性启动
flex-start 弹性启动

To summarize what's happening here:
总结一下这里发生的事情:

  • flex-wrap: wrap gives us two rows of stuff.
    flex-wrap: wrap提供了两行内容。
  • Within each row, align-items lets us slide each individual child up or down
    在每一行中,对齐-项目可以让我们上下滑动每个子代
  • Zooming out, however, we have these two rows within a single Flex context! The cross axis will now intersect two rows, not one. And so, we can't move the rows individually, we need to distribute them as a group.
    然而,将视图缩小后,我们就可以在一个 Flex 上下文中看到这两行!现在,横轴将与两行相交,而不是一行。因此,我们不能单独移动这两行,而需要将它们作为一组进行分配。
  • Using our definitions from above, we're dealing with content, not items. But we're also still talking about the cross axis! And so the property we want is align-content.
    根据上面的定义,我们处理的是内容,而不是项目。但我们仍在讨论横轴!因此,我们需要的属性是align-content

Link to this headingYou made it! 你成功了

So I want to acknowledge something: this has been a dense tutorial. We've gone way down the rabbit hole, and unless you're already a Flexbox pro, I expect your head is spinning a bit. 😅
因此,我想承认一点:这是一本内容繁杂的教程。我们已经深入了兔子洞,除非你已经是 Flexbox 专家,否则我估计你会有点头晕。😅

Like so much in CSS, Flexbox might seem simple when you first get started, but the complexity ramps up quickly when you get beyond the basics.
就像 CSS 中的很多内容一样,Flexbox 在刚开始使用时可能看起来很简单,但当你掌握了基础知识后,其复杂性就会迅速增加。

As a result, so many of us hit an early plateau with CSS. We know enough to get things done, but it's a constant struggle. The language feels rickety and unpredictable, like an ancient rope bridge that could give out at any second. When it snaps, we hurl random StackOverflow snippets at the problem, hoping something will help.
因此,我们中的许多人在使用 CSS 时很早就陷入了困境。我们知道足够多的知识来完成工作,但却一直在苦苦挣扎。这门语言给人的感觉是摇摇欲坠、难以捉摸,就像一座古老的索桥,随时都可能断裂。一旦出现问题,我们就会在 StackOverflow 上随意搜索一些片段,希望能有所帮助。

It's no fun. And that sucks, since CSS is a pretty big part of most front-end dev jobs!
这一点都不好玩。这很糟糕,因为 CSS 是大多数前端开发工作的重要组成部分!

The thing is, CSS is actually a deeply robust and consistent language. The problem is that most of our mental models are incomplete and inaccurate. When we take the time to build a proper intuition for the language, things start to click, and CSS becomes an absolute joy to use. ✨
事实上CSS 是一种非常强大和一致的语言。问题在于,我们的大部分心智模型都不完整、不准确。当我们花时间建立起对这门语言的正确直觉时,一切就会变得顺理成章,CSS 的使用也会变得轻松愉快。✨

Last year, I released a comprehensive course called CSS for JavaScript Developers(opens in new tab).
去年,我发布了一门名为《JavaScript开发人员的 CSS》的综合课程 (在新标签页中打开)

CSS for JavaScript Developers

The course is “multi-modality”, meaning that it uses lots of different forms of media. I built my own course platform from scratch, so that it supports:
这门课程是 "多模式 "的,也就是说,它使用了很多不同形式的媒体。我从零开始建立了自己的课程平台,使其支持以下功能

  • Interactive articles (like this blog post!)
    互动文章(如本博文)
  • Videos (170+ short videos)
    视频(170 多个视频短片)
  • Exercises 练习
  • Real-world-inspired projects
    受现实世界启发的项目
  • Mini-games 迷你游戏

If you found this blog post helpful, you'll love the course. It follows a similar approach, but for the entire CSS language, and with exercises and projects to make sure you're actually developing new skills.
如果你觉得这篇博文对你有帮助,那么你一定会喜欢这门课程。它采用了类似的方法,但针对的是整个 CSS 语言,并通过练习和项目确保你能真正掌握新技能。

It's specifically built for folks who use a JS framework like React/Angular/Vue. 80% of the course focuses on CSS fundamentals, but we also see how to integrate those fundamentals into a modern JS application, how to structure our CSS, stuff like that.
它是专门为使用 React/Angular/Vue 等 JS 框架的人设计的。课程 80% 的内容都集中在 CSS 基础知识上,但我们也会了解如何将这些基础知识整合到现代 JS 应用程序中,以及如何构建 CSS 结构等。

If you struggle with CSS, I hope you'll check it out. Gaining confidence with CSS is game-changing, especially if you're already comfortable with HTML and JS. When you complete the holy trinity, it becomes so much easier to stay in flow, to truly enjoy developing web applications.
如果你在 CSS 方面有困难,我希望你能看看这本书。获得使用 CSS 的信心会改变游戏规则,尤其是当你已经能够自如地使用 HTML 和 JS 时。当你完成了这三位一体的学习后,你就会更容易保持流畅,真正享受开发网络应用程序的乐趣。

Link to this headingBonus: Unpacking the demo
奖励:拆开演示

At the start of this tutorial, we saw the following “4 layouts for the price of 1” demo:
在本教程的开头,我们看到了以下"4 种布局只需 1 种价格 "的演示:

600
Drag me! 拖着我

Now that we've learned all about the Flexbox algorithm, can you figure out how this works? Feel free to experiment with the code here:
既然我们已经了解了 Flexbox 算法的全部内容,那么您能找出它是如何工作的吗?请随意尝试这里的代码:

Code Playground 代码游乐场

Result 结果

Let's walk through how this works:
让我们来看看它是如何工作的:

Thanks so much for reading! This blog post was a ton of work, and I'm thrilled to have it out in the world! I hope you found it useful. 💖
感谢您的阅读!这篇博文耗费了我大量的心血,我很高兴能将它公之于众!希望对你有用。💖

Last updated on 最后更新于

August 24th, 2024 2024 年 8 月 24 日

# of hits # 点击数

Hi friend! Hope I didn’t startle you. Can I tell you about my newsletter?
嗨,朋友!希望我没有吓到你。我能告诉你我的通讯吗?