css - 将元素水平居中到其容器,同时避免重叠

标签 css layout flexbox

我今天遇到了一个有趣的 CSS 问题,我绞尽脑汁试图解决它。

这类似于“一行三个元素,一个左,一个右,中心”的小问题,可以使用 Flexbox 轻松解决 - 但它有一些注意事项(我认为)如果没有 JavaScript,这是不可能的布局。


期望的目标

考虑一个行状容器元素和三个子元素:“left”、“right”和“center”。子级的宽度可能不同,但高度相同。

“Center”应尝试相对于其容器保持居中,但三个同级元素不得重叠,并且在必要时可能会推到容器之外。 p>

标记可能看起来像这样:

<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”相对于容器居中(即,其兄弟容器的宽度并不重要),如下图所示;请注意,“center”元素的中点与容器的中点相匹配,并且左右“剩余”空间不相等:

Wide

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

Narrower

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

Narrowest


我尝试解决这个问题

令人惊讶的是,我还没有找到在纯 CSS 中实现此功能的好方法。

您可能认为 Flexbox 会是赢家,但您实际上无法让 Flexbox 正确执行此操作:space- Between 属性在元素之间均匀分配空间,因此中心元素实际上并没有居中。 flex-grow/shr​​ink/basis 属性对此也不是特别有用,因为它们负责控制子元素,不用于控制它们之间的空间大小。

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

( float 布局无法做到这一点。)

我可以结合上面最好的两个解决方案,并使用 @media 查询在它们之间切换 - 如果所有宽度都提前知道的话。但事实并非如此,而且尺寸可能相差很大。

简而言之,据我所知,没有纯 HTML 和 CSS 解决方案可以解决这个问题。


结论,以及用于实验的 JSFiddle

我创建了一个 JSFiddle,它显示了期望的目标和一些非解决方案。请随意 fork 并进行实验。您可以通过捕获内容左侧的栏并拖动它来模拟容器大小的调整。如果重写可以让您更接近可行的答案,您可以重新排列/重组 HTML 和 CSS。

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

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

最佳答案

使用 flexbox 你应该能够通过给 left/right 元素 flex: 1 来解决这个问题> 和右侧的 text-align: right

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

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

Fiddle 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>

关于css - 将元素水平居中到其容器,同时避免重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42448379/

相关文章:

c# - CSS 显示模板类名中的额外空间

css - 寻呼机决定从水平切换到垂直

Android WebView 下面有一排按钮

css - 当 Flex 中的 flex 方向为 row-reverse 时,将元素向左对齐

javascript - CSS 样式与 Javascript 不同步

javascript - 如何让浏览器看到 CSS 和 Javascript 的变化?

html - twitter bootstrap 2列固定布局损坏

android - ViewFlipper.setDisplayedChild() 在 Android 中不起作用

html - Flexbox 列和行

html - 强制将 img 放入作为 flex 元素的 div