居中和右对齐flexbox元素

haz*_*red 94 html css css3 flexbox

我想有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*/
}
Run Code Online (Sandbox Code Playgroud)
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/z44p7bsx/

Mic*_*l_B 154

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

  • CSS定位
  • 带有隐形DOM元素的Flexbox
  • 带有隐形伪元素的Flexbox
  • Flexbox用 flex: 1
  • CSS网格布局

方法#1:CSS定位属性

应用于position: relativeFlex容器.

适用position: absolute于项目D.

现在这个项目绝对位于flex容器中.

更具体地,项目D从文档流中移除,但保持在最近定位的祖先的边界内.

使用CSS偏移属性top并将right此元素移动到位.

li:last-child {
  position: absolute;
  top: 0;
  right: 0;
  background: #ddd;
}
ul {
  position: relative;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p {
  text-align: center;
  margin-top: 0;
}
span {
  background-color: aqua;
}
Run Code Online (Sandbox Code Playgroud)
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>
Run Code Online (Sandbox Code Playgroud)

这种方法的一个警告是,某些浏览器可能无法从正常流中完全删除绝对定位的Flex项.这会以非标准的,意外的方式更改对齐方式.更多细节:IE11中的正常流程中没有删除绝对定位的flex项目


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

通过auto边距和新的隐形弹性项目的组合,可以实现布局.

新的弹性项目与项目D相同,并放置在另一端(左边缘).

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

新视图将从视图中删除visibility: hidden.

简而言之:

  • 创建D元素的副本.
  • 将它放在列表的开头.
  • 使用Flex auto利润率保持A,BC居中,既有D元素创建从两端完全平衡.
  • 适用visibility: hidden于副本D

li:first-child {
  margin-right: auto;
  visibility: hidden;
}
li:last-child {
  margin-left: auto;
  background: #ddd;
}
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;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
Run Code Online (Sandbox Code Playgroud)
<ul>
  <li>D</li><!-- new; invisible spacer item -->
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>
Run Code Online (Sandbox Code Playgroud)


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

这种方法类似于#2,除了它在语义上更清晰,并且D必须知道宽度.

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

ul::before {
  content:"D";
  margin: 1px auto 1px 1px;
  visibility: hidden;
  padding: 5px;
  background: #ddd;
}
li:last-child {
  margin-left: auto;
  background: #ddd;
}
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;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }
Run Code Online (Sandbox Code Playgroud)
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>
Run Code Online (Sandbox Code Playgroud)


方法#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%

百分比单位(%) on flex-basis会导致此方法min-height在容器上使用时中断.这是因为,作为一般规则,子项的百分比高度需要height在父项上设置显式属性.

这是一个可追溯到1998年的旧CSS规则(CSS Level 2),它在某种程度上仍然在许多浏览器中生效.如需了解更多信息请参见这里这里.

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

#flex-container {
  display: flex;
  flex-direction: column;
  background: teal;
  width: 150px;
  min-height: 80vh;
  justify-content: space-between;
}

#flex-container>div {
  background: orange;
  margin: 5px;
}

#flex-container>div:first-child {
  flex: 1;
}

#flex-container::after {
  content: "";
  flex: 1;
}
Run Code Online (Sandbox Code Playgroud)
<div id="flex-container">
  <div>very long annoying text that will add on top of the height of its parent</div>
  <div>center</div>
</div>
Run Code Online (Sandbox Code Playgroud)

解决方案是不使用百分比单位.尝试px或者根本没有(这是规范实际推荐的内容,尽管至少有一些主流浏览器出于某种原因附加了一个百分比单位).

#flex-container {
  display: flex;
  flex-direction: column;
  background: teal;
  width: 150px;
  min-height: 80vh;
  justify-content: space-between;
}

#flex-container > div {
  background: orange;
  margin: 5px;
}


/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */

#flex-container > div:first-child {
  flex: 1;
  flex-basis: 0;
}

#flex-container::after {
  content: "";
  flex: 1;
  flex-basis: 0;
}


/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY

#flex-container > div:first-child {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}

#flex-container::after {
  content: "";
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}
 */
Run Code Online (Sandbox Code Playgroud)
<div id="flex-container">
  <div>very long annoying text that will add on top of the height of its parent</div>
  <div>center</div>
</div>
Run Code Online (Sandbox Code Playgroud)


方法#5:CSS网格布局

这可能是最干净,最有效的方法.不需要绝对定位,虚假元素或其他hackery.

只需创建一个包含多列的网格.然后将项目放在中间和结束列中.基本上,只需将第一列留空.

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; }
Run Code Online (Sandbox Code Playgroud)
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>| true center |</span></p>
Run Code Online (Sandbox Code Playgroud)

  • 喜欢使用可见性:隐藏在方法#2中 - 太聪明了!第一次得到隐藏的实际用途:D (3认同)
  • 很好的答案!测试了所有5个解决方案,每个解决方案都是可行的! (2认同)
  • 隐形弹性物品既黑客又聪明 (2认同)

Suh*_*tar 24

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

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


.a,.d {
  margin-left:auto;
}
Run Code Online (Sandbox Code Playgroud)
<ul>
  <li class="a">A</li>
  <li>B</li>
  <li>C</li>
  <li class="d">D</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,通过这种方法,A/B/C 将在*剩余*空间内居中。换句话说,即使有空间让它们相对于整个宽度居中,它们也不会居中。 (15认同)

Ste*_*gin 11

使用该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;
}
Run Code Online (Sandbox Code Playgroud)
<div class='ul'>
  <span>
     <span class='li'>A</span>
     <span class='li'>B</span>
     <span class='li'>C</span>
  </span>
  <span class='li'>D</span>
</div>
Run Code Online (Sandbox Code Playgroud)


Raz*_*ain 7

最简单的方法

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

  • 需要使用元素的精确 px 宽度可能会出现问题 (4认同)