圣杯布局及原理详解之浮动,负margin,百分比

    之前看网上的双飞翼和圣杯布局讲解,很多博文都是大概讲了讲原理,但并没有深入,让我这个菜鸟经常看的一知半解的,今天算是把这个原理给弄懂了,特地写一篇博文详细解答双飞翼布局的原理

圣杯布局利用float实现一个三栏布局,左右定宽,中间自适应,dom结构如下,注意middle的盒子必须放在第一,后面会解释为什么。然后三栏都设置float:left,左右栏定宽200px,中间宽度设置为100%

dom

<div class="middle"></div>
<div class="left"></div>
<div class="right"></div>

css

.middle{
	background:grey;
        width:100%;
}
.left{
	width: 200px;
	background:pink;
}
.right{
        width: 200px;
	background:lightblue;
}

效果如下,可以看到因为中间宽度设置的是100%,所以占满整个屏幕宽度,左右盒子被它挤到第二行了。这个时候主要的问题就是如何把left盒子移到第一行去?—— 设置负margin!

1.负margin

我们先随便给left盒子设置一个负margin的值:-100px,可以看到left盒子向右移动了,但因为移出了视窗区域,所以移出的部分我们看不到了。

而浮动有这样一个特性:

浮动框的上边缘会去贴当前行盒的上边缘或是之前浮动框的下边缘,左浮动框的左边缘会去贴包含框的左边缘,或者他之前的左浮动框的右边缘。如果当前行剩余的空间容不下一个浮动框,他就会换行。(右浮动同理)

所以当我们设置margin-left:-100px的时候left盒子的左边界其实是到了middle盒子距离右边100px的地方,但是由于宽度不够放置left盒子,所以left盒子仍然在第二行,多余的部分在第二行在视窗左边(看不到)。

那么如果我们把margin-left设置为left盒子的宽度,left盒子是不是就可以上去了? 你真聪明,就是这样的

下图吧margin-left设置-200px之后left盒子就跑到第一行去了

关于负margin的解释可以参考这篇博文,写的很详细https://www.cnblogs.com/LiveWithIt/p/6024864.html#commentform

2.负margin取值-100%

left盒子上去是上去了,但是位置不对啊,应该在左边而不是右边

很简单我们把margin-left设置为-100%就好了,如下:

刚开始我还有一点疑惑,为什么吧-200px设置为-100%就可以让left盒子到左边去呢?-100%和-200px不都一样吗?

后来突然想到当margin和padding取值百分比的时候是按照父元素的宽高设置的,那么我这里设置-100%就等价于把left盒子向左移动视窗宽度的距离 等价于让left盒子直接放置到最左边

3.left盒子的left:-200px

这个时候我们在middle盒子里面放一些文字内容,显然因为我们把left盒子移动之后,它就把middle左边200px的范围给覆盖了,middle的文字也就不能显现出来了。

我第一个想法是这不很简单吗,外面加个container,设置个padding-left:200px,但是这个行不通,我们可以看看效果,如下:

可以看到连同left和right盒子一起右移了200px,原因也显而易见——因为left盒子和middle并没有分开,单单只是重叠在一起,给外层盒子设置padding,当然连left盒子也一起移动了

开发者模式中可以看到container的paddingleft为200px

解决办法我觉得还是挺巧妙的:既然margin-left -100%能让我移动到最左边,那么我再往左边移动200px不就可以和middle盒子分开了吗~ 在这里margin-left为百分比不好增加具体的200px值,那么我们另辟蹊径,给left盒子设置一个position:relative,再设置left:-200px之后left盒子就和middle分开了(container的padding-left为200px)如下所示:

4.left盒子用position absolute?

为什么left盒子要用relative 而不用 absolute呢?因为left盒子已经设置float脱离文档流了,如果在设置absolute会让float失效,而relative就不存在这个问题了

1.当positionabsolute/fixed时,元素已脱离文档流,再对元素应用float失效(即不起作用)。

2.当positionstatic/relative时,元素依旧处于普通流中,再对元素应用float起作用。

5 right盒子

right盒子也是一样的解决思路,通过margin-left:-200px把它移动到middle盒子的右端,这里不需要盒子处于最左端,所以不需要让它-100%,仅仅让它回到第一行即可

同样给right盒子设置一个position relative 和 right -200px就可以让它不挡住middle的文字了

6 为什么middle盒子不放在中间

最后来解答一下之前留下来的问题,为什么middle盒子不放在中间,相信各位小伙伴们看到这里也大概知道了,因为双飞翼结构的精髓就是让middle占满整个视窗宽度,然后通过负margin让左右两边的盒子移动到第一行来实现左右定宽 中间适应布局。

如果让中间盒子放在中间,就会像这样子

如果我们用负值margin-left,如何给margin-left取值就成为了一个问题,因为middle盒子为了自适应是100%宽度,margin-left取-100% middle盒子就会覆盖left盒子,并且因为其width100% 所以left盒子无论如何取值都不可能和middle盒子分离开来了

那给middle盒子的margin-left设置固定的百分比呢?——答案也是不可以的,下面两幅图分别是middle取值不同的确定百分比的情况,我们可以看出当margin-left小于某一临界值时候,他会一直左移,其实就是他的左边界在第一行左移,当超过某个临界值,middle盒子就直接上移到第一行覆盖left盒子了。

大家可以猜猜看 这个临界值代表着什么?

临界值其实代表的就是left盒子的宽度所占父盒子宽度的比例!middle盒子左移百分比值超过了left盒子宽度占比它就会上移,因为middle的左边距已经到达了left盒子的最左边,给middle腾出了足够的宽度——也就是100%父级盒子宽度,所以middle就会上移,但凡middle左边界左移百分比到不了left占据百分比 给middle的空间就到不了100%

 

这个想法的证据就是我缩放浏览器就会改变这个临界值的大小,上图是浏览器半屏的情形,那么浏览器全屏,固定宽带为200px的left盒子占比就会变小,是不是这样的呢?

是的!下图可证  临界值变成了20%

完整代码

<!DOCTYPE html>
<html>
<head>
	<title></title>
	<style type="text/css">
    .left,
    .middle,
    .right{ 
        position: relative;
        float: left;
        min-height: 130px;
	body{
		padding-top: 200px;
	}
	.middle{
		margin-left: -20%;
		background:grey;
		width: 100%;
	}
	.left{
		width: 200px;
		background:pink;
	}
	.right{
		margin-left: -200px;
        right: -200px;
        width: 200px;
		background:lightblue;
	}
	.container{
		padding: 0 200px 0 200px;
	}
	</style>
</head>
<body>
	<div class="container">
	    <div class="left">
	    </div>
	    <div class="middle">
			《魔卡少女樱 CL EARCARD篇》是由CLAMP创作的、连载于杂志《好朋友》的漫画作品,是《魔卡少女樱》的续篇单行本由讲谈社出版,其繁体中文版由东立出版社出版。作品讲述了成为初中生的小樱的新冒险故事。作品亦改编为同名动画。
	    </div>
	    <div class="right">
	    </div>
	</div>
</html>

双飞翼布局的原理和双飞翼类似,就不多赘述了

猜你喜欢

转载自blog.csdn.net/Sallywa/article/details/89281231