盒子模型简介

在 CSS 盒子模型中,页面中的每一个元素都可以看成一个盒子,并占据一定的页面空间。

一个页面由很多这样的盒子组成,这些盒子之间会互相影响,因此掌握盒子模型需要从两个方面来理解:一是理解单独一个盒子的内部结构;二是理解多个盒子之间的相互关系

每个元素都可以看成一个盒子,盒子模型是由 content(内容)、padding(内边距)、margin (外边距)和 border(边框)这 4 个属性组成的。此外,在盒子模型中,还有 width(宽度)和 height(高度)两大辅助性属性。 2015-10-03-css-27.jpgimage.png

内容区

内容区是 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 又常常被称为“补白”,它指的是内容区到边框之间的那一部分。

  1. <body>
  2. <div>入会状况</div>
  3. </body>
  4. div
  5. {
  6. background-image:url(fhn1.jpg);
  7. width:72px;
  8. height:30px;
  9. line-height:30px;
  10. font-size:12px;
  11. color:Red;
  12. padding-left: 55px;
  13. }

使用背景图时,默认情况下,文字会紧贴边框左边,这是就可以使用 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 种情况来讨论:同级元素、父子元素和空元素。

外边距叠加的三种情况

同级元素

当一个元素出现在另一个元素上边的时候,第一个元素的下边距将会与第二个元素的上边距发生合并。
image.png

父子元素

当一个元素包含在另外一个元素中时(呈父子关系),假如没有 padding 或 border 把外边距分隔开,父元素和子元素的相邻上下外边距也会发生合并,如图 3-11 所示。 image.png

空元素

空元素,指的是没有子元素或者没有文字内容的元素,例如


等,当一个空元素有上下外边距时,如果没有 border 或者 padding,则元素的上外边距与下外边距就会合并。 image.png
如果空元素的外边距碰到另一个元素的外边距,它们也会发生合并。image.png
外边距叠加只有 3 种情况:同级元素、父子元素和空元素。此外,对于外边距叠加,我们还需要注意以下 4 点:

▶ 水平外边距,永远不会有叠加,水平外边距指的是 margin-left 和 margin-right

▶ 垂直外边距只有在以上 3 种情况下会叠加,垂直外边距指的是 margin-top 和 margin-bottom。

▶ 外边距叠加之后的外边距高度,等于发生叠加之前的两个外边距中的最大值。

▶ 外边距叠加针对的是 block 以及 inline-block 元素,不包括 inline 元素。因为 inline 元素的 margin-top 和 margin-bottom 设置无效。

外边距叠加的意义

image.png
如图,如果没有外边距叠加,第一个段落之后的所有段落之间的外边距,都是相邻的 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 为负数时,“后续元素”会被拉向指定方向。 image.png
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>

n-margin.png

<!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>

n-margin-left_right.png

负数 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 使得内容超出时不会影响页面整体布局,这是它的好处。