盒模型
今天我们来看一下网页布局中很重要的一个概念:标准盒模型(框模型),如果理解了盒模型中各个元素的用法,才能熟练地使用css的定位方法和技巧。所有的页面的元素都可以抽象成一个盒子(其实也比较贴合现实生活),说通俗点,就是我们要养成这样一个思维习惯:看到一个元素,就要想到它的每一层结构;先来一张W3C教程里的图解镇楼:
我们可以看到,平时我们设置的width和height只是一个元素的一部分(也就是实际内容所占的空间),并不是这个元素整体所占的总空间,我们把人当成一个最小单位来举例子:
两个实体:width*height(实际内容所占的大小)——我们的身体 border(边框)——衣服
两个距离:padding(内边距)(父子元素之间的距离)——衣服和身体之间的距离 margin(外边距)(兄弟元素之间的距离)——人与人之间的距离
【注】:
-
实际内容所占的大小是必须要有的(不管被撑开,自己设置还是自适应获得的大小),你没肉体,只有灵魂合适吗?我们是唯物主义者;
-
边框看需求,就好比你的衣服出去要穿,洗澡还穿吗?
-
内边距看需求,就好比我们买衣服要买适合自己的尺码,因为需要衣服给自己带来一个合适的空间;
-
外边距看需求,人与人之间的距离,不同的人和你之间的舒适距离不同
说了这么多废话,能看出来除了实际内容所需要的大小,其他都是看需求,也就是看页面的布局需求,说白了,就是用户哪样舒服哪样来。下面来聊一聊盒模型的使用中注意的地方:其中width、height和border的使用没有什么问题,就是margin和padding使用起来要小心一点,先来看问题较小的padding,padding是内边距,但是书写了padding(不管哪个方向),盒子大小就会增大,也就是padding是凭空增加的大小,为了不影响其他元素,使用了padding后,我们就要在相应的方向上减去内容的大小,例:
1 <!doctype html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>padding</title>
6 <style>
7 div{100px;height:100px;background:yellow;border:2px solid #000;
8 }
9 </style>
10 </head>
11 <body>
12
13 <div>
14 内容
15 </div>
16
17 </body>
18 </html>
现在我设置了一个100px;height:100px;border:2px的元素,总大小是104*104
1 <!doctype html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>padding</title>
6 <style>
7 div{100px;height:100px;background:yellow;border:2px solid #000;padding:10px 15px 0 20px;
8 }
9 </style>
10 </head>
11 <body>
12
13 <div>
14 内容
15 </div>
16
17 </body>
18 </html>
然后我加入了一个上:10px;右15px;下0px;左:20px的padding,他的总大小变成了(104+15+20)*(104+10):139 *114,下面我们来看下margin的使用需要注意的问题:
- 上下mragin会重叠,左右不会(也就是上面元素的margin-bottom和下面元素的margin-top会重合)
1 <!doctype html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>margin问题一</title>
6 <style>
7 .top{100px;height:100px;background:yellow;margin-bottom:20px;}
8 .bottom{100px;height:100px;background:red;margin-top:100px;}
9 </style>
10 </head>
11 <body>
12
13 <div class="top"></div>
14 <div class="bottom"></div>
15
16
17 </body>
18 </html>
左侧图为上面元素的margin-bottom,右侧图为下面元素的margin-top,我们可以看到下面元素的大距离覆盖了上面元素的小距离,它们之间的距离是100px,而不是120px
-
- 方案:只设置一方即可,其实这个只要思维习惯好,就不用担心,因为你的目的是为了设置上面的元素和下面的元素的距离,那么直接给一个元素书写一个总距离margin就可以了
- 块元素内的第一个块状子元素的margin-top会向父元素无限传递(也就是只要满足条件,就会一直向上传)
1 <!doctype html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>margin问题2</title>
6 <style>
7 .top{200px;height:200px;background:blue;}
8 .top .top-son1{40px;height:40px;background:yellow;margin-top:50px;}
9 .top .top-son2{40px;height:40px;background:red;margin-top:30px;}
10 </style>
11 </head>
12 <body>
13
14 <div class="top">
15 <div class="top-son1"></div>
16 <div class="top-son2"></div>
17 </div>
18
19 </body>
20 </html>
我们可以看到父元素内第二个子元素正常显示了它的margin-top,但第一个子元素的margin-top并没有拉开它与父元素的距离,而是传给了父元素top,使得top和top的父元素body拉开了50px的距离,而且还没完,top作为body的第一个块状子元素,又向body传递了50px的margin-top,导致body和body的父元素html拉开了50px的距离,幸亏body不是html的第一个块状子元素,所以传递到此结束,感觉像瘟疫一样,真的是很可怕。接下来我们来看一下怎么来解决这个问题:
- 方案:
- 给父元素设置至少1px 的padding-top
- 给父元素设置至少1px的border-top
这两个方案明显就是牺牲小我,保全大我,因为虽然解决了,但是改变了大小,导致精确度变差,而且说不定就因为这1px,导致你还要去调其他元素的大小和距离
-
- 给父元素设置浮动
- 给子元素设置浮动
这两个方案感觉有点兴师动众,为了解决这个问题,又跳到了浮动的坑里,就算浮动不会出现问题,那么也打乱了自己的布局思路,感觉划不来
-
- 给父元素设置一个属性overflow:hidden
- 给父元素设置伪类:before{content:"";display:table;}
这个两个方案是目前为止,最偏向完美的解决方案了,不需要改动其他元素额距离,只需要加一条属性即可
- 行元素上下会穿透,左右正常
1 <!doctype html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>margin问题3</title>
6 <style>
7 .top{200px;height:100px;background:yellow;}
8 span{background:gray;margin:20px;border:10px solid #000;padding:20px;}
9 .bottom{200px;height:100px;background:red;}
10 </style>
11 </head>
12 <body>
13
14 <div class="top"></div>
15 <span>一个行元素</span>
16 <div class="bottom"></div>
17
18 </body>
19 </html>
我们可以看出行元素的上下margin穿透了上下两个元素
-
- 方案:避免给行元素设置上下盒模型