居中一个和右/左对齐其他 flexbox 元素 [英] Center one and right/left align other flexbox element

查看:26
本文介绍了居中一个和右/左对齐其他 flexbox 元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让 A BC 在中间对齐.

我怎样才能让 D 完全向右移动?

之前:

之后:

ul {填充:0;边距:0;显示:弹性;弹性方向:行;对齐内容:居中;对齐项目:居中;}李{显示:弹性;边距:1px;填充:5px;背景:#aaa;}李:最后一个孩子{背景:#ddd;/* 向右扔的魔法*/}

    <li>A</li><li>B</li><li>C</li><li>D</li>

https://jsfiddle.net/z44p7bsx/

解决方案

以下是实现此布局的五个选项:

  • CSS 定位
  • 带有隐形 DOM 元素的 Flexbox
  • 带有隐形伪元素的 Flexbox
  • 带有 flex: 1
  • 的 Flexbox
  • CSS 网格布局
<小时>

方法 #1:CSS 定位属性

position:relative 应用到 f​​lex 容器.

position: absolute 应用到项目 D.

现在这个项目绝对定位在 flex 容器中.

更具体地说,项目 D 已从文档流中删除,但仍保留在 最近定位的祖先.

使用 CSS 偏移属性 topright 将此元素移动到位.

li:last-child {位置:绝对;顶部:0;右:0;背景:#ddd;}ul{位置:相对;填充:0;边距:0;显示:弹性;弹性方向:行;对齐内容:居中;对齐项目:居中;}李{显示:弹性;边距:1px;填充:5px;背景:#aaa;}p{文本对齐:居中;边距顶部:0;}跨度 {背景颜色:浅绿色;}

    <li>A</li><li>B</li><li>C</li><li>D</li>
<p><span>真中心</span></p>

这个方法的一个警告是一些浏览器可能不会从正常流程中完全删除绝对定位的弹性项目.这以一种非标准的、意想不到的方式改变了对齐方式.更多详情:绝对定位的弹性项目不会从 IE11 中的正常流程中移除

<小时>

方法#2:Flex Auto Margins &不可见的 Flex Item(DOM 元素)

结合auto边距和新的,可以实现不可见的flex item布局.

新的 flex item 与 item D 相同,并放置在另一端(左边缘).

更具体地说,因为 flex 对齐是基于自由空间的分布,新项目是保持三个中间框水平居中的必要平衡.新项目必须与现有 D 项目的宽度相同,否则中间的框将不会精确居中.

新项目从视图中移除,visibility: hidden.

简而言之:

  • 创建 D 元素的副本.
  • 将其放在列表的开头.
  • 使用 flex auto 边距保持 ABC 居中,同时 D 元素从两端创造平等的平衡.
  • visibility: hidden 应用到重复的 D

li:first-child {右边距:自动;可见性:隐藏;}李:最后一个孩子{左边距:自动;背景:#ddd;}ul{填充:0;边距:0;显示:弹性;弹性方向:行;对齐内容:居中;对齐项目:居中;}李{显示:弹性;边距:1px;填充:5px;背景:#aaa;}p { 文本对齐:居中;边距顶部:0;}跨度{背景颜色:浅绿色;}

    <li>D</li><!-- 新的;隐形间隔项目 --><li>A</li><li>B</li><li>C</li><li>D</li>
<p><span>真中心</span></p>

<小时>

方法#3:Flex Auto Margins &不可见的 Flex 项目(伪元素)

这个方法类似于#2,只是语义更清晰,而且D的宽度必须是已知的.

  • 创建一个与 D 宽度相同的伪元素.
  • ::before 把它放在容器的开头.
  • 使用 flex auto 边距来保持 ABC 完美居中,伪和 D 元素从两端创造平等的平衡.

ul::before {内容:D";边距:1px 自动 1px 1px;可见性:隐藏;填充:5px;背景:#ddd;}李:最后一个孩子{左边距:自动;背景:#ddd;}ul{填充:0;边距:0;显示:弹性;弹性方向:行;对齐内容:居中;对齐项目:居中;}李{显示:弹性;边距:1px;填充:5px;背景:#aaa;}p { 文本对齐:居中;边距顶部:0;}跨度{背景颜色:浅绿色;}

    <li>A</li><li>B</li><li>C</li><li>D</li>
<p><span>真中心</span></p>

<小时>

方法 #4:将 flex: 1 添加到左右项目

从上面的方法#2 或#3 开始,不要担心左右项目的宽度相等以保持平衡,只需给每个项目一个flex: 1.这将迫使它们都消耗可用空间,从而使中间项居中.

然后您可以将 display: flex 添加到单个项目以对齐它们的内容.

注意 关于将这种方法与 min-height 一起使用: 目前在 Chrome、Firefox、Edge 和可能其他浏览器,速记规则 flex: 1 分解为:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%

flex-basis 上的 百分比单位 (%) 会在容器上使用 min-height 时导致此方法中断.这是因为,作为一般规则,子级的百分比高度需要在父级上进行显式的 height 属性设置.

这是一条可追溯到 1998 年的旧 CSS 规则(CSS Level 2) 这在某种程度上仍然在许多浏览器中有效.有关完整的详细信息,请参阅此处此处.

以下是 user2651804 在评论中发布的问题的说明:

#flex-container {显示:弹性;弹性方向:列;背景:青色;宽度:150px;最小高度:80vh;对齐内容:间隔;}#flex-container>div {背景:橙色;边距:5px;}#flex-container>div:first-child {弹性:1;}#flex-container::after {内容: "";弹性:1;}

<div>很长的烦人的文本,将添加到其父级的高度之上</div><div>中心</div>

解决方案是不使用百分比单位.尝试 px 或什么都不做(其中这是规范实际推荐的内容,尽管事实上至少有一些主要浏览器出于某种原因附加了百分比单位).

#flex-container {显示:弹性;弹性方向:列;背景:青色;宽度:150px;最小高度:80vh;对齐内容:间隔;}#flex-container >div {背景:橙色;边距:5px;}/* 覆盖 FLEX 属性中的浏览器设置 */#flex-container >div:第一个孩子{弹性:1;弹性基础:0;}#flex-container::after {内容: "";弹性:1;弹性基础:0;}/* 或... 单独设置长手属性#flex-container >div:第一个孩子{弹性增长:1;弹性收缩:1;弹性基础:0;}#flex-container::after {内容: "";弹性增长:1;弹性收缩:1;弹性基础:0;}*/

<div>很长的烦人的文本,将添加到其父级的高度之上</div><div>中心</div>

<小时>

方法 #5:CSS 网格布局

这可能是最干净、最有效的方法.不需要绝对定位,不需要虚假元素或其他黑客.

只需创建一个具有多列的网格.然后将您的项目放在中间列和结束列中.基本上,只需将第一列留空.

ul {显示:网格;网格模板列:1fr 重复(3,自动)1fr;网格列间距:5px;justify-items:居中;}li:nth-child(1) { grid-column-start: 2;}li:nth-child(4) { margin-left: auto;}/* 仅用于演示 */ul { 填充:0;边距:0;列表样式:无;}li { 填充:5px;背景:#aaa;}p { 文本对齐:居中;}

    <li>A</li><li>B</li><li>C</li><li>D</li>
<p><span>|真正的中心|</span></p>

I would like to have A B and C aligned in the middle.

How can I get D to go completely to the right?

BEFORE:

AFTER:

ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
li:last-child {
  background: #ddd;
  /* magic to throw to the right*/
}

<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>

https://jsfiddle.net/z44p7bsx/

解决方案

Below are five options for achieving this layout:

  • CSS Positioning
  • Flexbox with Invisible DOM Element
  • Flexbox with Invisible Pseudo-Element
  • Flexbox with flex: 1
  • CSS Grid Layout

Method #1: CSS Positioning Properties

Apply position: relative to the flex container.

Apply position: absolute to item D.

Now this item is absolutely positioned within the flex container.

More specifically, item D is removed from the document flow but stays within the bounds of the nearest positioned ancestor.

Use the CSS offset properties top and right to move this element into position.

li:last-child {
  position: absolute;
  top: 0;
  right: 0;
  background: #ddd;
}
ul {
  position: relative;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p {
  text-align: center;
  margin-top: 0;
}
span {
  background-color: aqua;
}

<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>

One caveat to this method is that some browsers may not completely remove an absolutely-positioned flex item from the normal flow. This changes the alignment in a non-standard, unexpected way. More details: Absolutely positioned flex item is not removed from the normal flow in IE11


Method #2: Flex Auto Margins & Invisible Flex Item (DOM element)

With a combination of auto margins and a new, invisible flex item the layout can be achieved.

The new flex item is identical to item D and is placed at the opposite end (the left edge).

More specifically, because flex alignment is based on the distribution of free space, the new item is a necessary counterbalance to keep the three middle boxes horizontally centered. The new item must be the same width as the existing D item, or the middle boxes won't be precisely centered.

The new item is removed from view with visibility: hidden.

In short:

  • Create a duplicate of the D element.
  • Place it at the beginning of the list.
  • Use flex auto margins to keep A, B and C centered, with both D elements creating equal balance from both ends.
  • Apply visibility: hidden to the duplicate D

li:first-child {
  margin-right: auto;
  visibility: hidden;
}
li:last-child {
  margin-left: auto;
  background: #ddd;
}
ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }

<ul>
  <li>D</li><!-- new; invisible spacer item -->
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>


Method #3: Flex Auto Margins & Invisible Flex Item (pseudo-element)

This method is similar to #2, except it's cleaner semantically and the width of D must be known.

  • Create a pseudo-element with the same width as D.
  • Place it at the start of the container with ::before.
  • Use flex auto margins to keep A, B and C perfectly centered, with the pseudo and D elements creating equal balance from both ends.

ul::before {
  content:"D";
  margin: 1px auto 1px 1px;
  visibility: hidden;
  padding: 5px;
  background: #ddd;
}
li:last-child {
  margin-left: auto;
  background: #ddd;
}
ul {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
li {
  display: flex;
  margin: 1px;
  padding: 5px;
  background: #aaa;
}
p { text-align: center; margin-top: 0; }
span { background-color: aqua; }

<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>true center</span></p>


Method #4: Add flex: 1 to left and right items

Starting with Method #2 or #3 above, instead of worrying about equal width for the left and right items to maintain equal balance, just give each one flex: 1. This will force them both to consume available space, thus centering the middle item.

You can then add display: flex to individual items in order to align their content.

NOTE about using this method with min-height: Currently in Chrome, Firefox, Edge and possibly other browsers, the shorthand rule flex: 1 breaks down to this:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0%

That percentage unit (%) on flex-basis causes this method to break when min-height is used on the container. This is because, as a general rule, percentage heights on the children require an explicit height property setting on the parent.

This is an old CSS rule dating back to 1998 (CSS Level 2) which is still in effect in many browsers to some degree or another. For complete details see here and here.

Here's an illustration of the problem posted in the comments by user2651804:

#flex-container {
  display: flex;
  flex-direction: column;
  background: teal;
  width: 150px;
  min-height: 80vh;
  justify-content: space-between;
}

#flex-container>div {
  background: orange;
  margin: 5px;
}

#flex-container>div:first-child {
  flex: 1;
}

#flex-container::after {
  content: "";
  flex: 1;
}

<div id="flex-container">
  <div>very long annoying text that will add on top of the height of its parent</div>
  <div>center</div>
</div>

The solution is to not use the percentage unit. Try px or just nothing at all (which is what the spec actually recommends, despite the fact that at least some of the major browsers have appended a percentage unit for whatever reason).

#flex-container {
  display: flex;
  flex-direction: column;
  background: teal;
  width: 150px;
  min-height: 80vh;
  justify-content: space-between;
}

#flex-container > div {
  background: orange;
  margin: 5px;
}


/* OVERRIDE THE BROWSER SETTING IN THE FLEX PROPERTY */

#flex-container > div:first-child {
  flex: 1;
  flex-basis: 0;
}

#flex-container::after {
  content: "";
  flex: 1;
  flex-basis: 0;
}


/* OR... JUST SET THE LONG-HAND PROPERTIES INDIVIDUALLY

#flex-container > div:first-child {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}

#flex-container::after {
  content: "";
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
}
 */

<div id="flex-container">
  <div>very long annoying text that will add on top of the height of its parent</div>
  <div>center</div>
</div>


Method #5: CSS Grid Layout

This may be the cleanest and most efficient method. There is no need for absolute positioning, fake elements or other hackery.

Simply create a grid with multiple columns. Then position your items in the middle and end columns. Basically, just leave the first column empty.

ul {
  display: grid;
  grid-template-columns: 1fr repeat(3, auto) 1fr;
  grid-column-gap: 5px;
  justify-items: center;
}

li:nth-child(1) { grid-column-start: 2; }
li:nth-child(4) { margin-left: auto; }

/* for demo only */
ul { padding: 0; margin: 0; list-style: none; }
li { padding: 5px; background: #aaa; }
p  { text-align: center; }

<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
  <li>D</li>
</ul>
<p><span>| true center |</span></p>

这篇关于居中一个和右/左对齐其他 flexbox 元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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