乐闻世界logo
搜索文章和话题

CSS 中为什么 flexbox 没有 justify items 和 justify self 属性?

9 个月前提问
5 个月前修改
浏览次数56

6个答案

1
2
3
4
5
6

CSS Flexbox 是一个用于在页面上布局元素的强大工具,它提供了一系列的属性用来对齐和分布容器内的子元素。在 Flexbox 中,关于元素的对齐,我们主要使用以下属性:

  • justify-content: 用来对齐一个容器内的子元素们(flex items)沿着主轴(main axis)的。
  • align-items: 用来对齐一个容器内的子元素们沿着交叉轴(cross axis)。
  • align-self: 允许单个子元素有不同于容器的 align-items 属性的对齐方式。

在 CSS Grid 布局中,有 justify-itemsjustify-self 属性,它们分别用来对齐网格项目(grid items)在网格区域内沿着行轴的对齐方式(即主轴对齐),以及允许单个网格项有不同于网格容器的 justify-items 属性设定的对齐方式。

而在 Flexbox 中,没有 justify-itemsjustify-self 这样的属性,原因有以下几点:

  1. 主轴对齐通过 justify-content 控制:在 Flexbox 中,主轴(横向或纵向)的对齐是通过 justify-content 属性来控制的,它影响整个容器内所有子元素的对齐方式。这意味着所有子元素作为一个整体在主轴方向上的间距和分布。

  2. 单个子元素在主轴上的控制:如果想要单独控制某个子元素在主轴上的位置,可以使用 margin 属性(如 margin-left, margin-right, margin-top, margin-bottom 或简写形式 margin),这样可以对单个子元素进行“推”或“拉”的操作来改变它们在主轴上的位置。

  3. 交叉轴对齐:对于交叉轴,Flexbox 提供了 align-items 来控制所有子元素的默认对齐方式,同时也提供了 align-self 来允许单个子元素有自己的交叉轴对齐方式,这与 Grid 的 justify-self 属性类似,只不过是应用于交叉轴而不是主轴。

因此,在 Flexbox 的设计中,justify-content, align-items, 和 align-self 这三个属性已经足够用来控制子元素在主轴和交叉轴上的对齐和分布。justify-itemsjustify-self 属性在 Flexbox 上下文中不是必需的,因为已经有其他属性覆盖了它们的功能。而且,Flexbox 主要是为了一维布局设计的,而 Grid 是为了更复杂的二维布局设计的,这也是为什么 Grid 有更详尽的对齐控制属性。

2024年6月29日 12:07 回复

沿主轴对齐 Flex 项目的方法

正如问题中所述:

要沿主轴对齐弹性项目,有一个属性:justify-content

要沿横轴对齐 Flex 项目,需要使用三个属性:align-contentalign-itemsalign-self

接下来的问题是:

为什么没有justify-itemsjustify-self属性?

一个答案可能是:因为它们没有必要。

Flexbox规范提供了_两种_沿主轴对齐 Flex 项目的方法:

  1. 关键字justify-content属性,以及
  2. auto边距

证明内容合理

justify-content属性沿着 Flex 容器的主轴对齐 Flex 项目。

它应用于 Flex 容器,但仅影响 Flex 项目。

有五个对齐选项:

  • flex-start~ Flex 商品包装在生产线的开头。

    在此输入图像描述

  • flex-end~ Flex 商品在生产线末端进行包装。

    在此输入图像描述

  • center~ Flex 商品朝生产线的中心方向包装。

    在此输入图像描述

  • space-between~ Flex 项目均匀分布,第一个项目与容器的一个边缘对齐,最后一个项目与相对的边缘对齐。第一项和最后一项使用的边取决于flex-direction书写模式ltrrtl)。

    在此输入图像描述

  • space-around~space-between与两端相同,但两端有一半大小的空格。

    在此输入图像描述


自动边距

通过auto边距,弹性项目可以居中、间隔开或打包到子组中。

justify-content与应用于 Flex 容器的不同,auto边距适用于 Flex 项目。

它们的工作原理是消耗指定方向上的所有可用空间。


将一组弹性项目向右对齐,但第一个项目向左对齐

问题中的场景:

  • 使一组弹性项目右对齐 ( justify-content: flex-end) 但第一个项目左对齐 ( justify-self: flex-start)

    考虑带有一组导航项和徽标的标题部分。徽标 justify-self可以向左对齐,而导航项则保持在最右侧,并且整个内容可以平滑地调整(“弯曲”)以适应不同的屏幕尺寸。

在此输入图像描述

在此输入图像描述


其他有用的场景:

在此输入图像描述

在此输入图像描述

在此输入图像描述


在角落放置一个弹性项目

问题中的场景:

  • 将弹性项目放置在角落.box { align-self: flex-end; justify-self: flex-end; }

在此输入图像描述


将弹性项目垂直和水平居中

在此输入图像描述

margin: auto``justify-content: center是and的替代align-items: center

而不是 Flex 容器上的这段代码:

shell
.container { justify-content: center; align-items: center; }

您可以在弹性项目上使用它:

shell
.box56 { margin: auto; }

当将溢出容器的弹性项目居中时,此替代方法非常有用。


将一个弹性项目居中,并将第二个弹性项目置于第一个弹性项目和边缘之间

弹性容器通过分配可用空间来对齐弹性项目。

因此,为了创建_相等的平衡_,以便中间的物品可以在容器中居中,旁边有单个物品,必须引入平衡。

在下面的示例中,引入了不可见的第三个弹性项目(框 61 和 68)来平衡“真实”项目(框 63 和 66)。

在此输入图像描述

在此输入图像描述

当然,这种方法在语义上并没有什么了不起。

或者,您可以使用伪元素而不是实际的 DOM 元素。或者您可以使用绝对定位。这里涵盖了所有三种方法:居中和底部对齐弹性项目

注意:上面的示例仅在真正居中时才有效 - 当最外面的项目具有相同的高度/宽度时。当弹性项目的长度不同时,请参阅下一个示例。


当相邻项目大小不同时将弹性项目居中

问题中的场景:

  • 在一排三个弹性项目中,将中间项目固定到容器的中心 ( justify-content: center),并将相邻项目与容器边缘对齐 (justify-self: flex-startjustify-self: flex-end)。

    请注意,如果相邻项目具有不同的宽度,则 valuespace-aroundspace-betweenonjustify-content属性不会使中间项目相对于容器居中(请参阅演示)。

如前所述,除非所有 Flex 项目的宽度或高度相等(取决于flex-direction),否则中间项目无法真正居中。这个问题为属性提供了强有力的理由justify-self(当然是为了处理任务而设计的)。

显示代码片段

shell
#container { display: flex; justify-content: space-between; background-color: lightyellow; } .box { height: 50px; width: 75px; background-color: springgreen; } .box1 { width: 100px; } .box3 { width: 200px; } #center { text-align: center; margin-bottom: 5px; } #center > span { background-color: aqua; padding: 2px; } <div id="center"> <span>TRUE CENTER</span> </div> <div id="container"> <div class="box box1"></div> <div class="box box2"></div> <div class="box box3"></div> </div> <p>The middle box will be truly centered only if adjacent boxes are equal width.</p>

运行代码片段隐藏结果

展开片段

解决这个问题有两种方法:

解决方案#1:绝对定位

Flexbox 规范允许Flex 项目的绝对定位。这使得中间项目能够完美居中,无论其兄弟项目的大小如何。

请记住,与所有绝对定位的元素一样,这些项目将从文档流中删除。这意味着它们不占用容器中的空间并且可以与它们的兄弟姐妹重叠。

在下面的示例中,中间项目以绝对定位居中,而外部项目保持流入。但可以以相反的方式实现相同的布局:将中间项目居中justify-content: center并绝对定位外部项目。

在此输入图像描述

解决方案#2:嵌套 Flex 容器(无绝对定位)

shell
.container { display: flex; } .box { flex: 1; display: flex; justify-content: center; } .box71 > span { margin-right: auto; } .box73 > span { margin-left: auto; } /* non-essential */ .box { align-items: center; border: 1px solid #ccc; background-color: lightgreen; height: 40px; } <div class="container"> <div class="box box71"><span>71 short</span></div> <div class="box box72"><span>72 centered</span></div> <div class="box box73"><span>73 loooooooooooooooong</span></div> </div>

运行代码片段隐藏结果

展开片段

它的工作原理如下:

  • 顶层 div ( .container) 是一个 Flex 容器。
  • 现在,每个子 div ( .box) 都是一个弹性项目。
  • 每个.box项目都是flex: 1为了平均分配容器空间而给出的。
  • 现在这些项目占用了行中的所有空间并且宽度相等。
  • 将每个项目设为(嵌套)弹性容器并添加justify-content: center.
  • 现在每个span元素都是居中的弹性项目。
  • 使用弹性边距左右auto移动外部。span

您也可以放弃justify-contentauto专门使用边距。

justify-content可以在这里工作,因为auto利润总是优先的。从规格来看:

8.1.与auto 边距对齐

justify-content在通过和进行对齐之前align-self,任何正可用空间都会分配到该维度中的自动边距。


调整内容:空间相同(概念)

回到justify-content一分钟,这里有一个想法,还有一个选择。

  • space-samespace-between~和的混合体space-around。 Flex 项目均匀间隔(如space-between),但两端不是半尺寸空格(如space-around),而是两端都有全尺寸空格。

::before这种布局可以通过::afterFlex 容器上的伪元素来实现。

在此输入图像描述

(来源:@oriol代码,@crl标签)

更新:浏览器已经开始实现space-evenly,它完成了上述任务。有关详细信息,请参阅此帖子:Flex 项目之间的间距相等


PLAYGROUND(包括上述所有示例的代码)

2024年6月29日 12:07 回复

我知道这不是一个答案,但我愿意为此事做出有价值的贡献。如果他们能够发布justify-selfFlexbox 以使其真正灵活,那就太好了。

我相信,当轴上有多个项目时,最合乎逻辑的justify-self行为方式是将自身与其最近的邻居(或边缘)对齐,如下所示。

我真心希望 W3C 能够注意到这一点,并且至少会考虑一下。 =)

在此输入图像描述

这样,无论左右框的大小如何,您都可以获得真正居中的项目。当其中一个盒子到达中心盒子的位置时,它会简单地推动它,直到没有更多的空间可以分配。

在此输入图像描述

制作精彩布局的容易程度是无穷无尽的,看看这个“复杂”的例子。

在此输入图像描述

2024年6月29日 12:07 回复

这是在 www-style 列表上被问到的,Tab Atkins(规范编辑)提供了一个答案,解释了原因。我将在这里详细说明这一点。

首先,我们首先假设我们的 Flex 容器是单行的 ( flex-wrap: nowrap)。在这种情况下,主轴和交叉轴之间明显存在对齐差异 - 主轴上堆叠了多个项目,但交叉轴上仅堆叠了一个项目。因此,在横轴上有一个可定制的每项“自我对齐”是有意义的(因为每个项目都是单独对齐的),而在主轴上则没有意义(因为在那里,项目集体对齐)。

对于多行 Flexbox,相同的逻辑适用于每个“Flex Line”。在给定的行中,项目在交叉轴上单独对齐(因为交叉轴上每行只有一个项目),而不是在主轴上集体对齐。


这是另一种表达方式:因此,所有*-self和属性*-content都是关于如何在事物周围分配额外空间。但关键的区别在于,*-self版本适用于_该轴上只有一个事物的_情况,而*-content版本适用于_该轴上可能有很多事物的情况_。一件事与多件事场景是不同类型的问题,因此它们有不同类型的可用选项 - 例如, /space-aroundspace-between对于 有意义*-content,但对于 则无效*-self

SO:在弹性盒的主轴上,有很多东西可以分配空间。因此,*-content财产在那里有意义,但不是*-self财产。

相反,在横轴上,我们同时具有 a*-self和 a*-content属性。一个决定如何在_多条_伸缩线 ( )周围分配空间align-content,而另一个 ( align-self) 决定如何在给定的伸缩线内,在横轴上的_各个伸缩项目周围分配空间。_

(我*-items在这里忽略属性,因为它们只是为 建立默认值*-self。)

2024年6月29日 12:07 回复

我刚刚找到了自己的解决方案来解决这个问题,或者至少是我的问题。
我正在使用justify-content: space-around而不是justify-content: space-between;.

这样,末端元素将粘在顶部和底部,并且如果需要,您可以拥有自定义边距。

2024年6月29日 12:07 回复

我知道这不使用弹性盒,但对于三个项目(左侧一个,中间一个,右侧一个)的简单用例,可以轻松地display: grid在父级、grid-area: 1/1/1/1;子级和justify-self定位上使用来完成此操作那些孩子们。

shell
<div style="border: 1px solid red; display: grid; width: 100px; height: 25px;"> <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: left;"></div> <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: center;"></div> <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: right;"></div> </div>

运行代码片段隐藏结果

展开片段

2024年6月29日 12:07 回复

你的答案