居中,右/左对齐其他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/

156268 次浏览

下面是实现这种布局的五个选项:

  • CSS定位
  • Flexbox与隐形DOM元素
  • Flexbox与隐形伪元素
  • Flexbox与flex: 1
  • CSS网格布局

方法#1:CSS定位属性

position: relative应用于伸缩容器。

对D项应用position: absolute

现在这个项目完全位于伸缩容器中。

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

使用CSS偏移量属性topright来移动该元素。

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

一个警告与此方法的区别在于,一些浏览器可能不会完全从正常流中删除绝对定位的伸缩项。这会以一种非标准的、意想不到的方式改变对齐方式。更多详细信息:绝对定位的伸缩项目没有从IE11的正常流程中删除 .


方法#2:Flex Auto margin &不可见的伸缩项目(DOM元素)

通过< >强auto < / >强劲的利润和一个新的、不可见的flex项目的组合,可以实现布局。

新的伸缩项目与项目D相同,并被放置在相反的一端(左边缘)。

更具体地说,因为伸缩对齐是基于自由空间的分配,新项目是保持中间三个盒子水平居中的必要平衡。新项目必须与现有的D项目宽度相同,否则中间的方框不会精确居中。

使用visibility: hidden将新项从视图中移除。

简而言之:

  • 创建D元素的副本。
  • 把它放在列表的开头。
  • 使用flex auto边距来保持ABC居中,两个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; }
<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>


方法#3:弹性自动裕量不可见的伸缩项目(伪元素)

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

  • 创建一个与D宽度相同的伪元素。
  • ::before将它放在容器的开头。
  • 使用flex auto边距来保持ABC完美居中,而pseudo和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; }
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>


方法4:将flex: 1添加到左右项

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

然后,您可以将display: flex添加到各个项目中,以便对齐它们的内容。

目前在Chrome, Firefox, Edge和可能的其他浏览器中,速记规则flex: 1分解为:

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

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

这是一条可以追溯到1998年(CSS级别2)的老CSS规则,在许多浏览器中或多或少仍然有效。详细信息见这里<强> < / >强这里<强> < / >强

下面是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;
}
<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>

解决方案是不使用百分比单位。尝试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;
}
*/
<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>


方法#5:CSS网格布局

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

只需创建一个包含多列的网格。然后把你的项目放在中间和结尾的列中。基本上,只要把第一列空了。

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>

非常清楚的问题。经过几个小时的挖掘,我忍不住把答案贴了出来。我们可以用表格,表格单元格,绝对位置,转换来解决这个问题,但我们必须用flexbox来做:)

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


.center {
margin: auto;
}

< a href = " http://codepen。io / rgfx /钢笔/ BLorgd " rel = " http://codepen.io/rgfx/pen/BLorgd nofollow”> < / >

我扩展了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>Center</li>
<li>this</li>
</span>
<span>
<li>Accusamus</li>
<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>Center</li>
<li>this</li>
</span>
<span>
<li>Accusamus</li>
<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>Accusamus</li>
<li>Porro</li>
<li>Culpa</li>
<li>Sit</li>
</span>
<span>
<li>Center</li>
<li>this</li>
</span>
</ul>


<br><br>
1 of 1
<ul class="center-flex__1-of-1">
<span>
<li>Center</li>
<li>this</li>
</span>
</ul>

< a href = " https://codepen.io/HerrSerker/pen/dQxMdO?editors=1100" rel="nofollow noreferrer">这里有SASS的帮助作为一个代码依赖

接受的答案可以改变一点,因为你可以使用网格模板区域,没有假元素

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

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

如果您想使它对齐,您可以简单地附加一个空span并将三个子span分割为它们。

最简单的方法

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

最简单的解决方案是将justify-content center设置为父容器,并将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>

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>

受到@Michal本杰明的解决方案的方法#5:CSS网格布局的启发,因为我正在使用顺风,到目前为止,默认情况下仍然没有访问所有的网格选项。这似乎很有效:

ul {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
}


li {
align-self: center;
}


li:nth-child(1) {
justify-content: flex-start; /* OR margin-right: auto */
}


li:nth-child(3) {
justify-content: flex-end; /* OR margin-left:auto */
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>

PS:不确定把flex和grid混合起来是不是一个好主意!

最简单的方法:

.wrap {
display:flex;
}
.full-width {
width: 100%;
}
.centered {
display: flex;
justify-content:center;
}
.btn {
display: flex;
justify-content: end;
}
<div class="wrap">
<div class="full-width"></div>
<div class="full-width centered">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
<div class="full-width btn">D</div>
</div>