在CSS Flexbox中,为什么没有“ justify-items”和“ justify-self”属性?


674

考虑伸缩容器的主轴和横轴:

在此处输入图片说明                                                                                                                                                    资料来源:W3C

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

要沿十字轴对齐弹性项目,需要三个属性:

在上图中,主轴是水平的,而横轴是垂直的。这些是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; }

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

    考虑带有一组导航项和徽标的标题部分。随着justify-self标志可以左对齐,而资产净值的项目留最右边,并顺利整件事调整(“挠曲”),以不同的屏幕尺寸。

  • 在三个伸缩项目的行中,将中间项目粘贴到容器的中心(justify-content: center),然后将相邻的项目与容器的边缘对齐(justify-self: flex-startjustify-self: flex-end)。

    请注意,如果相邻项目的宽度不同,则value space-aroundspace-betweenon justify-content属性不会使中间项目保持在容器中心。

jsFiddle版本


在撰写本文时,有没有提及justify-selfjustify-itemsFlexbox的规范

但是,在CSS Box Alignment Module中,这是W3C尚未完成的建议,目的是建立一套通用的对齐属性供所有Box模型使用。

在此处输入图片说明                                                                                                                                                    资料来源:W3C

您会注意到这一点justify-selfjustify-items并且正在考虑... 但是对于flexbox而言却不是


最后,我重申一个主要问题:

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


4
您希望如何justify-self为弹性商品工作?假设项目a,b,c,d周围有多余的空间可分布,而flex容器具有justify-content: space-between,那么它们最终的结果类似于| abcd |。justify-self: center在其中的项目“ b”中添加eg 或“ justify-self:flex-end” 是什么意思?您希望它去哪里?(我在此处的答案之一中看到了一些演示,但我看不出它通常可以正常工作的明确方法。)
dholbert

(或者:假设我们有justify-content: flex-start,所以项目开始时像| abcd |一样拥挤。如果justify-self: [anything]在项目上放置项目'b' ,您希望它做什么?)
dholbert

1
@dholbert,您写道:您希望justify-self弹性项目如何工作?我要说的是,与automargin在弹性项目上已经没有什么不同。在您的第二个示例中,justify-self: flex-end在项d上会将其移动到最远的边缘。这本身就是一个很大的功能,auto利润已经可以做到。我用示范发表了答案。
Michael Benjamin

2
我在这里主要看到更多用例,用例很棒–但是棘手的一点是如何将其塞入实际justify-contentjustify-self指定的方式中,以免发生冲突的情况(例如我所询问的情况)被明确和明智地定义。正如我在这里的答案中所指出的那样,它{justify|align}-self是关于在较大的盒子中{justify|align}-self对齐项目,而该盒子的大小与值的大小无关 -主轴上没有这样的盒子可以将弹性项目对齐。
dholbert

1
RE“与自动保证金没有区别”-我实际上是在询问您如何想象justify-selfjustify-content互动,如果它们发生冲突(例如我提出的方案)。自动边距根本与之交互justify-content-它们在justify-content获得使用机会之前会偷走所有包装空间。因此,自动页边距并不是一个很好的模拟方法。
dholbert

Answers:


1245

沿主轴对齐弹性项目的方法

如问题所述:

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

沿横轴对准柔性项目有三个属性:align-contentalign-itemsalign-self

然后问题问:

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

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

所述Flexbox的规范提供2点用于对准沿主轴弯曲的物品的方法:

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

证明内容

justify-content属性使伸缩项沿伸缩容器的主轴对齐。

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

有五个对齐选项:

  • flex-start 〜Flex项目被包装到行的开头。

    在此处输入图片说明

  • flex-end 〜Flex项目包装在行尾。

    在此处输入图片说明

  • center 〜柔性物品被包装到行的中心。

    在此处输入图片说明

  • space-between〜柔性物品均匀地隔开,第一个物品对准容器的一个边缘,最后一个物品对准相对的边缘。第一项和最后一项使用的边缘取决于flex-direction写入模式ltrrtl)。

    在此处输入图片说明

  • space-aroundspace-between除两端留半角空格外,其余均相同。

    在此处输入图片说明


自动保证金

使用automargins,可以将弹性项目居中,隔开或打包为子组。

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: centeralign-items: center

代替在flex容器上的此代码:

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

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

.box56 {
    margin: auto;
}

居中溢出容器的flex项目居中时,此替代方法很有用。


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

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

因此,为了创建平衡,以便中间物品可以在容器中居中放置单个物品,必须引入平衡。

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

在此处输入图片说明

在此处输入图片说明

当然,就语义而言,此方法并不是什么好事。

另外,您可以使用伪元素代替实际的DOM元素。或者,您可以使用绝对定位。此处介绍了所有三种方法:居中对齐和底部对齐的弹性项目

注意:仅当最外层项目的高度/宽度相等时,以上示例才有效(就真正居中而言)。如果弹性商品的长度不同,请参见下一个示例。


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

问题的场景:

  • 在三个伸缩项目的行中,将中间项目粘贴到容器的中心(justify-content: center),然后将相邻的项目与容器的边缘对齐(justify-self: flex-startjustify-self: flex-end)。

    请注意,如果相邻项目的宽度不同,则value space-aroundspace-betweenon justify-content属性不会使中间项目相对于容器居中(请参见demo)。

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

这是解决此问题的两种方法:

解决方案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)都是一个弹性项目。
  • .box给出每个项目是flex: 1为了平均分配容器空间。
  • 现在,项目占用了该行中的所有空间,并且宽度相等。
  • 使每个项目成为一个(嵌套的)flex容器并添加justify-content: center
  • 现在,每个span元素都是居中的弹性项目。
  • 使用伸缩auto边距左右移动外边的spans。

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

但是justify-content可以在这里工作,因为auto保证金始终是优先事项。从规格:

8.1。与auto 边距对齐

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


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

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

  • space-same〜的混合space-betweenspace-around。Flex项目的间距是均匀的(如space-between),除了两端没有半角空格(如space-around),两端还有全角空格。

这种布局可以用能够实现::before::after柔性容器上伪元素。

在此处输入图片说明

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

更新:浏览器已经开始实现space-evenly,可以完成上述工作。有关详细信息,请参见此帖子:伸缩项目之间的间距相等


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


1
上方覆盖答案主轴justify-contentauto利润率。对于硬币的另一面-的交叉轴align-itemsalign-selfalign-content-看到这个帖子:stackoverflow.com/q/42613359/3597276
迈克尔·本杰明

4
@MarkW,您正在为该justify-self属性辩护... auto边距justify-self: center很有用,但非常理想。解决您提出的问题的方法是在对面创建不可见的重复项。在这里查看我的答案:stackoverflow.com/q/38948102/3597276
Michael Benjamin

5
您的space-same概念现在是真实的。它称为space-evenly,但目前仅受Firefox支持:developer.mozilla.org/en-US/docs/Web/CSS/justify-content
benface

1
@benface,是的,您是对的。感谢您指出了这一点。我实际上一直在写space-evenly其他答案:stackoverflow.com/q/45134400/3597276
Michael Benjamin

1
事实上,space-evenly 在Chrome 57-60支持,但仅限于电网布局。此错误已修复,自Chrome 61起,Flexbox也支持该错误。此外,还有一种方法可以在不使用伪元素的情况下进行仿真:.item { margin-right: auto } .item:first-child { margin-left: auto }
Ilya Streltsyn

153

我知道这不是一个答案,但是我想为这个问题做出贡献。如果他们可以发布justify-selfflexbox使其真正具有灵活性,那将是很棒的。

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

我真正希望W3C注意到这一点,至少会考虑一下。=)

在此处输入图片说明

这样,您可以使项目真正居中,而无需考虑左右框的大小。当其中一个盒子到达中心盒子的位置时,它会简单地将其推入,直到没有更多的空间可分配。

在此处输入图片说明

制作出色布局的简便性无穷无尽,请看一下这个“复杂”示例。

在此处输入图片说明


12
@Mark,这太神奇了!感谢您抽出宝贵的时间来起草这份报告。希望您不要介意,但我已经在这里提交了:discourse.wicg.io/t/flexbox-justify-self-property/1146
Zaqx 2015年

1
@Zaqx可以肯定的是,曝光量越多越好。衷心希望他们能找到一种方法来实现这一目标,并希望能使我对此有所帮助。
标记

1
嗨,Mark,@ Zaqx,我发布了一个答案,该答案可能涵盖了此答案中提到的一些用例。我发现在主轴上仍然可以完成很多工作,而无需使用justify-selfjustify-items
Michael Benjamin

3
@Michael_B很高兴您正在学习有关flexbox的更多信息,并感谢您花时间将笔记格式化为答案。利润:自动确实很酷(尽管您会发现实现了2009和2012版本的flexbox规范的浏览器没有等效功能,从而大大降低了在生产站点上使用它的能力)。但是,即使使用支持margin:auto的浏览器,如果没有理由自我属性或类似属性,此处相对于其容器居中放置的项目的主要用例仍然是不可能的。
Zaqx 2015年

1
@Zaqx,感谢您的反馈。是的,我同意你的看法,auto利润不能完全替代justify-self。我谨慎地说出我以前的评论,说auto空白将覆盖一些用例。如您所述,当相邻项目的大小不同时,它无法将项目居中放置。但是,它确实提供了更多用于对齐弹性项目的选项。当我第一次开始学习flexbox时,我以为justify-content和看不见的间隔物是唯一的方法。
Michael Benjamin 2015年

20

这是在www样式列表中提出的,Tab Atkins(规范编辑器)提供了一个答案,解释了为什么。我会在这里详细说明。

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

对于多行flexbox,相同的逻辑适用于每个“ flex line”。在给定的行中,项目在横轴上单独对齐(因为在横轴上每行只有一个项目),而在主轴上则是统一排列。


这里的措辞它的另一种方式:所以,所有*-self*-content性能有关如何乾坤分配额外空间。但是关键的区别在于,*-self版本用于该轴上只有一个事物的情况,而*-content版本则用于该轴上可能存在许多事物的情况。单物与多物方案是不同类型的问题,因此它们具有不同类型的选项-例如,space-around/ space-between值对有意义*-content,但对*-self

SO:在flexbox的主轴上,有很多东西可以分配空间。因此,*-content此处的属性有意义,但对于*-self属性。

相反,在交叉轴上,我们同时具有a *-self*-content属性。一个决定了我们如何在许多弯曲线(align-content)周围分配空间,而另一个(align-self)确定了如何在单个弯曲线周围分配空间。在给定的弯曲线内在交叉轴上的弯曲项目。

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


1
我知道justify-self轴上有多个项目而不是一个项目可能是个问题。但是,我真的希望他们在多项目情况下会justify-self做得更好,因为在某些情况下这可能确实有用。例如(stackoverflow.com/questions/32378953/…)。
2015年

在该邮件列表上很好找到。尝试把头缠起来,因为我仍然看到的良好用例可能性justify-self
Michael Benjamin

我增加了一些说明,解释了*-self只有件事要对齐的*-content情况,而有很多事情要对齐的情况。这会使它更清晰吗?
dholbert 2015年

是的,这更加清楚。我感谢您的解释。但这似乎归结为规范作者的一个简单偏好,而不是基于逻辑的特定需求。从您引用邮件列表中* -self属性仅在子项在该轴上独自一人时才起作用。为什么?似乎没有必要。这是一个任意决定。偏好。实际上,页auto边距(也是规范的一部分)使* -self可以与该行中的多个项目对齐。也没有明确的理由说明为什么关键字属性不能。
Michael Benjamin 2015年

1

我知道这不使用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>


感谢您的回答,但并不能真正解决问题。另外,还有一种更简单的方法来完成布局:jsfiddle.net/fga89m2o
Michael Benjamin

0

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

这样,结束元素将固定在顶部和底部,并且您可以根据需要设置自定义边距。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.