居中和右对齐flexbox元素

时间:2016-08-15 01:13:17

标签: html css css3 flexbox

我希望A BC在中间对齐。

如何让D完全向右走?

在:

enter image description here

在:

enter image description here

这样做的最佳做法是什么?

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/

10 个答案:

答案 0 :(得分:123)

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

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

方法#1:CSS定位属性

position: relative应用于Flex容器。

position: absolute应用于项目D.

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

更具体地说,项目D已从文档流程中删除,但仍在nearest positioned ancestor的范围内。

使用CSS偏移属性topright将此元素移动到位。

&#13;
&#13;
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;
}
&#13;
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>
&#13;
&#13;
&#13;

对此方法的一个警告是某些浏览器可能无法从正常流程中完全删除绝对定位的Flex项目。这会以非标准的,意外的方式更改对齐方式。更多详情: Absolutely positioned flex item is not removed from the normal flow in IE11

方法#2:Flex Auto Margins&amp;不可见的Flex项目(DOM元素)

结合auto margins和新的隐形弹性项目,可以实现布局。

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

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

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

简而言之:

  • 创建D元素的副本。
  • 将其放在列表的开头。
  • 使用flex auto页边距保持ABC居中,两个D元素从两端创造平衡。
  • visibility: hidden应用于重复的D

&#13;
&#13;
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; }
&#13;
<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>
&#13;
&#13;
&#13;

方法#3:Flex Auto Margins&amp;不可见的Flex项(伪元素)

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

  • 创建一个与D宽度相同的伪元素。
  • 使用::before将其放在容器的开头。
  • 使用flex auto页边距保持ABC完美居中,伪和D元素从两端创造平衡。

&#13;
&#13;
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; }
&#13;
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>
&#13;
&#13;
&#13;

方法#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),在某种程度上仍然在许多浏览器中生效。有关完整的详细信息,请参阅herehere

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

&#13;
&#13;
#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;
}
&#13;
<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>
&#13;
&#13;
&#13;

解决方案是不使用百分比单位。尽管事实上至少有一些主流浏览器出于某种原因附加了一个百分比单位,但请尝试px或根本不做任何事情(which is what the spec actually recommends。)

&#13;
&#13;
#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;
}
 */
&#13;
<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>
&#13;
&#13;
&#13;

方法#5:CSS网格布局

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

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

&#13;
&#13;
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; }
&#13;
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>| true center |</span></p>
&#13;
&#13;
&#13;

答案 1 :(得分:7)

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

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>

答案 2 :(得分:2)

如果要使其对齐,可以简单地附加一个空跨度并将三个子跨度拆分为它们。

答案 3 :(得分:0)

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

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

.center {
  margin: auto;
}

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

答案 4 :(得分:0)

我在Michael_Banswer

上进行了扩展

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

Here with the help of SASS as a codepen

答案 5 :(得分:0)

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

答案 6 :(得分:0)

最简单的方法

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

答案 7 :(得分:0)

Method #5: CSS Grid Layout解决方案的@Michal Benjamin的启发,并且由于我使用的是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是否是个好主意!

答案 8 :(得分:-2)

可以稍作更改,因为您可以使用网格模板区域并且无需假元素即可完成

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

答案 9 :(得分:-2)

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>