盒子模型简介
在 CSS 盒子模型中,页面中的每一个元素都可以看成一个盒子,并占据一定的页面空间。
一个页面由很多这样的盒子组成,这些盒子之间会互相影响,因此掌握盒子模型需要从两个方面来理解:一是理解单独一个盒子的内部结构;二是理解多个盒子之间的相互关系。
每个元素都可以看成一个盒子,盒子模型是由 content(内容)、padding(内边距)、margin (外边距)和 border(边框)这 4 个属性组成的。此外,在盒子模型中,还有 width(宽度)和 height(高度)两大辅助性属性。
内容区
内容区是 CSS 盒子模型的中心,它呈现了盒子的主要信息内容,这些内容可以是文本、图片等多种类型。内容区是盒子模型必备的组成部分,其他的部分都是可选的。
内容区有 width、height 和 overflow3 个属性。使用 width 和 height 属性可以指定盒子内容区的高度和宽度。在这里要注意一点,width 和 height 这两个属性是针对内容区而言,并不包括 padding 部分。
当内容信息太多,超出内容区所占范围时,可以使用 overflow 溢出属性来指定处理方法。
内边距
内边距,指的是内容区和边框之间的空间,可以被看成是内容区的背景区域。 关于内边距的属性有 5 种,即 padding-top、padding-bottom、padding-left、paddingright 以及综合了以上 4 个方向的简写内边距属性 padding。使用这 5 种属性可以指定内容区与各方向边框之间的距离。
外边距
外边距,指的是两个盒子之间的距离,它可能是子元素与父元素之间的距离,也可能是兄弟元素之间的距离。 外边距使得元素之间不必紧凑地连接在一起,这是 CSS 布局的一个重要手段。
外边距的属性也有 5 种,即 margin-top、margin-bottom、margin-left、margin-right 以 及综合了以上 4 个方向的简写外边距属性 margin。 同时,CSS 允许给外边距属性指定负数值,当指定负外边距值时,整个盒子将向指定负值的相反方向移动,以此可以产生盒子的重叠效果。这就是“负 margin 技术”。
边框
边框属性有 border-width、border-style、border-color 以及综合了 3 类属性的快捷边框属性 border。
深入 border
对于 border 属性,只有一个值得介绍的知识点,那就是 border:0 和 border:none 的区别。 border:0 与 border:none 的区别主要体现在两个方面:一方面是“性能差异”,另一方面是“兼容差异”。
性能差异
▶ border:0
border:0 表示把 border 定义为 0 像素。虽然 0px 在页面上看不见,但是浏览器依然会对 border 进行渲染,渲染之后,实际上是一个像素为 0 的 border。 也就是说,border:0 需要占用内存。
▶ border:none
border:none 表示把 border 定义为“none(无)”,浏览器解析 border:none 时并不会对它进行渲染。 也就是说,border:none 不需要占用内存。
兼容差异
兼容性差异只存在于 IE7 和 IE6 中,在其他浏览器中不存在兼容性问题,而目前 IE 已经渐渐被淘汰,所以这里不再赘述。
深入 padding
内边距 padding 又常常被称为“补白”,它指的是内容区到边框之间的那一部分。
<body>
<div>入会状况</div>
</body>
div
{
background-image:url(fhn1.jpg);
width:72px;
height:30px;
line-height:30px;
font-size:12px;
color:Red;
padding-left: 55px;
}
使用背景图时,默认情况下,文字会紧贴边框左边,这是就可以使用 padding 达到文字右移的效果。
外边距叠加
之前的学习中出现过这样一种状况: 有相邻的两个块元素 A 和 B,上面的为 A,下 面的为 B。其中 A 定义了一个 margin-bottom,B 定义了一个 margin-top。在浏览器预览效果中,我们会发现 A 和 B 之间的垂直距离明显小于 margin-bottom 和 margin-top 相加之和。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="first">first</div>
<div id="second">second</div>
</body>
</html>
div
{
width: 500px;
height:50px;
line-height:60px;
text-align:center;
font-size:30px;
color:White;
background-color:lightskyblue;
}
#first{margin-bottom:20px;}
#second{margin-top:30px;}
/*#second{margin-top:50px;}*/
在这里,A 的 margin-bottom 为 20px,B 的 margin-top 为 30px,但是 A 和 B 之间的间距并不是 50px。这个现象就是由外边距叠加引起的。
外边距叠加,又称“margin 叠加”,指的是当两个垂直外边距相遇时,这两个外边距将会合并为一个外边距,即“二变一”。其中,叠加之后的外边距高度,等于发生叠加之前的两个外边距中的最大值。
对于外边距叠加,我们分为 3 种情况来讨论:同级元素、父子元素和空元素。
外边距叠加的三种情况
同级元素
当一个元素出现在另一个元素上边的时候,第一个元素的下边距将会与第二个元素的上边距发生合并。
父子元素
当一个元素包含在另外一个元素中时(呈父子关系),假如没有 padding 或 border 把外边距分隔开,父元素和子元素的相邻上下外边距也会发生合并,如图 3-11 所示。
空元素
空元素,指的是没有子元素或者没有文字内容的元素,例如
等,当一个空元素有上下外边距时,如果没有 border 或者 padding,则元素的上外边距与下外边距就会合并。

如果空元素的外边距碰到另一个元素的外边距,它们也会发生合并。

外边距叠加只有 3 种情况:同级元素、父子元素和空元素。此外,对于外边距叠加,我们还需要注意以下 4 点:
▶ 水平外边距,永远不会有叠加,水平外边距指的是 margin-left 和 margin-right
▶ 垂直外边距只有在以上 3 种情况下会叠加,垂直外边距指的是 margin-top 和 margin-bottom。
▶ 外边距叠加之后的外边距高度,等于发生叠加之前的两个外边距中的最大值。
▶ 外边距叠加针对的是 block 以及 inline-block 元素,不包括 inline 元素。因为 inline 元素的 margin-top 和 margin-bottom 设置无效。
外边距叠加的意义
如图,如果没有外边距叠加,第一个段落之后的所有段落之间的外边距,都是相邻的 margin-top 和 marginbottom 之和,这样就跟第一个段落显得不一致了。
如果发生外边距叠加,段落之间的 margin-top 和 margin-bottom 就会合并在一起,这样就跟第一个段落显得一致了。
CSS 定义外边距叠加的初衷就是为了更好地对文章进行排版。 在实际开发中,最好统一使用 margin-top 或 margin-bottom,不要混合使用,从而降低出现问题的风险。这并不是必需的,但却是一个良好的习惯。
负 margin 技术
在 CSS 中,margin 属性取值可以是正数,也可以是负数。无论取正数还是负数,margin 都可以让当前元素或者周围元素进行移动。这里主要介绍负 margin 技术。
简介
当取值为负数时,margin 对普通文档流元素和对浮动元素的影响是不一样的。其中,负 margin 对普通文档流元素的影响,可以分为两种情况。
▶ 当元素的 margin-top 或者 margin-left 为负数时,“当前元素”会被拉向指定方向。
▶ 当元素的 margin-bottom 或者 margin-right 为负数时,“后续元素”会被拉向指定方向。
margin-top 和 margin-left 会将“当前元素”拉出,然后覆盖“其他元素”。而 margin-bottom 和 margin-right 是将“后续元素”拉进,然后覆盖“当前元素”。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
#wrapper div {
width: 200px;
height: 60px;
line-height: 60px;
font-size: 21px;
font-weight: bold;
text-align: center;
color: White;
}
#first {
background-color: hotpink;
}
#second {
background-color: lightskyblue;
margin-bottom: -30px;
}
#third {
background-color: purple;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="first">first</div>
<div id="second">second</div>
<div id="third">third</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
/*去除inline-block元素之间的间距*/
#wrapper {
font-size: 0;
}
#wrapper div {
display: inline-block;
width: 80px;
height: 80px;
line-height: 80px;
font-size: 24px;
font-weight: bold;
text-align: center;
color: White;
}
#first {
background-color: hotpink;
}
#second {
background-color: lightskyblue;
margin-right: -30px;
}
#third {
background-color: purple;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="first">1</div>
<div id="second">2</div>
<div id="third">3</div>
</div>
</body>
</html>
负数 margin 技巧
负 margin 使用灵活,应用广泛,常用的技巧有以下 4 个。
▶ 图片与文本对齐。
▶ 自适应两列布局。
▶ 元素垂直居中。
▶ tab 选项卡。
图片与文本对齐
当图片与文本放到一起的时候,它们在底部水平方向上往往都是不对齐的。这是因为在默认情况下,图片与周围的文本是“基线对齐”,也就是 vertical-align:baseline。如果想让它们在底部水平方向对齐,有两种方法:一种是使用 vertical-align:text-bottom ;另外一种是使用负 margin 技术。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
img
{
width: 1em;
height: 1em;
margin: 0 3px -3px 0;
}
div
{
text-indent: 2em;
border: 1px solid black;
}
</style>
</head>
<body>
<div>
<img src="map.jpg" alt="" />黑暗之魂 Dark Soul
</div>
</body>
</html>
自适应两列布局
自适应两列布局,指的是在两列布局中,其中一列的宽度是固定的,而另外一列宽度自适应。 如果使用浮动来做的话,只能实现固定的左右两列布局,并不能实现其中一列为自适应的布局。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
#main,
#sidebar {
float: left;
color: white;
}
#main {
width: 100%;
margin-right: -200px;
background-color: hotpink;
}
#sidebar {
width: 200px;
background-color: lightskyblue;
}
/* 防止浏览器可视区域宽度不足时发生文本重叠*/
#main p {
margin-right: 210px;
}
/* 它是 200px + 10px, 10px是他们的间距*/
</style>
</head>
<body>
<div id="main">
<p>这是主体部分,自适应宽度</p>
</div>
<div id="sidebar">
<p>这是侧边栏部分,固定宽度 </p>
</div>
</body>
</html>
元素垂直居中
想要实现块元素的垂直居中,一般来说比较麻烦,不过有一个经典的方法就是使用 position 结合负 margin 来实现,具体做法是:首先,给父元素写上 position:relative; ,这样做是为了给子元素添加 position:absolute 的时候不会被定位到“外太空”去;然后给子元素添加如下属性。
父元素
{
position:relative;
}
子元素
{
position:absolute;
top:50%;
left:50%;
margin-top: "height值一半的负值" ;
margin-left: "width值一半的负值" ;
}
这种方法是万能的,也就是说它不仅可以用于 block 元素,还可以用于 inline 元素和 inlineblock 元素。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<style type="text/css">
#father {
position: relative;
width: 200px;
height: 160px;
border: 1px solid silver;
}
#son {
position: absolute;
top: 50%;
left: 50%;
margin-left: -50px;
width: 100px;
height: 60px;
margin-top: -30px;
background-color: hotpink;
}
</style>
</head>
<body>
<div id="father">
<div id="son"></div>
</div>
</body>
</html>
以上代码可以达成效果:垂直居中,首先使用 margin 将子元素拉到左上角,容易发现,子块的中心在移动后落到了父块的左上角,然后的 top 和 left 指的是该中心在父块中,关于顶边的距离为高的 50%,关于左边的距离为宽度的 50%。
关于垂直居中,还有其他方式,之后还会再见到。
tab 选项卡
tab 选项卡效果是一种十分节省页面空间的方式,在实际开发中会经常用到。其关键就是使用 margin-top:-1px 来解决选项卡下边框显示的问题。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
.tab {
width: 500px;
height: 300px;
border: 1px solid rgb(22, 2, 2);
margin: 10px auto;
overflow: hidden;
}
ul {
list-style-type: none;
overflow: hidden;
}
ul li {
float: left;
width: 25%;
line-height: 35px;
text-align: center;
box-sizing: border-box;
border-right: 1px solid silver;
border-bottom: 1px solid silver;
margin-top: -1px;
font-weight: bold;
cursor: pointer;
}
li:last-child {
border-right: none;
}
.active {
background: rgb(192, 72, 72);
border-bottom: none;
}
.tab div {
width: 100%;
height: 300px;
display: none;
}
</style>
<script>
window.onload = function () {
var aDiv = document.querySelectorAll(".tab div");
var aTab = document.querySelectorAll(".tab ul li");
for (var i = 0; i < aTab.length; i++) {
aTab[i].index = i;
aTab[i].onmouseover = function () {
for (var j = 0; j < aTab.length; j++) {
aDiv[j].style.display = "none";
aTab[j].className = "";
};
aDiv[this.index].style.display = "block";
this.className = "active";
};
};
}
</script>
</head>
<body>
<div class="tab">
<ul>
<li class="active">娱乐</li>
<li>经济</li>
<li>科技</li>
<li>时事</li>
</ul>
<div style="display: block;">"娱乐"部分的内容……</div>
<div>"经济"部分的内容……</div>
<div>"科技"部分的内容……</div>
<div>"时事"部分的内容……</div>
</div>
</body>
</html>
其中的标签作用均可以在编辑器和浏览器中查看,这里不做解释,关于 JS 内容,暂时跳过。
overflow
W3C 标准指出,通常一个盒子的内容是被限制在盒子边框之内的,但是有时也会溢出,即部分或者全部内容跑到盒子边框之外。
在 CSS 中,我们可以使用 overflow 属性来定义内容溢出元素边框时发生的事情。
对于 overflow 属性,最常见的用途有以下 3 个:
▶ 使用 overflow:scroll 显示滚动条。
▶ 使用 overflow:hidden 来隐藏内容,以免影响布局。
▶ 使用 overflow:hidden 来清除浮动。
overflow:hidden 会将超出元素的部分自动隐藏。不好的一点就是,这部分的内容会显示不完全,比如图片只显示了一部分。不过 overflow:hidden 使得内容超出时不会影响页面整体布局,这是它的好处。