将元素水平定心到其容器,同时避免重叠

时间:2017-02-24 21:12:46

标签: css css3 layout flexbox

我今天遇到了一个有趣的CSS问题,而且我一直在试图解决它的问题。

这类似于“一排三个元素,左边,右边和中心”的微不足道的问题,这可以通过flexbox轻松解决 - 但它有一些注意事项(我认为) )没有JavaScript的不可能的布局。

预期目标

考虑一个类似行的容器元素和三个子元素,“left”,“right”和“center”。孩子们可能有不同的宽度,但它们都是相同的高度。

“中心”应该尝试相对于其容器保持居中 - 但是三个兄弟元素不得重叠,并且可以在必要时推送到容器外。

然后,标记可能看起来像这样:

<div class="container">
    <div class="left">I'm the left content.</div>
    <div class="center">I'm the center content. I'm longer than the others.</div>
    <div class="right">Right.</div>
</div>

CSS是挑战所在。

对于宽容器,“中心”相对于容器居中(即,其兄弟姐妹的宽度无关紧要),如下图所示;注意“center”元素的中点与容器的中点匹配,左右“剩余”空格不相等:

Wide

对于较窄的容器,“中心”邻接最宽的兄弟,但它不重叠。剩余空间仅分布在 narrow 兄弟和“中心”兄弟之间。另请注意,由插入符指示的容器中点不再与“中心”中点相同:

Narrower

最后,随着容器继续缩小,没有其他选择,只能将所有三个元素排成一行,溢出父级:

Narrowest

我尝试解决此问题

令人惊讶的是,我还没有找到一种在纯CSS中实现它的好方法。

你认为flexbox会成为胜利者,但是你无法让flexbox正确地做到这一点:space-between属性在元素之间均匀分配空间,因此中心元素实际上并未结束向上集中。 flex - grow / shrink / basis属性也不是特别有用,因为它们负责控制子元素的大小,而不是控制子元素的大小它们之间的空间。

只要容器足够宽,使用position:absolute就可以解决它,但当容器缩小时,最终会出现重叠。

(并且浮动布局无法在达到这一目标的一英里之内。)

我可以将上面最好的两个解决方案结合起来,并使用@media查询在它们之间切换 - 如果所有宽度都事先已知。但它们不是,尺寸可能差别很大。

简而言之,我所知道的这个问题没有纯HTML-and-CSS解决方案。

结论,以及一个JSFiddle来试验

我创建了一个JSFiddle,它既显示了所需的目标,也显示了一些非解决方案。随意分叉并进行实验。您可以通过抓取内容左侧的栏并拖动它来模拟容器调整大小。您可以重新排列/重新构建HTML和CSS,如果重写它可以让您更接近工作答案。

  

https://jsfiddle.net/seanofw/35qmdnd6

那么有没有人有这个解决方案,不涉及使用JavaScript智能地分配元素之间的空间?

1 个答案:

答案 0 :(得分:2)

使用flexbox,您应该能够通过提供left / right元素flex: 1和右text-align: right来解决这个问题。

主要技巧是flex: 1,这将使他们平等分享可用空间。

有关更多版本,请参阅此精彩问题/答案,flexbox-justify-items-and-justify-self-properties

Fiddle snippet

Stack snippet

body {
  font: 14px Arial;
}
.container {
  display: flex;
  border: 1px solid #00F;
}
.container > div > span {
  display: inline-block;
  background: #36F;
  white-space: nowrap;
  padding: 2px 4px;
  color: #FFF;
}
.container > .center > span {
  background: #696;
}

.container .left,
.container .right {
  flex: 1;
}
.container .right {
  text-align: right;
}

.center-mark {
  text-align: center;
  font-size: 80%;
}
.note {
  text-align: center;
  color: #666;
  font-style: italic;
  font-size: 90%;
}
<div class="container">
  <div class="left">
    <span>
      I'm the left content.
    </span>
  </div>
  <div class="center">
  <span>I'm the center content. I'm longer than the others.</span>
  </div>
  <div class="right">
    <span>
      Right.
    </span>
  </div>
</div>
<div class="center-mark">^</div>
<div class="note">(centered marker/text)</div>