从”圣杯布局”到负边距
圣杯布局
『圣杯布局』的 HTML 结构很直观,实现的布局目标是两边栏定宽,中间栏自适应,它的优点在于兼容性强,毕竟是十来年前的奇思妙想😋
1 | <div id="content"> |
它的 CSS 样式如下:
1 | #content { |
简要概括一下的话,主要通过以下几个方面来实现:
- 父元素
content
下的所有子元素即middle
left
right
全部左浮动; middle
宽度设置为 100%,此时它独占一行,left
right
因为宽度固定,全部紧靠在第二行左边缘,上边缘紧贴middle
下边缘;- 这时给
left
一个margin-left: -100%
,会将left
拉出第二行,此时因为不受middle
上边缘限制,会直接移动到第一行最左边; - 同理给
right
一个margin-right: -200px
,会将right
拉到第一行的最右边;(可以理解为先到第一行后,再进行向左拉动) - 因为此时
middle
被覆盖,给父元素设置左右padding
,再让left
right
分别设置position: relative
,用left: -200px
right: -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
会将后方的元素往上拉动并覆盖自己;