将一个flexbox元素居中并使其左/右对齐 [英] Center one and right/left align other flexbox element
问题描述
我想拥有 A
B
和 C
对齐在中间。
I would like to have A
B
and C
aligned in the middle.
如何获得 D
完全移到右边?
How can I get D
to go completely to the right?
之前:
之后:
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/
推荐答案
以下是实现此布局的五个选项:
Below are five options for achieving this layout:
- CSS定位
- 带有不可见DOM元素的Flexbox
- 带有不可见的伪元素的Flexbox
- 带有
flex的Flexbox:1
- CSS网格布局
- CSS Positioning
- Flexbox with Invisible DOM Element
- Flexbox with Invisible Pseudo-Element
- Flexbox with
flex: 1
- CSS Grid Layout
将 position:relative
应用于flex容器。
Apply position: relative
to the flex container.
将位置:绝对
应用于项目D。
现在,此项目已完全放置在flex容器中。
Now this item is absolutely positioned within the flex container.
更具体地说,项目D已从文档流中删除,但仍位于 最靠近的祖先 。
More specifically, item D is removed from the document flow but stays within the bounds of the nearest positioned ancestor.
使用CSS偏移属性 top
和右
将元素移到位置。
Use the CSS offset properties top
and right
to move this element into position.
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>
此方法的一个警告是,某些浏览器可能无法从正常流程中完全删除绝对定位的flex项目。这将以非标准的意外方式更改对齐方式。更多详细信息: 绝对定位的弹性商品不会从IE11的常规流程中删除
One caveat to 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
与 auto
边距和一个新的,不可见的flex项目,可以实现布局。
With a combination of auto
margins and a new, invisible flex item the layout can be achieved.
新的flex项与项D相同,并位于另一端(左边缘)。
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.
使用<$将新项目从视图中删除c $ c>可见性:隐藏。
简而言之:
- 创建
D
元素的副本。 - 将其放在列表的开头。
- 使用flex
auto
边距来保持A
,B
和C
居中,两个D
元素在两端产生相等的余额。 - 将
可见性:隐藏
应用于重复的D
- 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
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>
此方法与#2相似,但在语义上更清晰,且宽度 D
必须是已知的。
This method is similar to #2, except it's cleaner semantically and the width of D
must be known.
- 创建一个宽度与
D $ c相同的伪元素$ c>。
- 使用
:: before
将其放在容器的开头。 - 使用flex
auto
边距来保持A
,B
和C
完美居中,伪元素和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.
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>
从上面的方法2或方法3开始,不必担心左右物品的宽度相等以保持平衡,给每个一个 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.
然后您可以添加 display:flex
以使各个项目保持一致。
You can then add display: flex
to individual items in order to align their content.
注意 关于将此方法与最小高度
:当前在Chrome,Firefox,Edge和其他浏览器中,速记规则 flex:1
细分为:
-
flex-grow:1
-
flex-shrink:1
-
flex-basis:0%
flex-grow: 1
flex-shrink: 1
flex-basis: 0%
flex-上的百分比单位(%)在容器上使用
会使此方法中断。这是因为,通常来说,孩子的百分比高度要求在父对象上具有明确的最小高度
时,base height
属性设置。
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.
这是一条可以追溯到1998年的旧CSS规则( CSS 2级)在某种程度上仍在许多浏览器中有效。有关完整的详细信息,请参见 此处 和 此处 。
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 here and here.
这是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
或根本不尝试(这是规范的实际建议,尽管事实上至少有一些主要的浏览器出于某种原因附加了百分比单位。
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).
#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>
这可能是最干净,最有效的方法。不需要绝对定位,伪造元素或其他黑客手段。
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>
这篇关于将一个flexbox元素居中并使其左/右对齐的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!