Html 居中和右对齐 flexbox 元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38948102/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Center and right align flexbox elements
提问by hazyred
I would like to have A
B
and C
aligned in the middle.
我想有A
B
和C
中间对齐。
How can I get D
to go completely to the right?
我怎样才能D
完全向右走?
BEFORE:
前:
AFTER:
后:
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>
回答by Michael Benjamin
Below are five options for achieving this layout:
以下是实现此布局的五个选项:
- CSS Positioning
- Flexbox with Invisible DOM Element
- Flexbox with Invisible Pseudo-Element
- Flexbox with
flex: 1
- CSS Grid Layout
- CSS 定位
- 带有隐形 DOM 元素的 Flexbox
- 带有隐形伪元素的 Flexbox
- 弹性盒与
flex: 1
- CSS 网格布局
Method #1: CSS Positioning Properties
方法 #1:CSS 定位属性
Apply position: relative
to the flex container.
应用于position: relative
弹性容器。
Apply position: absolute
to item D.
适用position: absolute
于 D 项。
Now this item is absolutely positioned within the flex container.
现在这个项目绝对定位在 flex 容器中。
More specifically, item D is removed from the document flow but stays within the bounds of the nearest positioned ancestor.
更具体地说,项目 D 从文档流中删除,但保留在最近定位的祖先的范围内。
Use the CSS offset properties top
and right
to move this element into position.
使用 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;
}
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<p><span>true center</span></p>
One caveatto this method is that some browsers may not completely remove an absolutely-positioned flex item from the normal flow. This changes the alignment in a non-standard, unexpected way. More details: Absolutely positioned flex item is not removed from the normal flow in IE11
这种方法的一个警告是一些浏览器可能不会从正常流中完全删除绝对定位的弹性项目。这以一种非标准的、意想不到的方式改变了对齐方式。更多细节:绝对定位的 flex 项目不会从 IE11 中的正常流程中删除
Method #2: Flex Auto Margins & Invisible Flex Item (DOM element)
方法#2:Flex Auto Margins & Invisible Flex Item(DOM 元素)
With a combination of auto
marginsand a new, invisible flex item the layout can be achieved.
通过结合auto
边距和一个新的、不可见的弹性项目,可以实现布局。
The new flex item is identical to item D and is placed at the opposite end (the left edge).
新的 flex 项目与项目 D 相同,并放置在另一端(左边缘)。
More specifically, because flex alignment is based on the distribution of free space, the new item is a necessary counterbalance to keep the three middle boxes horizontally centered. The new item must be the same width as the existing D item, or the middle boxes won't be precisely centered.
更具体地说,因为 flex 对齐是基于自由空间的分布,新项目是保持三个中间框水平居中的必要平衡。新项目必须与现有 D 项目的宽度相同,否则中间的框不会精确居中。
The new item is removed from view with visibility: hidden
.
使用 将新项目从视图中删除visibility: hidden
。
In short:
简而言之:
- Create a duplicate of the
D
element. - Place it at the beginning of the list.
- Use flex
auto
margins to keepA
,B
andC
centered, with bothD
elements creating equal balance from both ends. - Apply
visibility: hidden
to the duplicateD
- 创建
D
元素的副本。 - 将其放在列表的开头。
- 使用Flex
auto
利润率保持A
,B
并C
居中,既有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>
Method #3: Flex Auto Margins & Invisible Flex Item (pseudo-element)
方法#3:Flex Auto Margins & Invisible Flex Item(伪元素)
This method is similar to #2, except it's cleaner semantically and the width of D
must be known.
这种方法与#2 类似,但它在语义上更清晰,并且D
必须知道的宽度。
- Create a pseudo-element with the same width as
D
. - Place it at the start of the container with
::before
. - Use flex
auto
margins to keepA
,B
andC
perfectly centered, with the pseudo andD
elements creating equal balance from both ends.
- 创建一个与
D
. - 用 将它放在容器的开头
::before
。 - 使用 flex
auto
margins 保持A
,B
并C
完美居中,伪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>
Method #4: Add flex: 1
to left and right items
方法#4:添加flex: 1
到左右项目
Starting with Method #2 or #3 above, instead of worrying about equal width for the left and right items to maintain equal balance, just give each one flex: 1
. This will force them both to consume available space, thus centering the middle item.
从上面的方法 #2 或 #3 开始,与其担心左右项目的宽度相等以保持平衡,只需给每个flex: 1
. 这将迫使它们都消耗可用空间,从而使中间项目居中。
You can then add display: flex
to individual items in order to align their content.
然后,您可以添加display: flex
到单个项目以对齐它们的内容。
NOTEabout using this method with min-height
:Currently in Chrome, Firefox, Edge and possibly other browsers, the shorthand rule flex: 1
breaks down to this:
关于使用此方法的min-height
注意事项:目前在 Chrome、Firefox、Edge 和可能的其他浏览器中,速记规则flex: 1
分解为:
flex-grow: 1
flex-shrink: 1
flex-basis: 0%
flex-grow: 1
flex-shrink: 1
flex-basis: 0%
That percentage unit (%)on flex-basis
causes this method to break when min-height
is used on the container. This is because, as a general rule, percentage heights on the children require an explicit height
property setting on the parent.
该百分比单位(%)上flex-basis
的原因这种方法时,打破min-height
在容器上使用。这是因为,作为一般规则,子项的百分比高度需要height
在父项上进行明确的属性设置。
This is an old CSS rule dating back to 1998 (CSS Level 2) which is still in effect in many browsers to some degree or another. For complete details see hereand here.
这是一个可以追溯到 1998 年的旧 CSS 规则(CSS Level 2),它在某种程度上仍然在许多浏览器中有效。有关完整的详细信息,请参阅此处和此处。
Here's an illustration of the problem posted in the comments by user2651804:
这是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>
The solution is to not use the percentage unit. Try px
or just nothing at all (which is what the spec actually recommends, despite the fact that at least some of the major browsers have appended a percentage unit for whatever reason).
解决方案是不使用百分比单位。尝试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>
Method #5: CSS Grid Layout
方法 #5:CSS 网格布局
This may be the cleanest and most efficient method. There is no need for absolute positioning, fake elements or other hackery.
这可能是最干净、最有效的方法。不需要绝对定位、虚假元素或其他黑客。
Simply create a grid with multiple columns. Then position your items in the middle and end columns. Basically, just leave the first column empty.
只需创建一个具有多列的网格。然后将您的项目放在中间列和结束列中。基本上,只需将第一列留空。
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>
回答by Razib Hossain
Most easy way
最简单的方法
.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>
回答by Ali Korkmaz
If you want to make it aligned, you can simply attach an empty span and split the three child spans into them.
如果你想让它对齐,你可以简单地附加一个空的跨度并将三个子跨度拆分成它们。
回答by Saba Ahang
Inspired by the Method #5: CSS Grid Layoutof @Michal Benjamin's solution and because I'm using Tailwind and as of now still don't have access to all the grid options by default. This seems to work:
受到@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: Not sure if mixing up flex and grid like this is a good idea!
PS:不确定像这样混合 flex 和 grid 是否是个好主意!
回答by Suhail AKhtar
The simplest solution will be to justify-content center to the parent container and giving margin-left auto to first and last child element.
最简单的解决方案是将内容中心对齐到父容器,并为第一个和最后一个子元素提供 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>
回答by Steven Spungin
Using the display:grid
approach, you can simply put all of the ul
children into the same cell and then set justify-self
:
使用该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>
回答by rgfx
Very clear question. I couldn't help but post the answer after a few hours of digging. We Could of solved this with tables, table-cell, absolute positions, transforms but we just had to do it with flexbox :)
很清楚的问题。经过几个小时的挖掘,我忍不住发布了答案。我们可以用表格、表格单元格、绝对位置、变换来解决这个问题,但我们只需要用 flexbox 来做:)
.parent {
display: flex;
justify-content: flex-end;
}
.center {
margin: auto;
}
回答by yunzen
I expanded on Michael_B's answer
.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>
回答by repo
The accepted answer can be changed a bit because you can use grid template areas and do it without fake element
可接受的答案可以稍作更改,因为您可以使用网格模板区域并在没有假元素的情况下进行
grid-template-areas '. b c'
grid-template-columns: 1fr 1fr 1fr
回答by SUDHIR KUMAR
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>