在CSS Flexbox中,为什么没有“证明项目”和“证明自我”属性?

考虑柔性容器的主轴和交叉轴:

应用于行flex容器的各种方向和大小术语的说明来源:W3C

要沿主轴对齐flex项,有一个属性:

要沿十字轴对齐flex项,有三个属性:

在上面的图像中,主轴是水平的,横轴是垂直的。这些是柔性容器的默认方向。

但是,这些方向可以很容易地与flex-direction属性互换。

/* main axis is horizontal, cross axis is vertical */flex-direction: row;flex-direction: row-reverse;
/* main axis is vertical, cross axis is horizontal */flex-direction: column;flex-direction: column-reverse;

(十字轴始终与主轴垂直。)

我在描述轴的工作方式时的观点是,两个方向似乎都没有什么特别之处。主轴,十字轴,它们在重要性方面都是相等的,flex-direction使来回切换变得容易。

那么为什么十字轴有两个额外的对齐属性呢?

为什么align-contentalign-items合并为主轴的一个属性?

为什么主轴没有得到justify-self属性?


这些属性有用的场景:

  • 在flex容器的角落放置一个flex项目
    #box3 { align-self: flex-end; justify-self: flex-end; }

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

考虑一个带有一组导航项目和一个徽标的标题部分。使用justify-self,徽标可以向左对齐,而导航项目保持在最右边,整个事情可以平滑地调整(“弯曲”)到不同的屏幕尺寸。

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

注意,值space-aroundspace-between在如果相邻项具有不同的宽度,则justify-content属性不会将中间项保持在容器的中心。

#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>note that the middlebox will only be truly centered if adjacent boxes are equal width</p>

jsFiddle version


在撰写本文时,在flexbox规范中没有提到justify-selfjustify-items

然而,在CSS框对齐模块中,这是W3C未完成的建议,即建立一组通用的对齐属性以用于所有盒子模型,其中包括:

输入图片描述                                                                                                                                                   来源:W3C

你会注意到justify-selfjustify-items正在被考虑……但不是Flexbox


最后,我将重申主要问题:

为什么没有“证明项目”和“证明自我”属性?

357325 次浏览

这是在www样式列表和Tab Atkins(规范编辑器)提供了解释原因的答案上提出的。我将在这里详细说明一下。

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

对于多行flexbox,相同的逻辑适用于每个“柔性线”。在给定的行中,项目在十字轴上单独对齐(因为在十字轴上每行只有一个项目),而在主轴上集体对齐。


这是另一种表达方式:所以,*-self*-content属性中的所有是关于如何围绕事物分配额外空间的。但关键的区别在于*-self版本适用于有那个轴上只有一个东西的情况,*-content版本适用于可能有*-content0的情况。一件事与多件事的场景是不同类型的问题,因此它们有不同类型的可用选项-例如,space-around/space-between值对*-content有意义,但对*-self没有意义。

SO:在flexbox的主轴上,有很多东西可以分配空间。所以*-content属性在那里是有意义的,但*-self属性不是。

相比之下,在十字轴上,我们有*-self*-content属性。一个决定了我们如何在许多个柔性线(align-content)周围分配空间,而另一个(align-self)决定了如何在给定柔性线内的十字轴上围绕个人个柔性项分配空间。

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

我知道这不是一个答案,但我想为这件事做出贡献。如果他们能为flexbox发布justify-self以使其真正灵活,那就太好了。

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

我真的希望W3C注意到这一点,至少会考虑它。

在此处输入图片描述

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

在此处输入图片描述

制作令人敬畏的布局的容易性是无穷无尽的,看看这个“复杂”的例子。

在此处输入图片描述

沿主轴对齐Flex项目的方法

如问题所述:

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

要沿十字轴对齐flex项,有三个属性:align-content#1和#2

接下来的问题是:

为什么没有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相同,只是两端有一半大小的空格。

    输入图片描述


自动边距

使用#0页边距,flx项目可以居中,间隔开或打包成子组。

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

它们通过消耗指定方向上的所有可用空间来工作。


向右对齐flex项目组,但第一个项目向左对齐

问题的场景:

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

    考虑一个标题部分,其中包含一组导航项和一个徽标。随着justify-self当导航项保留时,徽标可以向左对齐最右边,整个事情顺利调整(“弯曲”)到不同的屏幕尺寸。

在此处输入图片描述

在此处输入图片描述


其他有用的场景:

在此处输入图片描述

在此处输入图片描述

在此处输入图片描述


在角落里放一个弹性物品

问题的场景:

  • 在角落里放置一个柔性项目.box { align-self: flex-end; justify-self: flex-end; }

在此处输入图片描述


垂直和水平居中一个flex项目

在此处输入图片描述

margin: autojustify-content: centeralign-items: center的替代方案。

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

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

您可以在flex项目上使用它:

.box56 {margin: auto;}

此选项在将溢出容器的flex项居中时很有用。


将一个flex项居中,并将第二个flex项居中在第一个和边缘之间

flex容器通过分配可用空间来对齐flex项。

因此,为了创建平衡,以便中间项目可以在容器中居中,旁边有一个项目,必须引入平衡。

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

在此处输入图片描述

在此处输入图片描述

当然,这种方法在语义学方面没有什么大不了的。

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

注意:上面的示例仅在最外层的项目等于高度/宽度时才有效-就真正的居中而言。当flx项目长度不同时,请参阅下一个示例。


当相邻项的大小不同时,将一个flex项居中

问题的场景:

  • 在一行三个flex项目中,将中间项目粘贴到容器的中心(justify-content: center)并对齐相邻的项目项目到容器边缘(justify-self: flex-startjustify-self: flex-end.

    请注意,如果相邻项具有不同的宽度,则#2属性上的值#0和#1不会保持中间项相对于容器的居中(请参阅演示

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

#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规范允许柔性物品的绝对定位。这允许中间项完全居中,而不管其兄弟项的大小如何。

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

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

在此处输入图片描述

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

.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)现在都是一个flex项。
  • 每个.box项都被赋予flex: 1,以便平均分配容器空间。
  • 现在,这些项正在占用行中的所有空间,并且宽度相等。
  • 使每个项目成为(嵌套的)flex容器并添加justify-content: center
  • 现在每个span元素都是一个居中的flex项。
  • 使用flexauto边距将外部span左右移动。

您也可以放弃justify-content并仅使用auto边距。

但是justify-content可以在这里工作,因为auto的边距始终具有优先级。从规范中:

8.1。与auto对齐边距

在通过justify-contentalign-self对齐之前,任何正自由空间被分配到该维度的自动边距。


证明内容:空间相同(概念)

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

  • space-same~space-betweenspace-around的混合体。Flex项目是均匀间隔的(如space-between),除了两端没有半尺寸的空间(如space-around),两端都有全尺寸的空间。

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

在此处输入图片描述

(信用:@oriol用于代码,@crl用于标签)

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


操场(包括上面所有示例的代码)

我知道这不使用flexbox,但是对于三个项目(一个在左边,一个在中间,一个在右边)的简单用例,这可以很容易地完成,在父级上使用display: grid,在子级上使用grid-area: 1/1/1/1;,在这些子级上使用justify-self

<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>

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

这样,最终元素将坚持顶部和底部,如果你愿意,你可以有自定义的边距。

这是由于flexbox的一维性质,并且沿着轴可能有多个项目,因此无法证明单个项目的合理性.要在flexbox中沿着主内联轴对齐项目,请使用justify-content属性。

参考:CSS网格布局中的框对齐