MaureenChen 2019-12-01
最近看到几篇博文讲解margin:auto在flex容器中的使用,可惜的是大多讲解都浮于页面表现,没深究其中的作用机理,本文在此浅薄对其表现机理做简单探讨.
日常业务迭代过程中,flex已经是前端工程师解决常见布局的神兵利器.但是随着使用的深入,偶然会发觉flex对于简单的布局足够直接迅速,但是对于稍稍复杂一些的布局,就需要层层的包裹分组来解决.举个栗子,下图是我们常见的布局图:
![[CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组? [CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组?](https://cdn.ancii.com/article/image/v1/lS/gl/1x/x1gSllHxWhPghwUXA8tx6_-JJHXyozjniDTxKM5HCAgIBmFBVc1fpOfIXQvgPzqtnctYpGHVwyYJ1M_Bzros6lEjpr5-hzFZV4ZUylabdtKxseFVWtLsKy7We64MlInzdDTeDqtBQ1gO4U4SECx3lmFyUmT0I17UHIo17ckpA-INRqHw_7gVO8aeMx9jXoe9.jpg)
如果flex容器之中仅仅只有三个元素,彼此分离,我们借助于justify-content就足够应付.但是如果其中两个元素需要当成一组来处理,比如图一中的BC,使用flex布局,就不能保证布局结构足够简单,就需要把AB用一个div之类的标签包括起来当成一个元素,并且BC需要在新的包裹容器中居中,才可以实现上图布局.代码如下:
<div class="flex-container">
<div class="A">A</div>
<div class="BC">
<div class="B">B</div>
<div class="C">C</div>
</div>
<div class="D">D</div>
</div>.flex-container {
display: flex;
justify-content: space-between;
}
.A {
background: #FFE6CC;
width: 100px;
}
.BC {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
}
.B {
background: #FFF2CC;
width: 100px;
}
.C {
background: #F8CECC;
width: 100px;
}
.D {
background: #E1D5E7;
width: 100px;
}那么有没有比上面更简单的布局方式么?有,那就是使用margin:auto.
如果使用margin:auto的话,那么怎么更加简单实现上图的布局.
下面是布局代码.
<div class="flex-container"> <div class="A">A</div> <div class="B">B</div> <div class="C">C</div> <div class="D">D</div> </div>
.flex-container {
display: flex;
justify-content: space-between;
}
.A {
background: #FFE6CC;
width: 100px;
}
.B {
background: #FFF2CC;
width: 100px;
margin-left: auto;
}
.C {
background: #F8CECC;
width: 100px;
margin-right: auto;
}
.D {
background: #E1D5E7;
width: 100px;
}相对与引子中的代码来说,图中标红的是改动的地方.
主要是下面三个改动:
去掉外层flex中的justify-content属性.[margin:auto优先级比justify-content高,会使此属性失效,所以删除]
简化html结构.原来需要三层结构,简化后只需要两层.
B的margin-left和C的margin-right设置为auto.
最好的原理说明在css的规范中.我们首先查阅规范中对于flex容器margin:auto的说明[资源来源可参阅文末的参考资料].
![[CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组? [CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组?](https://cdn.ancii.com/article/image/v1/lS/gl/1x/x1gSllHxWhPghwUXA8tx6_-JJHXyozjniDTxKM5HCAgIBmFBVc1fpOfIXQvgPzqtnctYpGHVwyYJ1M_Bzros6m-unmOHQyqKKdFSZk3ea5sR8Slf-lIHu6nCw0ar8gUpdI7GFHxDjebZMn75IMa1dTjhimlr5l-zgXwo70IgjqRHlz1HnVr-3XtVPR_1Hs6q.jpg)
规范中明确说明了两个重要的点,:
margin:auto优先级比 justify-content,align-self优先级高
如果正常分配空间之后,仍然有未分配的空间,剩下的空间将分配给margin:auto的元素.
但是此规范没有说明,如果有多个margin:auto的元素,空间将如何分配?对此,mdn文档有说明[资源来源可参阅文末的参考资料]:
![[CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组? [CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组?](https://cdn.ancii.com/article/image/v1/lS/gl/1x/x1gSllHxWhPghwUXA8tx6_-JJHXyozjniDTxKM5HCAgIBmFBVc1fpOfIXQvgPzqtnctYpGHVwyYJ1M_Bzros6rZVaEOwJnyPZLFqcjLvBsAfKfhNecZ1Sun1EJRMuKDW2sbJMWMBjhwCbZTEGG1TVsA5WiY_8NnacKW4HP5I32wYfCZOTcvIe6-WCXir9ZNg.jpg)
mdn明确告知,空间将会平均分配给margin:auto的元素.
总结来看,就是可以使用margin:auto在flex容器主轴方向给子元素的左右两侧分配空间.
到此有看官可能有疑问了,如果flex容器,一个子元素margin-left,margin-right都设置为auto,另外一个子元素仅仅只设置了margin-left,那么空间该如何分配.实测证明,在主轴方向上,有几个外边距(指margin-left,margin-right)设置为auto,那么就分几份.
.flex-container {
display: flex;
}
.A {
background: #FFE6CC;
width: 100px;
}
.B {
background: #FFF2CC;
width: 100px;
margin-left: auto;
margin-right: auto;
}
.C {
background: #F8CECC;
width: 100px;
margin-left: auto;
}
.D {
background: #E1D5E7;
width: 100px;
}上述代码显示效果如下:
![[CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组? [CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组?](https://cdn.ancii.com/article/image/v1/lS/gl/1x/x1gSllHxWhPghwUXA8tx6_-JJHXyozjniDTxKM5HCAgIBmFBVc1fpOfIXQvgPzqtnctYpGHVwyYJ1M_Bzros6ihkvJhvwV1PeCygT5AN45cQ2ftLmQIcW-YusVKaq2t41n36dwtZoiIXiMpiOVsk5itddgBGJHL4OTVWqHVDkYe3U4kn6yWMdEAA5TZcsSqB.jpg)
B因为左右两个外边距都是auto,所以会各占一份,C因为只有左边距是auto,因此只占用一份.
上面的举例主轴都是水平方向.那么主轴是竖直方向的是否也适用呢?这里可以肯定回答: 列容器margin:auto仍然有效.不过需要把margin-left,margin-right改成设置 margin-top,margin-bottom为auto.
.flex-container {
display: flex;
flex-direction: column;
height: 500px;
}
.A {
background: #FFE6CC;
width: 100px;
}
.B {
background: #FFF2CC;
width: 100px;
margin-top: auto;
}
.C {
background: #F8CECC;
width: 100px;
margin-bottom: auto;
}
.D {
background: #E1D5E7;
width: 100px;
}<span><span> </span></span>上述代码显示效果如下:
![[CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组? [CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组?](https://cdn.ancii.com/article/image/v1/lS/gl/1x/x1gSllHxWhPghwUXA8tx6_-JJHXyozjniDTxKM5HCAgIBmFBVc1fpOfIXQvgPzqtnctYpGHVwyYJ1M_Bzros6oZx8USv0bQH1eH25NwzvA0geQYNJ1q0LFBxm8nqZphyyLOqfiNN9pCghXyBsLApQKRrRYaKkJLSrlblMCiq3zUNRqHw_7gVO8aeMx9jXoe9.jpg)
从示例中可以看出,margin:auto有空间占有效应. 使用margin:auto在某些情况下可以替代 flex:1, justify-content: space-between等的使用.这里不再展开阐释.
margin:auto适合用来给flex容器的子元素间(在主轴方向)增加空间,适当的使用margin:auto可以简化dom的布局结构以及样式代码,提高编程效率.
[1] w3c css-flexbox规范: https://www.w3.org/TR/css-flexbox-1/#auto-margins
[2] mdn关于margin:auto对flex容器的影响说明: https://developer.mozilla.org/zh-CN/docs/Web/CSS/margin-left
![[CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组? [CSS七分钟系列]都1902年了,还不知道用margin:auto给flex容器内元素分组?](https://cdn.ancii.com/article/image/v1/lS/gl/1x/x1gSllHxWhPghwUXA8tx65JZjl_ksehGxMnNDLZU678IBmFBVc1fpOfIXQvgPzqtnctYpGHVwyYJ1M_Bzros6vvn9tbvkEW_8Uo5bmhHW4qSlk5GETMq4UjxFxMw2XimlyHRJhQsb7nZIfIK5_m9FLhdm_U7guxb6X7AcUolJK6NJchP5Q9pjC9oUrOw3vWe.jpg)
微信搜索 ‘‘十八将君‘‘,关注我的公众号和我一起成长~