当被其他弹性项目包围时,在容器中居中弹性项目

Posted

技术标签:

【中文标题】当被其他弹性项目包围时,在容器中居中弹性项目【英文标题】:Center flex item in container, when surrounded by other flex items 【发布时间】:2016-12-26 00:31:43 【问题描述】:

我有一个 flex-box(参见下面的 sn-p 示例)。

我想设置它,以便在所有情况下,<h2> 都位于 flex-box 的中心,而其他跨度将根据它们的标记围绕它流动。

我基本上是在寻找align-self CSS 代码,但它是针对主轴,而不是横轴(this 可能有助于解释我的要求)。

我还将margin: auto; 应用于我的<h2>,这是我在阅读this 后了解到的(很棒的页面,但仍然给我留下了以下问题——除非我没有完全理解它)。

这是我得到的代码:

.container 
  align-items: center;
  border: 1px solid red;
  display: flex;
  justify-content: center;
  width: 100%;

h2 
  margin: auto;
]
<div class="container">
  <h2>I'm an h2</h2>
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <span>I'm span 3</span>
</div>
<div class="container">
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <span>I'm span 3</span>
  <h2>I'm an h2</h2>
  <span>I'm span 4</span>
  <span>I'm span 5</span>
  <span>I'm span 6</span>
</div>
<div class="container">
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <h2>I'm an h2</h2>
  <span>I'm span 3</span>
</div>

完全重申我的问题:我想知道如何将&lt;h2&gt; 放在我的页面的中心,这样无论其他&lt;span&gt;s 在哪里,&lt;h2&gt; 将始终处于死亡 strong> 弹性盒的中心。

谢谢。

附:我愿意使用 JS 和 jQuery,但更喜欢纯 CSS 方式来实现这一点。

更新

这是@Michael_B回答后更新

他的回答让我思考。虽然我还没有找到这样做的方法,但我相信以下是朝着正确方向迈出的一步:

HTML

<div class="container">
  <div>
    <span>I'm span 1</span>
    <span>I'm span 2</span>
    <span>I'm span 3</span>
  </div>
  <h2>I'm an h2</h2>
  <div>
    <span>I'm span 4</span>
    <span>I'm span 5</span>
    <span>I'm span 6</span>
  </div>
</div>

CSS

.container div 
  flex: 1 1 auto;
  text-align: center;

h2 
  flex: 0 0 auto;
  margin: auto;

.container 
  align-items: center;
  border: 1px solid red;
  display: flex;
  justify-content: center;
  width: 100%;

.container div 
  flex: 1 1 auto;
  text-align: center;

h2 
  flex: 0 0 auto;
  margin: auto;
<div class="container">
  <div>
  </div>
  <h2>I'm an h2</h2>
  <div>
    <span>I'm span 1</span>
    <span>I'm span 2</span>
    <span>I'm span 3</span>
  </div>
</div>
<div class="container">
  <div>
    <span>I'm span 1</span>
    <span>I'm span 2</span>
    <span>I'm span 3</span>
  </div>
  <h2>I'm an h2</h2>
  <div>
    <span>I'm span 4</span>
    <span>I'm span 5</span>
    <span>I'm span 6</span>
  </div>
</div>
<div class="container">
  <div>
    <span>I'm span 1</span>
    <span>I'm span 2</span>
  </div>
  <h2>I'm an h2</h2>
  <div>
    <span>I'm span 3</span>
  </div>
</div>

理论上,虽然&lt;span&gt;s 的总数未知,但已知的是总共会有三个元素:&lt;div&gt;&lt;h2&gt;&lt;div&gt;

正如你在上面的 sn-p 中看到的,我已经尝试(flex: 0 0 autoflex: 1 1 auto等)让它工作但没有成功。谁能告诉我这是否是朝着正确方向迈出的一步,以及如何将其推向实际产品?

再次感谢您。

【问题讨论】:

【参考方案1】:

Flex 对齐属性通过分配容器中的可用空间来工作。

因此,当一个弹性项目与其他项目共享空间时,没有单步方法可以将其居中,除非两侧的兄弟元素的总长度相等

在第二个示例中,h2 两侧的跨度总长度相等。因此,h2 在容器中完美居中。

.container 
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid red;
    margin: 5px;
    padding: 5px;

p  text-align: center;
p > span  background-color: aqua; padding: 5px; 
<div class="container">
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <span>I'm span 3</span>
  <h2>I'm an h2</h2>
  <span>I'm span 4</span>
  <span>I'm span 5</span>
  <span>I'm span 6</span>
</div>
<p><span>TRUE CENTER</span></p>

请记住,将h2justify-content: center(或space-aroundspace-between)居中,只有在两边平衡时才有效。边之间的每个像素差异都会使h2 产生相应的量。

在您的第一个和最后一个示例中,双方之间存在明显的不平衡。 justify-contentmargin 等标准对齐属性将不起作用,因为它们在可用空间而不是总空间内居中。

您可以使用visibility: hidden 在相对侧插入重复的跨度以实现相等的平衡。但这会使您的标记在语义上毫无价值的元素中膨胀。

相反,如果你有能力计算出每个跨度的宽度,你可以插入伪元素来达到相等的平衡。

.container 
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1px solid red;
  margin: 5px;
  padding: 5px;

span 
  flex: 0 0 75px;
  border: 1px dashed black;
  box-sizing: border-box;

div.container:first-child::before 
  content: "";
  width: 225px;

.container:nth-child(2)::after 
 content: "";
  width: 75px;

p  text-align: center;
p > span  background-color: aqua; padding: 5px; border: none; 
<div class="container">
  <h2>I'm an h2</h2>
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <span>I'm span 3</span>
</div>
<div class="container">
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <h2>I'm an h2</h2>
  <span>I'm span 3</span>
</div>
<p><span>TRUE CENTER</span></p>

最后,作为 CSS 的最后手段,您可以使用绝对定位将 h2 居中。这将从文档流中移除元素,但始终保持它在容器中完全居中。

.container 
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1px solid red;
  position: relative; /* NEW */
  height: 50px;

h2 
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  margin: 0;
  
.container:nth-child(1)  justify-content: flex-end; 
.container:nth-child(2) > span:nth-of-type(4)  margin-left: auto;   
.container:nth-child(3) > span:nth-of-type(2)  margin-right: auto; 

p  text-align: center;
p > span  background-color: aqua; padding: 5px; 
<div class="container">
  <h2>I'm an h2</h2>
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <span>I'm span 3</span>
</div>
<div class="container">
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <span>I'm span 3</span>
  <h2>I'm an h2</h2>
  <span>I'm span 4</span>
  <span>I'm span 5</span>
  <span>I'm span 6</span>
</div>
<div class="container">
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <h2>I'm an h2</h2>
  <span>I'm span 3</span>
</div>
<p><span>TRUE CENTER</span></p>

更新(基于修改后的问题)

理论上,虽然&lt;span&gt;s 的总数未知,但已知的是总共有三个元素:&lt;div&gt;&lt;h2&gt;&lt;div&gt;

所以,如果我们知道总会有三个元素,那么就有一个使用 flex 属性的潜在解决方案。

.container 
  display: flex;

.container > * 
  flex: 1;  /* KEY RULE */

h2  
  text-align: center;
  margin: 0;

.container > div 
  display: flex;
  justify-content: space-around;


/* non-essential decorative styles */
.container  background-color: lightgreen; border: 1px solid #ccc; padding: 5px; 
.container > *  border: 1px dashed red; 
p  text-align: center;
p > span  background-color: aqua; padding: 5px; 
<div class="container">
  <div>
    <span>I'm span 1</span>
    <span>I'm span 2</span>
    <span>I'm span 3</span>
  </div>
  <h2>I'm an h2</h2>
  <div>
    <span>I'm span 4</span>
    <span>I'm span 5</span>
    <span>I'm span 6</span>
  </div>
</div>
<p><span>TRUE CENTER</span></p>

这是发生了什么:

这三个元素都是弹性项目,因为它们的父级是弹性容器 每个项目都有一个flex: 1,这使它们能够在它们之间平均分配容器空间。最终结果是三个等宽的项目。 现在,在 h2 元素中居中 h2 文本也会使容器中的文本居中。 每个 div 都可以做成一个嵌套的 flex 容器,span 可以与 flex 属性对齐。

更多信息和解决方案:

Center and right align flexbox elements Keep the middle item centered when side items have different widths

【讨论】:

哇!确实是一个精明的答案。在此之后我已经更新了我的答案,也许您对此有进一步的了解?谢谢。 我的朋友,你是弹性盒之神。这真的很有帮助。我有最后一个问题,如果你当然愿意(我只是在测试你的最后一次更新时才想到它)。也许它太多了,但也许你可以帮忙。你已经非常慷慨了。 由于 Stack Overflow Q & A 旨在为更广泛的开发者社区提供高质量的参考,添加太多更新和偏离原始问题会使这篇文章变得不那么有用并且有些复杂。我建议您将这个问题集中在一个特定问题上。关于使用 order 属性居中的问题,请考虑发布一个新问题。 是的,你是对的。谢谢你。我已将其设为新问题 (***.com/questions/39043729/…) 并将其从该问题中删除【参考方案2】:

一种方法是在两侧添加空跨度,然后将跨度和 h2 设置为某个 flex 值,如下所示:

.container 
  align-items: center;
  border: 1px solid red;
  display: flex;
  justify-content: center;
  width: 100%;

h2 
  margin: auto;
  text-align: center;
  flex: 3 0;

span
  flex: 1 0;
<div class="container">
<span></span>
<span></span>
<span></span>
  <h2>I'm an h2</h2>
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <span>I'm span 3</span>
</div>
<div class="container">
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <span>I'm span 3</span>
  <h2>I'm an h2</h2>
  <span>I'm span 4</span>
  <span>I'm span 5</span>
  <span>I'm span 6</span>
</div>
<div class="container">
  <span>I'm span 1</span>
  <span>I'm span 2</span>
  <span></span>
  <h2>I'm an h2</h2>
  <span>I'm span 3</span>
  <span></span>
  <span></span>
</div>

所以你保证两边的空间是相等的。那么唯一的问题是您必须确定您希望 h2 采用多少宽度。

【讨论】:

哇!好点子。这很好,但需要始终有六个跨度(每侧三个)如果我将此 html 分发给我的一位同事并且他忘记放置额外的跨度,它将出错。你知道吗?这是否可能需要 JS 代码来验证有六个/偶数(例如,如果每边放置超过 6 个跨度)?再次感谢您的回答

以上是关于当被其他弹性项目包围时,在容器中居中弹性项目的主要内容,如果未能解决你的问题,请参考以下文章

如何使弹性容器居中但左对齐弹性项目

防止弹性项目高度扩展以匹配其他弹性项目

如何在弹性容器中居中卡片

如何在弹性项目(单元格)中居中图像

在列表中居中弹性项目

当它也是一个弹性容器时,如何防止最后一个弹性项目填充剩余宽度[重复]