最近在使用Flex
布局时,遇到的一个情况:
有以下的代码:
<div class="toolbox">
<button id="decrease">-</button>
<span id="size">1</span>
<button id="increase">+</button>
<!-- 取色器 -->
<input type="color" id="color" />
<button id="clear">X</button>
</div>
我们给父容器设置Flex
布局,简单设置一下内部子元素的宽度和高度
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.toolbox {
display: flex;
border: 1px solid lightcoral;
width: 500px;
}
.toolbox > * {
height: 50px;
width: 50px;
}
效果如下:
很简单的例子,但是如果我给最后一个子元素设置设置一下css
代码 :
.toolbox > *:last-child {
margin-left: auto;
}
效果变成了以下:
最后一个元素变成了右对齐,自动把剩余的空间全部变成了他的左外边距margin-left
:
为什么会产生这种情况呢?
关于这个问题,我直接问了GPT3.5,它提到了一个叫做 自动外边距(Auto Margins),但是我并没有搜索到相关的资料,所以只能参考了GPT的回答,其中给出了W3C的候选规范:Aligning with auto margins
This section is non-normative. The normative definition of how margins affect flex items is in the Flex Layout Algorithm section.
Auto margins on flex items have an effect very similar to auto margins in block flow:
- During calculations of flex bases and flexible lengths, auto margins
are treated as 0. - Prior to alignment via justify-content and align-self, any positive
free space is distributed to auto margins in that dimension. - Overflowing boxes ignore their auto margins and overflow in the end
direction.
Note: If free space is distributed to auto margins, the alignment properties will have no effect in that dimension because the margins will have stolen all the free space left over after flexing.
nav > ul {
display: flex;
}
nav > ul > #login {
margin-left: auto;
}
<nav>
<ul>
<li><a href=/about>About</a>
<li><a href=/projects>Projects</a>
<li><a href=/interact>Interact</a>
<li id="login"><a href=/login>Login</a>
</ul>
</nav>
理解不太容易理解,只能说这就是规范,直接记住结论,关键点如下:
本例中的margin-left: auto;
的效果是该方向的外边距尽可能大,直到填充主轴
上的所有可用空间为止,在设置 margin-left: auto
的情况下,浏览器会为该元素的左侧自动分配剩余空间,结果是该元素会被推到容器的右侧。
然后副作用是:如果自动外边距
吸收了所有可用空间,那么像 justify-content
这样的对齐属性在该维度上将不再有效
,因为没有剩余空间来进行对齐。
所以,如果我们设置了父容器的justify-content: center;
同时内部的子元素设置了 margin-left: auto
,此时justify-content: center;
不生效:
.toolbox {
display: flex;
/* justify-content: space-between; */
justify-content: center;
border: 1px solid lightcoral;
width: 500px;
}
.toolbox > * {
height: 50px;
width: 50px;
}
.toolbox > *:nth-child(5) {
margin-left: auto;
}
效果如下,justify-content: center;
不生效
根据这个效果,我们就可以在一些场景下应用这个,比如类似的导航栏效果:
实现类似效果还有其他方法,比如弹性盒子的嵌套,或者用定位,但是这种方式代码简单,同时也具备响应式。
另外如果我们修改代码为:
.toolbox > *:nth-child(4) {
margin-left: auto;
}
第4个元素以及后面的兄弟元素会一起被左侧边距挤到右侧