居中并右/左对齐其他 flexbox 元素

新手上路,请多包涵

我想让 A BC 在中间对齐。

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

前:

在此处输入图像描述

后:

在此处输入图像描述

 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/

原文由 hazyred 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 395
2 个回答

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

  • CSS 定位
  • 带有不可见 DOM 元素的 Flexbox
  • 具有不可见伪元素的 Flexbox
  • 带有 flex: 1 的弹性盒
  • CSS 网格布局

方法 #1:CSS 定位属性

应用 position: relative 到弹性容器。

position: absolute 应用于 D 项。

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

更具体地说,项目 D 已从文档流中删除,但仍位于 最近定位的祖先 的范围内。

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

 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>

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


方法 #2:Flex 自动边距和不可见的 Flex 项目(DOM 元素)

结合 auto 边距 和一个新的、不可见的弹性项目,可以实现布局。

新的弹性项目与项目 D 相同,并放置在另一端(左边缘)。

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

使用 visibility: hidden 从视图中删除新项目。

简而言之:

  • 创建 D 元素的副本。
  • 将其放在列表的开头。
  • Use flex auto margins to keep A , B and C centered, with both D elements creating equal balance从两端。
  • 应用 visibility: hidden 到副本 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>

方法#3:Flex Auto Margins & Invisible Flex Item(伪元素)

这种方法类似于#2,除了它在语义上更清晰,而且必须知道 D 的宽度。

  • 创建一个与 D 宽度相同的伪元素。
  • 将其放在容器的开头 ::before
  • Use flex auto margins to keep A , B and C perfectly centered, with the pseudo and D elements从两端创造平等的平衡。
 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>

方法#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%

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

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

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

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

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

方法 #5:CSS 网格布局

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

只需创建一个包含多列的网格。然后将您的项目放置在中间列和末尾列。基本上,只需将第一列留空。

 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>

原文由 Michael Benjamin 发布,翻译遵循 CC BY-SA 3.0 许可协议

最简单的解决方案是将 justify-content center 分配给父容器,并将 margin-left auto 分配给第一个和最后一个子元素。

 ul {
  display:flex;
  justify-content:center;
}

.a,.d {
  margin-left:auto;
}
 <ul>
  <li class="a">A</li>
  <li>B</li>
  <li>C</li>
  <li class="d">D</li>
</ul>

原文由 Suhail Akhtar 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题