两栏布局(bfc)demo
原理:BFC的区域不会与float box重叠。通过触发main生成BFC, 来实现自适应两栏布局。
但是会有个问题:为何给body设置border之后参见demo
补坑解释:
外边距折叠(margin collapse) 发生的场景是,同一个块级盒子布局上下文(BFC)中相邻的次方向外边距会折叠
box2
没有padding和border那么,box1 box2 box3
的margin就要折叠,但是如果box2
有padding或border,那么内部box3
的margin就被隔开了,就只有box1 box2
margin参与折叠
加上border之后
参见demo
这可能就是给body加border
会出现不合并的原因了吧。
但是一般来讲会给加一个 padding-top:1px 来解决。
其他方式的两栏布局
。。。。。
三栏 (负margin思想)
涉及浮动和清除浮动,主要“圣杯”和“双飞翼”两种解决方法。这两种方法实现的都是三栏布局,两边的盒子宽度固定,中间盒子自适应,也就是常说的固比固布局。它们实现的效果是一样的,差别在于其实现的思想。
- 圣杯布局 demo
第一步:给出页面结构以及各个盒子的具体样式
<header>header内容区域</header>
<div class="container">
<div class="middle">我是中间弹性布局</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
<footer>footer内容区</footer>
body{ min-width:700px;}//当你缩放页面的时候,宽度不能小于700PX,为了安全起见,最好还是给body加一个最小宽度!
header{width: 100%;height: 40px;background-color: darkseagreen;}
.container{overflow:hidden;}
.middle{width: 100%;height: 200px; background-color: deeppink;float:left;}
.left{width: 200px;height: 200px;background-color: blue;float:left;}
.right{width: 200px;height: 200px;background-color: green;float:left;}
footer{width: 100%; height: 30px;background-color: darkslategray;}
可以看到左右两栏并没有在父元素的一行显示,因为中间盒子我们给了百分之百的宽度。所有左右两个盒子才会被挤下来。
如果中间盒子不是100%的宽度,那么按照文档流,左边的盒子一定会在中间盒子的后面显示,接着显示右边的盒子。但是现在中间盒子是满屏了的,所以左右两个盒子被挤到下一行显示。我们要做到的是让左右两个盒子都上去。此时,CSS的负边距(negative margin)该上阵了。
第二步:利用负margin布局
.left {margin-left:-100%;}
为负的中间盒子的宽度,左盒子往最左边移动。
.right {margin-left:-200px;}
为负的自己的宽度,右盒子才可以在一行的最右边显示出自己。
但是如果给中间盒子加很多内容,就会被左右盒子挡住。如图:
第三步:让中间自适应的盒子安全显示
-
首先:利用父级元素设置左右内边距的值,把父级的三个子盒子往中间挤。
.container{ padding: 0 200px;}
这里的200px是左右盒子的宽度。
-
其次:给左右两个盒子加一个定位,加了定位之后左右两个盒子就可以设置left和right值。
.left{ position: relative; left: -200px;}
.right{position: relative;right: -210px;}
双飞翼布局Demo
第一步:给出页面结构以及各个盒子的具体样式
<header>header内容区域</header>
<div class="container">
<div class="middle">
<div class="middle-inner">我是中间弹性布局</div></div>
<div class="left">left</div>
<div class="right">right</div>
</div>
</div>
<footer>footer内容区</footer>
header{width: 100%;height: 40px;background-color: darkseagreen;}
.container{overflow:hidden;}
.middle{width: 100%;height: 200px; background-color: deeppink;float:left;}
.left{width: 200px;height: 200px;background-color: blue;float:left;}
.right{width: 200px;height: 200px;background-color: green;float:left;}
footer{width: 100%; height: 30px;background-color: darkslategray;}
第二步:跟圣杯布局一样,利用负margin布局
但是仍然被挡住,如何让中间一栏自适应呢?
第三步:中间盒子里面再添加一个 div
.middle-inner{margin:0 200px;}
这个 div 设置 margin-left 和 margin-right来为左右盒子留位置;
圣杯和双飞翼异同:
两边定宽,中间自适应的三栏布局的解决方式,中间栏要在放在文档流前面以优先渲染。
- 两种方法基本思路都相同:三栏全部 float 浮动。首先让中间盒子 100% 宽度占满同一高度的空间,在左右两个盒子被挤出中间盒子所在区域时,使用 margin-left 的负值将左右两个盒子拉回与中间盒子同一高度的空间。接下来进行一些调整避免中间盒子的内容被左右盒子遮挡。
- 主要区别在于 如何使中间盒子的内容不被左右盒子遮挡:
- 圣杯布局的方法:设置父盒子的 padding 值为左右盒子留出空位,再利用相对布局对左右盒子调整位置占据 padding 出来的空位;
- 双飞翼布局的方法:在中间盒子里再增加一个子盒子,直接设置这个子盒子的 margin 值来让出空位,而不用再调整左右盒子。
简单来说:双飞翼布局比圣杯布局多创建了一个 div,但不用相对布局了,少设置几个属性。
总结有几点:
不使用 float 的话,负 margin 元素是不会破坏页面的文档流。所以如果你使用负 margin 上移一个元素,所有跟随的元素都会被上移(而 relative 定位的元素则不同,会保留原位置,影响文档流) 。
当 static 元素的 margin-top/margin-left 被赋予负值时,元素将被拉进指定的方向。
如果你设置 margin-bottom/right 为负数,元素并不会如你所想的那样向下/右移动,而是将后续的元素拖拉进来,覆盖本来的元素。
-
当元素不存在 width 属性或者 width: auto 的时候,负 margin 会增加元素的宽度. Link
margin-top 为负值不会增加高度,只会产生向上位移;margin-bottom 为负值不会产生位移,会减少自身的供 CSS 读取的高度,影响下方的元素位置;上下相邻的元素两者均为负时,效果不叠加,取负值更多的那个效果。(也即外边距合并)
本文参考链接CSS 布局经典问题初步整理