当侧边项目有不同的宽度时,保持中间项目居中

enter image description here

设想下面的布局,其中的点表示盒子之间的空间:

[Left box]......[Center box]......[Right box]

当我移除右边的盒子时,我希望中间的盒子仍然在中间,像这样:

[Left box]......[Center box].................

如果我移除左边的盒子也是一样。

................[Center box].................

现在,当中心框内的内容变长时,它将在保持居中状态的同时,根据需要占用尽可能多的可用空间。左边和右边的盒子将永远不会收缩,因此当没有空间留给 overflow:hiddentext-overflow: ellipsis将有效地打破内容;

[Left box][Center boxxxxxxxxxxxxx][Right box]

以上都是我的理想情况,但我不知道如何实现这个效果。因为当我创建一个这样的伸缩结构时:

.parent {
display : flex; // flex box
justify-content : space-between; // horizontal alignment
align-content   : center; // vertical alignment
}

如果左边和右边的盒子大小完全一样,我就可以得到想要的效果。然而,当其中一个来自不同的大小,居中的盒子不再真正居中。

有人能帮我吗?

更新

justify-self是不错的选择,这是最理想的:

.leftBox {
justify-self : flex-start;
}


.rightBox {
justify-self : flex-end;
}
120227 次浏览

如果左右方框的大小完全相同,我就会得到想要的效果。然而,当其中一个大小不同时,居中的盒子就不再是真正的居中了。有人能帮我吗?

下面是一个使用flexbox将中间项居中的方法,而不考虑兄弟项的宽度。

主要特点:

  • 纯CSS
  • 没有绝对定位
  • 没有JS / jQuery

使用嵌套的伸缩容器和auto边距:

.container {
display: flex;
}
.box {
flex: 1;
display: flex;
justify-content: center;
}


.box:first-child > span { margin-right: auto; }


.box:last-child  > span { margin-left: auto;  }


/* non-essential */
.box {
align-items: center;
border: 1px solid #ccc;
background-color: lightgreen;
height: 40px;
}
p {
text-align: center;
margin: 5px 0 0 0;
}
<div class="container">
<div class="box"><span>short text</span></div>
<div class="box"><span>centered text</span></div>
<div class="box"><span>loooooooooooooooong text</span></div>
</div>
<p>&#8593;<br>true center</p>

下面是它的工作原理:

  • 顶层的div (.container)是一个伸缩容器。
  • 每个子div (.box)现在都是一个伸缩项。
  • 每个.box项被赋予flex: 1,以便平均分配容器空间(更多的细节)。
  • 现在这些项占用了行中的所有空间,并且宽度相等。
  • 将每个项目设置为(嵌套的)伸缩容器,并添加justify-content: center
  • 现在每个span元素都是居中的伸缩项。
  • 使用flex auto边距来左右移动外部的__abc1。

你也可以放弃justify-content而专门使用auto边距。

但是justify-content可以在这里工作,因为auto页边距总是有优先级。

8.1。与auto对齐 利润< /强> < / > < / p >

在通过justify-contentalign-self对齐之前,any 正自由空间被分配到该维度的自动边距

  1. 在容器中使用三个伸缩项目
  2. flex: 1设置为第一个和最后一个。这使得它们平均生长,以填满中间那棵留下的可用空间。
  3. 这样,中间的那个就会趋于居中。
  4. 然而,如果第一个或最后一个项的内容较宽,该伸缩项也将由于新的min-width: auto初始值而增长。

    注意Chrome似乎没有正确地实现这一点。但是,你可以将min-width设置为-webkit-max-content-webkit-min-content,它也可以工作

  5. 只有在这种情况下,中间的元素才会被推出中心。

.
.outer-wrapper {
display: flex;
}
.item {
background: lime;
margin: 5px;
}
.left.inner-wrapper, .right.inner-wrapper {
flex: 1;
display: flex;
min-width: -webkit-min-content; /* Workaround to Chrome bug */
}
.right.inner-wrapper {
justify-content: flex-end;
}
.animate {
animation: anim 5s infinite alternate;
}
@keyframes anim {
from { min-width: 0 }
to { min-width: 100vw; }
}
<div class="outer-wrapper">
<div class="left inner-wrapper">
<div class="item animate">Left</div>
</div>
<div class="center inner-wrapper">
<div class="item">Center</div>
</div>
<div class="right inner-wrapper">
<div class="item">Right</div>
</div>
</div>
<!-- Analogous to above --> <div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item animate">Center</div></div><div class="right inner-wrapper"><div class="item">Right</div></div></div><div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item">Center</div></div><div class="right inner-wrapper"><div class="item animate">Right</div></div></div>

你可以这样做:

.
.bar {
display: flex;
background: #B0BEC5;
}
.l {
width: 50%;
flex-shrink: 1;
display: flex;
}
.l-content {
background: #9C27B0;
}
.m {
flex-shrink: 0;
}
.m-content {
text-align: center;
background: #2196F3;
}
.r {
width: 50%;
flex-shrink: 1;
display: flex;
flex-direction: row-reverse;
}
.r-content {
background: #E91E63;
}
<div class="bar">
<div class="l">
<div class="l-content">This is really long content.  More content.  So much content.</div>
</div>
<div class="m">
<div class="m-content">This will always be in the center.</div>
</div>
<div class="r">
<div class="r-content">This is short.</div>
</div>
</div>

而不是默认使用flexbox,使用网格在2行CSS中解决了这个问题,而不需要在顶级子级中添加额外的标记。

HTML:

<header class="header">
<div class="left">variable content</div>
<div class="middle">variable content</div>
<div class="right">variable content which happens to be very long</div>
</header>

CSS:

.header {
display: grid;
grid-template-columns: [first] 20% auto [last] 20%;
}
.middle {
/* use either */
margin: 0 auto;
/* or */
text-align: center;
}

Flexbox很棒,但不应该是所有问题的答案。在这种情况下,网格显然是最干净的选择。

甚至为你的测试乐趣做了一个代码依赖: https://codepen.io/anon/pen/mooQOV < / p >

你也可以使用这个简单的方法来达到中间元素的精确中心对齐:

.container {
display: flex;
justify-content: space-between;
}


.container .sibling {
display: flex;
align-items: center;
height: 50px;
background-color: gray;
}


.container .sibling:first-child {
width: 50%;
display: flex;
justify-content: space-between;
}


.container .sibling:last-child {
justify-content: flex-end;
width: 50%;
box-sizing: border-box;
padding-left: 100px; /* .center's width divided by 2 */
}


.container .sibling:last-child .content {
text-align: right;
}


.container .sibling .center {
height: 100%;
width: 200px;
background-color: lightgreen;
transform: translateX(50%);
}


codepen: https://codepen.io/ErAz7/pen/mdeBKLG

这里有一个答案,使用网格而不是flexbox。这个解决方案不需要像接受的答案那样在HTML中添加额外的孙子元素。即使一边的内容足够长,溢出到中间,它也能正常工作,不像2019年的网格答案。

这个解决方案没有做的一件事是显示省略号或隐藏在中心框中的额外内容,如问题中所述。

section {
display: grid;
grid-template-columns: 1fr auto 1fr;
}


section > *:last-child {
white-space: nowrap;
text-align: right;
}


/* not essential; just for demo purposes */
section {
background-color: #eee;
font-family: helvetica, arial;
font-size: 10pt;
padding: 4px;
}


section > * {
border: 1px solid #bbb;
padding: 2px;
}
<section>
<div>left</div>
<div>center</div>
<div>right side is longer</div>
</section>


<section>
<div>left</div>
<div>center</div>
<div>right side is much, much longer</div>
</section>


<section>
<div>left</div>
<div>center</div>
<div>right side is much, much longer, super long in fact</div>
</section>

下面是另一种方法,在父类和子类中使用display: flex:

.Layout{
display: flex;
justify-content: center;
}
.Left{
display: flex;
justify-content: flex-start;
width: 100%;
}
.Right{
display: flex;
justify-content: flex-end;
width: 100%;
}
<div class = 'Layout'>
<div class = 'Left'>I'm on the left</div>
<div class = 'Mid'>Centered</div>
<div class = 'Right'>I'm on the right</div>
</div>

虽然我在这个问题上可能晚了,但所有这些解决方案似乎都很复杂,而且根据你所面临的情况可能不会起作用。

非常简单,只需要用position : absolute包装你想要居中的组件,而让其他两个用justify-content : space-between,如下所示:

CSS:

.container {
display: flex;
justify-content: space-between;
align-items: center;
background-color: lightgray;
}


.middle {
position: absolute;
margin-left: auto;
margin-right: auto;
/* You should adapt percentages here if you have a background ; else, left: 0 and right: 0 should do the trick */
left: 40%;
right: 40%;
text-align: center;
}


/* non-essential, copied from @Brian Morearty answer */
.element {
border: 1px solid #ccc;
background-color: lightgreen;
}


p {
margin: 5px;
padding: 5px;
}
<div class="container">
<p class="element">First block</p>
<p class="middle element">Middle block</p>
<p class="element">Third THICC blockkkkkkkkk</p>
</div>

关键是要使用flex-basis。那么解决方案很简单:

.parent {
display: flex;
justify-content: space-between;
}


.left, .right {
flex-grow: 1;
flex-basis: 0;
}

CodePen可用在这里

稍微健壮一点的网格解决方案如下所示:

.container {
overflow: hidden;
border-radius: 2px;
padding: 4px;
background: orange;
display: grid;
grid-template-columns: minmax(max-content, 1fr) auto minmax(max-content, 1fr);
}


.item > div {
display: inline-block;
padding: 6px;
border-radius: 2px;
background: teal;
}


.item:last-child > div {
float: right;
}
<div class="container">
<div class="item"><div contenteditable>edit the text to test the layout</div></div>
<div class="item"><div contenteditable>just click me and</div></div>
<div class="item"><div contenteditable>edit</div></div>
</div>

这里你可以在Codepen: https://codepen.io/benshope2234/pen/qBmZJWN中看到它

enter image description here

我想要在问题中显示的确切结果,我结合了gamliela和Erik Martín Jordán的答案,它最适合我。

.parent {
display: flex;
justify-content: space-between;
}


.left, .right {
flex-grow: 1;
flex-basis: 0;
}


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

Michael Benjamin给出了一个不错的答案,但没有理由不能/不应该进一步简化:

.container {
display: flex;
}


.box {
flex: 1;
display: flex;
justify-content: center;
}


.box:first-child { justify-content: left; }


.box:last-child  { justify-content: right;  }

和html

<div class="container">
<div class="box">short text</div>
<div class="box">centered tex</div>
<div class="box">loooooooooooooooong text</div>
</div>