29

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

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

因此,它的孩子(浅蓝色方块)如下所示排列。但是,我想在正常流程之外添加另一个孩子(绿色方块)并将其相对于其父级定位。要将其定位为如下所示,理想情况下,我会编写类似bottom: 20px;and的内容margin: auto;

在此处输入图像描述

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

4

3 回答 3

57

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

  1. CSS 定位
  2. 带有不可见 DOM 元素的 Flexbox
  3. 具有不可见伪元素的 Flexbox
  4. 弹性盒与flex: 1
  5. CSS 网格布局

方法 #1:CSS 定位属性

应用于position: relativeflex 容器。

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

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

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

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

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


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

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

新的弹性项目与底部项目相同,并放置在另一端(顶部)。

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

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

简而言之:

  • 创建绿色框的副本。
  • 将其放在列表的开头。
  • 使用弹性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>


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

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

  • 创建一个与现有绿色框高度相同的伪元素。
  • 将它放在容器的开头,并带有::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>


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

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

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


方法 #5:CSS 网格布局

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

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

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>

于 2016-03-24T01:11:17.547 回答
4

让容器与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>

于 2016-03-24T01:17:02.040 回答
3

您可以使用伪将前三个容器向下移动一行,然后将 amargin: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>

于 2016-03-24T01:22:16.527 回答