水平居中元素,以避免重叠的容器 [英] Horizontally centering elements to their container while avoiding overlap

查看:149
本文介绍了水平居中元素,以避免重叠的容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这与连续三个元素,一个左,一个右,和中心,这可以用flexbox轻松解决 - 但它有一些警告,使得它(我认为)一个不可能的布局,没有JavaScript。





期望的目标

考虑一个像行的容器元素和三个孩子,左,右和中心。



Center应该尽量保持与其容器相对的位置 - 但是三个兄弟元素不能重叠,并且可能会在必要时将其推送到容器外面。



标记可能看起来像这:

 < div class =container> 
< div class =left>我是左边的内容。< / div>
< div class =center>我是中心内容。我比其他人长。< / div>
< div class =right> Right。< / div>
< / div>

CSS就是挑战所在。



< hr>

应该发生的例子

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



对于较窄的容器,中心邻接最宽的兄弟,但它不重叠。剩下的空间只分布在 兄弟姐妹和<中心>兄弟姐妹之间。请注意,由插入符号表示的容器中点不再是中心的中点:



最后,随着容器的不断缩小,除了三个元素排成一行,溢出父母:






我试图解决这个问题

令人惊讶的是,我还没有找到一个很好的方法来实现这个纯CSS。



你会认为flexbox是胜利者,但是你不能真正让flexbox做到这一点:属性之间的空间在元素之间均匀分配空间,所以中心元素实际上并不以居中为中心。 flex - grow / shrink / basis properties aren'因为它们负责控制子元素的大小,而不是控制它们之间的空间大小。



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



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



简而言之,我不知道纯粹的HTML和CSS解决方案。 / p>




结论和一个JSFiddle来试验

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


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


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

解决方案

使用 flexbox 你应该可以解决这个问题,通过给 left / right 元素 flex:1 和右边 text-align:right
$ b

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

欲了解更多版本,请参阅这个精彩的问题/答案, Flexbox的对齐项和对齐自性质



小提琴



堆栈片段

body {font: 14px Arial;}。container {display:flex; border:1px solid#00F;}。container> div> span {display:inline-block;背景:#36F;白色空间:nowrap; padding:2px 4px; color:#FFF;}。container> .center> span {background:#696;}。container .left,.container .right {flex:1;}。container .right {text-align:right;}。 font-size:80%;}。注意{text-align:center;颜色:#666; font-style:italic; font-size:90%;}

< div class = 容器 > < div class =left> <跨度>我是左边的内容。 < /跨度> < / DIV> < div class =center> < span>我是中心内容。我比其他人长。< / span> < / DIV> < div class =right> <跨度>对。 < /跨度> < / div>< / div>< div class =center-mark> ^< / div>< div class =note>(centered marker / text) / code>


I ran into an interesting CSS problem today, and I have been wracking my brain trying to solve it.

This is similar to the trivial problem of "a row of three elements, with a left, a right, and center," which can be solved easily with flexbox — but it has a couple of caveats that make it (I think) an impossible layout without JavaScript.


The desired goal

Consider a row-like container element and three children, "left", "right", and "center". The children may be of varying widths, but they are all the same height.

"Center" should try to stay centered relative to its container — but the three sibling elements must not overlap, and may push outside the container if necessary.

The markup, then, might look something like this:

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

The CSS is where the challenge is.


Examples of what should happen

For wide containers, "center" is centered relative to the container (i.e., its siblings' widths do not matter), as in the image below; notice that midpoint of the "center" element matches the midpoint of the container, and that the left and right "leftover" spaces are not equal:

For narrower containers, "center" abuts the widest sibling, but it does not overlap. The remaining space is distributed only between the narrow sibling and the "center" sibling. Notice also that the container's midpoint, indicated by the caret, is no longer the same as "center's" midpoint:

Finally, as the container continues to shrink, there's no other option but to have all three elements lined up in a row, overflowing the parent:


My attempts to solve this

Surprisingly, I haven't found a good way to implement this in pure CSS.

You'd think flexbox would be the winner, but you can't really get flexbox to do it right: The space-between property distributes the space uniformly between the elements, so the center element doesn't actually end up centered. The flex-grow/shrink/basis properties aren't especially useful for this either, since they're responsible for controlling the size of the child elements, not for controlling the size of the space between them.

Using position:absolute can solve it as long as the container is wide enough, but when the container shrinks, you end up with overlap.

(And float layouts can't get within a mile of getting this right.)

I could combine the best two solutions above, and switch between them with a @media query — if all of the widths were known in advance. But they aren't, and the sizes may vary widely.

In short, there's no pure-HTML-and-CSS solution to this problem that I know of.


Conclusion, and a JSFiddle to experiment with

I created a JSFiddle that shows both the desired goal and a few non-solutions. Feel free to fork it and experiment. You can simulate the container resizing by grabbing the bar to the left of the content and dragging it. You are allowed to rearrange/restructure the HTML and CSS, if rewriting it gets you closer to a working answer.

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

So does anyone have a solution to this that doesn't involve using JavaScript to intelligently distribute the space between the elements?

解决方案

With flexbox you should be able to solve that, by giving the left/right elements flex: 1 and the right text-align: right.

The main trick is flex: 1, which will make them share available space equally.

For more versions, see this brilliant question/answer, 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>

这篇关于水平居中元素,以避免重叠的容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆