使flexbox元素居中和右对齐


147

我想有A BC中间对齐。

我怎样才能D完全右移?

之前:

在此处输入图片说明

后:

在此处输入图片说明

ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  /* magic to throw to the right*/
}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>

https://jsfiddle.net/z44p7bsx/

Answers:


214

以下是实现此布局的五个选项:

  • CSS定位
  • 带有不可见DOM元素的Flexbox
  • 带有不可见伪元素的Flexbox
  • Flexbox与 flex: 1
  • CSS网格布局

方法1:CSS定位属性

应用于position: relativeflex容器。

应用于position: absolute项目D。

现在,此项目已完全放置在flex容器中。

更具体地说,项目D从文档流中删除,但停留在最接近的祖先的范围内。

使用CSS偏移属性top并将right此元素移到适当位置。

此方法的一个警告是,某些浏览器可能无法从正常流程中完全删除绝对定位的flex项目。这会以非标准的意外方式更改对齐方式。更多详细信息:绝对定位的弹性项目不会从IE11的常规流中移除


方法2:Flex自动边距和不可见的Flex项(DOM元素)

结合使用页auto边距和新的,不可见的柔性项目,可以实现布局。

新的弹性项目与项目D相同,并位于另一端(左边缘)。

更具体地说,因为弯曲对齐基于自由空间的分布,所以新项目是保持三个中间框水平居中的必要平衡。新项目的宽度必须与现有D项目的宽度相同,否则中间框将无法精确居中。

使用将该新项目从视图中删除visibility: hidden

简而言之:

  • 创建该D元素的副本。
  • 将其放在列表的开头。
  • 使用Flex auto利润率保持ABC居中,既有D元素创建从两端完全平衡。
  • 申请visibility: hidden副本D


方法3:Flex自动页边距和不可见的Flex项(伪元素)

此方法与#2相似,但在语义上更清晰,并且D必须知道的宽度。

  • 创建一个宽度与相同的伪元素D
  • 将其放置在容器的开头::before
  • 使用Flex auto利润率保持ABC完全居中,用伪和D元素来创建从两端完全平衡。


方法4:添加flex: 1到左侧和右侧项目

从上面的方法2或方法3开始,不必担心左右项目的宽度相等以保持相等的平衡,只需给每个项分配即可flex: 1。这将迫使它们都占用可用空间,从而使中间项居中。

然后,您可以添加display: flex到各个项目以使其内容对齐。

关于在以下情况下使用此方法的min-height注意事项目前,在Chrome,Firefox,Edge和其他可能的浏览器中,速记规则flex: 1细分如下:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%

当在容器上使用该百分比单位(%)时flex-basis此方法将中断min-height。这是因为,通常来说,子级上的百分比高度要求height在父级上进行显式的属性设置。

这是一条可以追溯到1998年的旧CSS规则(CSS Level 2),在某种程度上还是在许多浏览器中仍然有效。有关完整的详细信息,请参见此处此处

这是user2651804在评论中发布的问题的说明:

解决方案是不使用百分比单位。尝试px或根本不尝试(这实际上是规范的建议,尽管事实上至少有一些主要的浏览器出于某种原因附加了百分比单位)。


方法5:CSS网格布局

这可能是最干净,最有效的方法。无需绝对定位,伪造元素或其他黑客手段。

只需创建一个具有多列的网格。然后将项目放在中间和结尾列中。基本上,只需将第一列留空。

ul {
  display: grid;
  grid-template-columns: 1fr repeat(3, auto) 1fr;
  grid-column-gap: 5px;
  justify-items: center;
}

li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }

/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p  { text-align: center; }
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>| true center |</span></p>


1
非常好,谢谢您的解释!我猜想新添加的代码段将从缩短示例文本中受益,因为从输出中实际上看不到内容是否居中/由于视口较小而居中。只有我?
user2651804

“新项目的宽度必须与现有D项目的宽度相同,否则中间框将无法精确居中。” -很糟糕,它必须具有相同的宽度,但是感谢CSS网格的上帝:)
Vucko

使用网格技术,物品不会处于死角,是否有办法使徽标元素死在中心?imgur.com/a/SVg9xsj
J86

对网格解决方案的熟悉程度不够高,尽管它就像一个魅力,而且是最干净的。我有一个问题是如何给中间列更多的空间而不是全部三个?
Saba Ahang

5

最简单的方法

.box{
  display:flex;
  justify-content:center;
}
.item1{
   flex:1;
   display: flex;
   justify-content: center;
   transform: translateX(10px);/*D element Width[if needed]*/
}
 <div class="box">
   <div class="item1">
      <div>A</div>
      <div>B</div>
      <div>C</div>
   </div>
   <div class="item2">D</div>
 </div>



2

最简单的解决方案是将内容中心对齐到父容器,并为第一个和最后一个子元素赋予margin-left auto。

ul {
  display:flex;
  justify-content:center;
}


.a,.d {
  margin-left:auto;
}
<ul>
  <li class="a">A</li>
  <li>B</li>
  <li>C</li>
  <li class="d">D</li>
</ul>


1

使用该display:grid方法,您可以简单地将所有ul子代放入同一单元格,然后进行设置justify-self

ul {
  display: grid;
}

ul > * {
  grid-column-start: 1;
  grid-row-start: 1;
  justify-self:center;
}

ul > *:last-child {
  justify-self: right;
}

/* Make Fancy */
li {
  display:inline-block;
  margin: 1px;
  padding: 5px;
  background: #bbb;
}
<ul>
  <span>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  </span>
  <li>D</li>
</ul>


0

非常明确的问题。在挖掘了几个小时后,我忍不住发布了答案。我们可以通过表格,表格单元格,绝对位置,变换来解决此问题,但我们只需要使用flexbox即可:)

.parent {
  display: flex;
  justify-content: flex-end;
}

.center {
  margin: auto;
}

http://codepen.io/rgfx/pen/BLorgd


8
这并不能真正使中间项目居中,因为它仅考虑剩余空间,而不考虑整个空间。codepen.io/anon/pen/QKGrRk
Michael Benjamin

@Michael_B,您的权利没有注意到,我不好。返回使用绝对位置:(也许与你的高代表你应该设定一个赏金得到这个解决好我想,但我有一个非常低的代表,甚至更低,现在想帮你。
rgfx

今天,给定的答案就已经足够好了,Michael_B并没有为Linux的Flexbox模型添加新的行为。
阿森

0

我扩展了Michael_B答案

.center-flex__2-of-3 > :nth-child(1), .center-flex__2-of-3 > :nth-child(3) {
  flex: 1;
}
.center-flex__2-of-3 > :nth-child(1) {
  justify-content: flex-start;
}
.center-flex__2-of-3 > :nth-child(3) {
  justify-content: flex-end;
}
.center-flex__1-of-2 > :nth-child(1) {
  margin: auto;
}
.center-flex__1-of-2 > :nth-child(2) {
  flex: 1;
  justify-content: flex-end;
}
.center-flex__2-of-2 > :nth-child(1) {
  flex: 1;
  justify-content: flex-start;
}
.center-flex__2-of-2 > :nth-child(2) {
  margin: auto;
}
.center-flex__1-of-2:before, .center-flex__1-of-1:before {
  content: '';
  flex: 1;
}
.center-flex__1-of-1:after, .center-flex__2-of-2:after {
  content: '';
  flex: 1;
}

[class*=center-flex] {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  border: 10px solid rgba(0, 0, 0, 0.1);
}
[class*=center-flex] > * {
  display: flex;
}
li {
  padding: 3px 5px;
}
2 of 3
<ul class="center-flex__2-of-3">
  <span>
    <li>Accusamus</li>
    <li>Porro</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
1 of 2
<ul class="akex center-flex__1-of-2">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
</ul>

<br><br>
2 of 2
<ul class="akex center-flex__2-of-2">
  <span>
    <li>Porro</li>
    <li>Culpa</li>
    <li>Sit</li>
  </span>
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

<br><br>
1 of 1
<ul class="center-flex__1-of-1">
  <span>
    <li>Lorem</li>
    <li>Dolor</li>
  </span>
</ul>

这里借助SASS作为代码笔


0

受到@Michal Benjamin解决方案的方法#5:CSS网格布局启发,并且由于我使用的是Tailwind,到目前为止,默认情况下仍然无法访问所有网格选项。这似乎可行:

ul {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
li:nth-child(1) { justify-content: flex-start; } // OR: margin-right: auto
li:nth-child(3) { justify-content: flex-end; } // OR: margin-left:auto
li: {align-self: center;}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>

PS:不确定像这样混合flex和grid是否是个好主意!


1
您没有混合使用网格和flex,justifty-content是CSS网格属性和flexbox属性(与align-self相同)
Temani Afif

-1

可以稍微更改可接受的答案,因为您可以使用网格模板区域并且可以在不使用假元素的情况下进行操作

grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr

-1
ul { 
  padding: 0; 
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  position:absolute;
  right:10px;

}
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
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.