从”圣杯布局”到负边距
圣杯布局
『圣杯布局』的 HTML 结构很直观,实现的布局目标是两边栏定宽,中间栏自适应,它的优点在于兼容性强,毕竟是十来年前的奇思妙想😋
1 | <div id="content"> |
它的 CSS 样式如下:
1 | #content { |
简要概括一下的话,主要通过以下几个方面来实现:
- 父元素
content下的所有子元素即middleleftright全部左浮动; middle宽度设置为 100%,此时它独占一行,leftright因为宽度固定,全部紧靠在第二行左边缘,上边缘紧贴middle下边缘;- 这时给
left一个margin-left: -100%,会将left拉出第二行,此时因为不受middle上边缘限制,会直接移动到第一行最左边; - 同理给
right一个margin-right: -200px,会将right拉到第一行的最右边;(可以理解为先到第一行后,再进行向左拉动) - 因为此时
middle被覆盖,给父元素设置左右padding,再让leftright分别设置position: relative,用left: -200pxright: -200px将它们拉出middle范围内;
标准流/通常流(Normal flow)
负边距(Negative margin)的工作特性,与 CSS 文档流有很大关系,在可视化模型中,一切元素都能表示为框/盒模型,而所有的框都处于流动状态;在标准流中,主要的流向是从右下 往 左上,即类似『↖』的方向;其中的框分为块级上下文与行内级上下文,也就是通常说的块级元素与行内元素;
对于块级上下文,它通常是占满一行的宽度,从上到下依次排列;即如果没有给它设置宽度,那它的宽度便为『填充』,而垂直方向则是占据内容的最大高度;
负边距

再来谈谈负边距的作用,对于 CSS 盒模型来说,一个未定义宽度的块级盒子的总宽度应该为margin + border + padding + width = 父元素的width,如果width未指定,会自动让其『填充』;如果指定了宽度,则会用水平的margin来补全,这也是通常说的『元素定宽加margin: 0 auto实现水平居中』的原理;然而这些都是margin为正时的情况;
当margin为负时,如果宽度指定,margin-right不会产生影响,margin-left会将元素往左拉动;如果宽度已未指定(auto),二者都会将元素宽度往对应方向增大;
这种现象的产生都是因为要满足之前提到的块级上下文宽度等式,一旦产生负值,那必定要产生一个正值来抵消,当宽度指定时,只能通过另一边的 margin来抵消(如果两边都指定了,margin-right会被无视); 当宽度未指定时,可以通过扩大宽度来抵消;
上图即为定宽元素产生自动产生的margin-right,以此来维持等式平衡
垂直方向的margin只会导致位置的移动,因为元素在垂直方向并不会有『填充』的特性;当然因为标准流是从下往上的,所以marin-top会将元素本身往上拉动覆盖上方元素,margin-bottom会将后方的元素往上拉动并覆盖自己;