最近了解了圣杯布局和双飞燕布局,对 margin-right 和 float 了解更深了,写下这篇文章分享下我的收获
圣杯布局
先看看什么是圣杯布局。像下面这张图,有 title 和 footer,中间内容分成了三块,left,和 right 内容宽度固定,container 内容宽度随屏幕宽度变化而变化。这是在布局上的要求。这个要求很容易 flex 来实现,但是不满足加载顺序
圣杯对加载顺序也有要求,先加载 container,然后加载 left 和 right。DOM 解析是从前往后的,所以如果 left DOM 是在 container 之前,那么就会先加载 left 的 DOM 结构,并且先加载 left 涉及到的资源
上面的图像不像一个抽象的圣杯?
圣杯布局的写法是将 container 写在 left 和 right 之前,这样就可以满足加载顺序了。
好,基本要求了解了,那该如何实现呢?
由于网上有各种文章,这个话题都被说烂了,下面就不详细说代码了,只说重点的部分
html
<!DOCTYPE html>
<html lang="en">
<head>
<title>圣杯布局</title>
</head>
<body>
<div class="title">title</div>
<div class="content">
<div class="float container">container</div>
<div class="float left">left</div>
<div class="float right">right</div>
</div>
<div class="footer">footer</div>
</body>
</html>
title 和 footer 的 DOM 结构很普通,放在最前面和最后面。主要看中间部分,container 的 DOM 结构确实是放在 left 和 right 前面
下面是各个 DOM 结构的样式代码
css
.title,
.footer {
width: 100%;
height: 30px;
background-color: antiquewhite;
}
.float {
float: left;
}
.left,
.right,
.container {
height: 500px;
background-color: tomato;
}
.left {
width: 100px;
background-color: aquamarine;
}
.right {
width: 200px;
background-color: aqua;
}
.container {
width: 100%;
}
.footer {
clear: both;
}
为了在页面上明显地区分各个结构,将不同部分标上了不同的颜色,并且对 container,left,right DOM 添加了float: left
样式
现在变成了下面这个样子:
可以看到,页面显示的内容和 DOM 结构排列一致,container 在 left, right 前面。
footer 要想不被 float 影响,就要使用 clear:both;
调整 left,理解 float
现在要使用定位样式,将 left 放在 container 的右边
css
.content{
padding: 0 200px 0 100px;
}
先对 content 添加了 padding 样式,为接下来的 left 和 right 腾出位置
css
.left {
width: 100px;
background-color: aquamarine;
/* 将left放到container的左边 */
margin-left: -100%;
}
然后对 left 添加margin-left
样式,想让 left 往左移。现在是这个样子:
可以看到 left 贴到了 container 的右边,首先,这不是最终位置,最终位置是贴到窗口的左边框。其次,我想问的是,为什么 left 加上了margin-left: -100%;
后会到这个位置
margin-left 的作用是将当前元素往左移,margin-left: -100%;
往左移动父元素宽度(content.width)的距离,即 content 的宽度 width。 又因为 content 元素的 box-sizing 是默认的content-box
,所以 width 的 内容是不包含 padding 的宽度的。
现在假设一下,left 是紧挨着 container 右边的,那么往右移动content.width
的距离后,确实会恰好紧挨着 container 左边的。但现实是,left 是放在 container 下面的,这个如何解释?
其他 left **就是**
紧挨着在 container 右边的。因为,它们都是float:left;
元素。而现在 left 在 container下面,只是因为被 container 挤下来了而已。如果把 container 的宽度放小一定程度,那就会看到 left 跑上去了,如果再缩小,还会看到 right 跑上去。
理解 float 的元素之间是紧紧挨着的,是理解圣杯布局样式的关键
再给 left 加点样式,让其贴到整个视口的左边
css
.left {
width: 100px;
background-color: aquamarine;
/* 将left放到container的左边 */
margin-left: -100%;
/* 相对定位 */
position: relative;
right: 100px;
}
对于relative
来说,right:100px;
意味当前元素的右边,距离原本的位置右边有 100px 的距离。效果就是往左移动 100px 的距离
调整 right,理解 margin
css
.right {
width: 200px;
background-color: aqua;
/* 将right放到container的右边 */
margin-right: -200px;
}
right 元素的定位设置只有简单的margin-right: -200px;
,就能实现准确定位:
太神奇了吧
理解这个现象,首先要理解 margin-right。
我们知道 margin-left 如果是负值的话,效果就相当于将自身往左移动,而对于 margin-right 来说,不是将自身往右移,而是将当前元素的右边元素左移。margin 的意思是元素之间的边距,如果边距为负,自然就会出现元素重叠的现象,那么为什么不是左边的元素叠放到右边,而是右边的元素叠放到左边呢?
这是因为页面布局就好像是印刷排版,是从左放到右边的,一行放满了,就另起一行重新放置。
这就是为什么当margin-left 为负值时,也是当前元素相对于当前元素的左边元素
往左移。当 margin-right 为负值的时候,当前元素的右边元素
相对于当前元素往左移
引入排版这个概念后,是不是就很好理解了
right 元素的 width 为 200px,设置margin-right 后,右边元素就会往左移动 200px,彻底地将 right 覆盖。就相当于 right 元素的宽度不存在一样,width 变成了 0;
前面我提到,float 元素就是紧挨着一起的,right 放在了下面,是因为被 container 挤下来的,那么如果 right 宽度为 0 了,还能被挤下来了吗?显然不会了,所以 right 跑到了上面去了。证明完毕
margin-right 还能这么玩,真是没想到啊
总结
这篇文章分享了我学习完圣杯布局之后,对 float 和 margin 概念理解更进一步了,真是不可思议啊🤔
- float元素就是互相紧挨着的,下面的元素是被上面给挤下来了
- margin就是元素之间的边距,如果边距为负,就会出现元素重叠的现象,并且总是右边的元素覆盖左边的元素
大家有收获吗,欢迎在评论区留言哦