Html 居中和底部对齐 flex 项目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36191516/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 13:02:54  来源:igfitidea点击:

Center and bottom-align flex items

htmlcssflexboxcss-grid

提问by Willege

I have a flex container (the blue square) with the following properties:

我有一个具有以下属性的 flex 容器(蓝色方块):

display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;

Therefore, its children (the light blue squares) arrange themselves as you see below. However, I'd like to add another child (the green square) out of the normal flow and position it relative to its parent. To position it as you see below, I'd ideally write something like bottom: 20px;and margin: auto;.

因此,它的子元素(浅蓝色方块)如下所示。但是,我想从正常流中添加另一个子项(绿色方块)并将其相对于其父项定位。要将其定位为如下所示,我最好写一些类似bottom: 20px;and 的内容margin: auto;

enter image description here

在此处输入图片说明

I tried to play around with z-indexto no avail. How should I approach this? Should I resort to creating another parent element?

我试图玩弄z-index无济于事。我应该如何处理这个问题?我应该求助于创建另一个父元素吗?

回答by Michael Benjamin

Below are five options for achieving this layout:

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

  1. CSS Positioning
  2. Flexbox with Invisible DOM Element
  3. Flexbox with Invisible Pseudo-Element
  4. Flexbox with flex: 1
  5. CSS Grid Layout
  1. CSS 定位
  2. 带有隐形 DOM 元素的 Flexbox
  3. 带有隐形伪元素的 Flexbox
  4. 弹性盒与 flex: 1
  5. CSS 网格布局


Method #1: CSS Positioning Properties

方法 #1:CSS 定位属性

Apply position: relativeto the flex container.

应用于position: relative弹性容器。

Apply position: absoluteto the green flex item.

应用于position: absolute绿色弹性项目。

Now the green square is absolutely positioned within the flex container.

现在绿色方块绝对位于 flex 容器内。

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

更具体地说,绿色方块从文档流中移除,但保留在最近定位的祖先的边界内。

Use the CSS offset properties top, bottom, leftand rightto move the green square around.

使用CSS污损特性topbottomleftright移动的绿色广场周围。

flex-container {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  position: relative;
  border: 4px solid blue;
  height: 300px;
  width: 300px;
}
flex-container > flex-item:first-child {
  display: flex;
}
flex-container > flex-item:first-child > flex-item {
  border: 4px solid aqua;
  height: 50px;
  width: 50px;
  margin: 0 5px;
}
flex-container > flex-item:last-child {
  position: absolute;
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%); /* fine tune horizontal centering */
  border: 4px solid chartreuse;
  height: 50px;
  width: 50px;
}
<flex-container>
    <flex-item><!-- also flex container -->
     <flex-item></flex-item>
     <flex-item></flex-item>
     <flex-item></flex-item>
    </flex-item>
    <flex-item></flex-item>
</flex-container>

One caveat: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 normal flow in Firefox & IE11

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



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

方法#2:Flex Auto Margins & Invisible Flex Item(DOM 元素)

With a combination of automarginsand a new, invisible flex item the layout can be achieved.

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

The new flex item is identical to the bottom item and is placed at the opposite end (the top).

新的 flex item 与底部 item 相同,并放置在另一端(顶部)。

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

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

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

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

In short:

简而言之:

  • Create a duplicate of the green box.
  • Place it at the beginning of the list.
  • Use flex automargins to keep the blue boxes centered, with both green boxes creating equal balance from both ends.
  • Apply visibility: hiddento the duplicate green box.
  • 创建绿色框的副本。
  • 将其放在列表的开头。
  • 使用弹性auto边距使蓝色框居中,两个绿色框从两端创建相等的平衡。
  • 适用visibility: hidden于重复的绿色框。

flex-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    border: 4px solid blue;
    height: 300px;
    width: 300px;
}
flex-container > flex-item:first-child {
    margin-top: auto;
    visibility: hidden;
}
flex-container > flex-item:nth-child(2) {
    margin-top: auto;
    display: flex;
}
flex-container > flex-item:last-child {
    margin-top: auto;
    margin-bottom: auto;
}
flex-container > flex-item:first-child,
flex-container > flex-item:last-child {
    border: 4px solid chartreuse;
    height: 50px;
    width: 50px;
}
flex-container > flex-item:nth-child(2) > flex-item {
    border: 4px solid aqua;
    height: 50px;
    width: 50px;
    margin: 0 5px;
}
<flex-container>
    <flex-item></flex-item>
    <flex-item><!-- also flex container -->
     <flex-item></flex-item>
     <flex-item></flex-item>
     <flex-item></flex-item>
    </flex-item>
    <flex-item></flex-item>
</flex-container>



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

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

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

这种方法与#2 类似,但它在语义上更清晰,并且必须知道绿色框的高度。

  • Create a pseudo-element with the same height as the existing green box.
  • Place it at the start of the container with ::before.
  • Use flex automargins to keep the blue boxes centered, with the green pseudo and DOM elements creating equal balance from both ends.
  • 创建一个与现有绿色框高度相同的伪元素。
  • 用 将它放在容器的开头::before
  • 使用弹性auto边距保持蓝色框居中,绿色伪元素和 DOM 元素从两端创建相等的平衡。

flex-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    border: 4px solid blue;
    height: 300px;
    width: 300px;
}
flex-container::before {
  content: "";
  margin-top: auto;
  height: calc(50px + 8px);  /* height + borders */
  visibility: hidden;
}
flex-container > flex-item:first-child {
  margin-top: auto;
  display: flex;
}
flex-container > flex-item:last-child {
  margin-top: auto;
  margin-bottom: auto;
  border: 4px solid chartreuse;
  height: 50px;
  width: 50px;
}
flex-container > flex-item:first-child > flex-item {
  border: 4px solid aqua;
  height: 50px;
  width: 50px;
  margin: 0 5px;
}
<flex-container>
    <flex-item><!-- also flex container -->
        <flex-item></flex-item>
     <flex-item></flex-item>
     <flex-item></flex-item>
    </flex-item>
    <flex-item></flex-item>
</flex-container>



Method #4: Add flex: 1to top and bottom items

方法#4:添加flex: 1到顶部和底部项目

Starting with Method #2 or #3 above, instead of worrying about equal height for the top and bottom 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.

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

You can then add display: flexto the bottom item in order to align the content.

然后,您可以添加display: flex到底部项目以对齐内容。



Method #5: CSS Grid Layout

方法 #5:CSS 网格布局

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 three rows. Then center-align the items in the second and third rows. The first row can remain empty.

只需创建一个包含三行的网格。然后将第二行和第三行中的项目居中对齐。第一行可以保持为空。

grid-container {
  display: grid;
  grid-template-rows: repeat(3, 1fr);
  align-items: center;
  justify-items: center;
  border: 4px solid blue;
  height: 300px;
  width: 300px;
}

grid-item:nth-child(2) {
  display: flex;
}

grid-item:nth-child(2)>flex-item {
  width: 50px;
  height: 50px;
  margin: 0 5px;
  border: 4px solid aqua;
}

grid-item:nth-child(3) {
  border: 4px solid chartreuse;
  height: 50px;
  width: 50px;
}
<grid-container>
  <grid-item></grid-item>
  <grid-item><!-- also flex container -->
    <flex-item></flex-item>
    <flex-item></flex-item>
    <flex-item></flex-item>
  </grid-item>
  <grid-item></grid-item>
</grid-container>

回答by Le____

let the container with position: relativeand the green square with position:absolute;

让容器position: relative和绿色方块 position:absolute;

body {
  margin: 0;  
}

#container {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  width: 192px;
  height: 192px;
  border: 4px solid indigo;
  position: relative;
  background: lavender;
}

.blue {
  margin: 10px;
  width: 30px;
  height: 30px;
  outline: 4px solid skyblue;
  background: honeydew;
}

#green {
  position: absolute;
  width: 30px;
  height: 30px;
  left: 0;
  right: 0;
  margin: auto;
  bottom: 20px;
  outline: 4px solid yellowgreen;
  background: greenyellow;
}
<div id=container>
<div class=blue></div><div class=blue></div><div class=blue></div>
<div id=green></div>
</div>

回答by G-Cyrillus

you can use a pseudo to move down one row the first three containers then applie a margin:autoto last one

您可以使用伪指令将前三个容器向下移动一行,然后将 a 应用margin:auto到最后一个

div {
  display:flex;
  flex-wrap:wrap;
  border:#0066FD solid;;
  width:200px;
  height:200px;
  justify-content:space-around;
  /* show me box center */
  background:linear-gradient(to top,rgba(0,0,0,0.2) 50%, transparent 50%),linear-gradient(to left,rgba(0,0,0,0.2) 50%, transparent 50%)
 
}

span, div:before {
  width:50px;
  height:50px;
  border:solid #01CDFF;
  margin:0 auto 0;
}
span:last-of-type , div:before{
  margin: 12px auto;
  border:solid  #01FE43;
}
div:before {
  content:'';
  width:100%;
  border:none;
}

span {
   /* show me box center */
  background:linear-gradient(45deg,rgba(0,0,0,0.1) 50%, transparent 50%),linear-gradient(-45deg,rgba(0,0,0,0.1) 50%, transparent 50%)
  }
<div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>