【Web前端HTML5&CSS3】06、盒模型

1,522 阅读12分钟

六、盒模型

1、文档流(normalflow)

网页是一个多层的结构,一层摁着一层

427afb11d92e0c4a6b1dea762d85c5d1png

通过 CSS 可以分别为每一层来设置样式,作为用户来讲只能看到最顶上一层

这些层中,最底下的一层称为文档流

文档流是网页的基础我们所创建的元素默认都是在文档流中进行排列

对于我们来元素主要有两个状态

  • 在文档流中
  • 不在文档流中(脱离文档流)

那么元素在文档流中有什么特点,我们接着往下看

2、块元素

  • 块元素会在页面中独占一行
  • 默认宽度是父元素的全部(会把父元素撑满)
  • 默认高度是被内容撑开(子元素)

080c032067884d770c86ccbf274ed5e6png

3、行内元素

  • 行内元素不会独占页面的一行,只占自身的大小
  • 行内元素在页面中左向右水平排列(书写习惯一致)
  • 如果一行之中不能容纳下所有的行内元素,则元素会换到第二行继续自左向右排列
  • 行内元素的默认宽度和高度都是被内容撑开

979118a55475dd62fc9ec197e46b9e53jpeg

4、盒子模型

盒模型、盒子模型、框模型(box model)

CSS 将页面中的所有元素都设置为了一个矩形的盒子

d06232c90cee4c38a9a3bda54145bb69gif

将元素设置为矩形的盒子后,对页面的布局就变成将不同的盒子摆放到不同的位置

每一个盒子都由一下几个部分组成:

  • 内容区(content)
  • 内边距(padding)
  • 边框(border)
  • 外边距(margin)

image20220829202637363png

内容区(content)

内容区是盒子模型的中心,它呈现了盒子的主要信息内容,这些内容可以是文本、图片等多种类型

image20220829203427397png

元素中的所有的子元素和文本内容都在内容区中

  • width和height 设置排列内容区的大小
  • width 设置内容区的宽度
  • height 设置内容区的高度

示例

.box1 {
  width: 200px;
  height: 200px;
  border-color: red;
  /*
              solid 实线
              dotted 点状虚线
              dashed 虚线
              double 双线
  */
  border-style: solid;
  background-color: rgb(73, 184, 139);
}

效果

image20220829232008345png

边框(border)

边框属于盒子边缘,边框里边属于盒子内部,出了边框都是盒子的外部

e54266bf90d5dc77568f7f0bc92fb923gif

注意:边框的大小会影响到整个盒子的大小

  • border-width:边框的宽度:默认 3px

    • border-top-width 上边框的宽度
    • border-right-width 右边框的宽度
    • border-bottom-width 下边框的宽度
    • border-left-width 左边框的宽度
  • border-color 边框的颜色:默认使用 color 的颜色值

  • border-top-color 上边框的颜色

  • border-right-color 右边框的颜色

  • border-bottom-color 下边框的颜色

  • border-left-color 左边框的颜色

  • border-style:边框的样式:没有默认值,必须指定

    • border-top-style 上边框的样式
    • border-right-style 右边框的样式
    • border-bottom-style 下边框的样式
    • border-left-style 左边框的样式

效果(solid)

image20220830102319275png

效果(dotted)

image20220830102506680png

效果(dashed)

image20220830102558654png

效果(double)

image20220830102632241png

不论是border-widthborder-colorborder-style 还是其衍生出来的属性写法,都可以指定每个方向的边框情况

设定几个值就决定了对应方向的宽度、颜色或样式

  • 四个值:上 右 下 左
  • 三个值:上 左右 下
  • 两个值:上下 左右
  • 一个值:上下左右

其实不管设置几个值,只要记住:其顺序是按顺时针方向设置的,剩下的可以由矩形的对称性推导出来

border:简写属性,通过该属性可以同时设置边框所有的相关样式,并且没有顺序要求

  • border-top 上边框的宽度、颜色和样式
  • border-right 右边框的宽度、颜色和样式
  • border-bottom 下边框的宽度、颜色和样式
  • border-left 左边框的宽度、颜色和样式
.box1 {
  border: 10px red solid;
}

内边距(padding)

内边距,也叫填充,是内容区和边框之间的空间

  • padding-top 上内边距
  • padding-right 右内边距
  • padding-bottom 下内边距
  • padding-left 左内边距

padding 内边距的简写属性,可以同时指定四个方向的内边距,规则和边框中属性值设置一样

注意:内边距的设置会影响到盒子的大小,背景颜色会延伸到内边距上

示例

<style>
  .outer {
    width: 200px;
    height: 200px;
    border: 10px orange solid;
    background-color: pink;
    padding-right: 100px;
    padding-top: 100px;
    padding-bottom: 100px;
    padding-left: 100px;
  }

  .inner {
    width: 200px;
    height: 200px;
    background-color: greenyellow;
  }
</style>

<div class="outer">
  <div class="inner"></div>
</div>

效果

image20220830154742336png

可以看出,当内外 div 宽度和高度一样时,由于 outer 设置了一个 padding 属性,其盒子大小被“撑大了”

盒子可见框的大小,由内容区、内边距和边框共同决定,所以在计算盒子大小时,需要将这三个区域加到一起计算

外边距(margin)

外边距,也叫空白边,位于盒子的最外围,是添加在边框外周围的空间。空白边使盒子之间不会紧凑地连接在一起,是 CSS 布局的一个重要手段

注意:外边距不会影响盒子可见框的大小,但是外边距会影响盒子的位置和占用空间

一共有四个方向的外边距:

  • margin-top:上外边距

    • 设置正值,元素自身向下移动
    • 设置负值,元素自身向上移动
  • margin-right:右外边距

    • 设置正值,其右边的元素向右移动
    • 设置负值,其右边的元素向左移动
    • 上述说法并不准确,对于块元素,设置margin-right不会产生任何效果
  • margin-bottom :下外边距

    • 设置正值,其下边的元素向下移动
    • 设置负值,其下边的元素向上移动
    • 上述说法并不准确,对于块元素,会有垂直方向上的边距重叠问题(后面会细说)
  • margin-left:左外边距

    • 设置正值,元素自身向右移动
    • 设置负值,元素自身向左移动

元素在页面中是按照自左向右的顺序排列的,所以默认情况下

  • 如果我们设置的左和上外边距则会移动元素自身
  • 而设置下和右外边距会移动其他元素

示例 1

.box1 {
  width: 200px;
  height: 200px;
  background-color: #bfa;
  border: 10px orange solid;

  margin-top: 100px;
  margin-right: 100px;
  margin-bottom: 100px;
  margin-left: 100px;
}

效果

image20220830154845734png

示例 2:

.box1 {
  width: 200px;
  height: 200px;
  background-color: #bfa;
  border: 10px orange solid;
  margin-bottom: 100px;
}

.box2 {
  width: 200px;
  height: 200px;
  background-color: #bfa;
  border: 10px red solid;
  margin-top: 100px;
}

效果

c5f16dc4f083b514f7e53b1f37f520dbpng

5、水平方向布局

元素在其父元素中水平方向的位置由以下几个属性共同决定

  • margin-left
  • border-left
  • padding-left
  • width
  • padding-right
  • border-right
  • margin-right

一个元素在其父元素中,水平布局必须要满足以下的等式

margin-left + border-left + padding-left + width + padding-right + border-right + margin-right = 其父元素的宽度

以上等式必须满足,如果相加结果使等式不成立,则称为==过渡约束==

30c7e982a9aaeaaac7181f5e51427098jpeg

则等式会自动调整调整的情况:

  • 如果这七个值中没有auto的情况,则浏览器会自动调整margin-right值以使等式满足

    100 + 0 + 0 + 200 + 0 + 0 + 0 = 800 ==> 100 + 0 + 0 + 200 + 0 + 0 + 500 = 800

  • 如果这七个值中有auto的情况,则会自动调整auto值以使等式成立

    这七个值中有三个值可以设置为autowidthmargin-leftmaring-right

    1. 如果某个值为 auto,则会自动调整auto的那个值以使等式成立 200 + 0 + 0 + auto + 0 + 0 + 200 = 600 ==> 200 + 0 + 0 + 400 + 0 + 0 + 200 = 800

      auto + 0 + 0 + 200 + 0 + 0 + 200 = 600 ==> 400 + 0 + 0 + 200 + 0 + 0 + 200 = 800

      200 + 0 + 0 + 200 + 0 + 0 + auto = 600 ==> 200 + 0 + 0 + 200 + 0 + 0 + 400 = 800

    2. 如果宽度为auto,则宽度会调整到最大,其他auto的外边距会自动设置为 0

      auto + 0 + 0 + auto + 0 + 0 + 200 = 600 ==> 0 + 0 + 0 + 600 + 0 + 0 + 200 = 800

      200 + 0 + 0 + auto + 0 + 0 + auto = 600 ==> 200 + 0 + 0 + 600 + 0 + 0 + 0 = 800

      auto + 0 + 0 + auto + 0 + 0 + auto = 600 ==> 0 + 0 + 0 + 800 + 0 + 0 + 0 = 800

    3. 如果外边距都为auto,则auto的外边距会自动均分以使等式成立

      auto + 0 + 0 + 200 + 0 + 0 + auto = 600 ==> 300 + 0 + 0 + 200 + 0 + 0 + 300 = 800

8e724b2f4df77f1fef55ff9a7c8b82adjpeg

示例

<style>
  .box1 {
    width: 200px;
    height: 200px;
    background-color: #bfa;
    border: 10px orange solid;
    /* 下列条件等价于 margin: 0 auto */
    margin-left: auto;
    margin-right: auto;
  }
</style>
<div class="box1"></div>

效果

image20220830172408221png

6、垂直方向布局

元素溢出

子元素是在父元素的内容区中排列的,如果子元素的大小超过了父元素,则子元素会从父元素中溢出

3bd5d68af80a8c4eb2743de0f3103c6ajpeg

使用overflow/overflow-x/overflow-y属性来设置父元素如何处理溢出的子元素

可选值:visible/hidden/scroll/auto

visible 溢出内容会在父元素外部位置显示,默认值

示例

<style>
  .box1 {
    width: 200px;
    height: 200px;
    background-color: #bfa;
    border: 10px orange solid;
    overflow: visible; /* 默认值 */
  }
</style>
<div class="box1">
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores aspernatur
  illo inventore deleniti laudantium quaerat excepturi sed quidem tempore?
  Eaque, cumque porro. Fuga quam error cupiditate quasi eveniet in numquam!
</div>

效果

image20220830172703579png

hidden 溢出内容会被裁剪,不会显示

示例

<style>
  .box1 {
    width: 200px;
    height: 200px;
    background-color: #bfa;
    overflow: hidden; /* 隐藏溢出内容 */
  }
</style>
<div class="box1">
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores aspernatur
  illo inventore deleniti laudantium quaerat excepturi sed quidem tempore?
  Eaque, cumque porro. Fuga quam error cupiditate quasi eveniet in numquam!
</div>

效果

image20220830172809315png

scroll 生成两个滚动条,通过滚动条来查看完整的内容

示例

<style>
  .box1 {
    width: 200px;
    height: 200px;
    background-color: #bfa;
    overflow: scroll;
  }
</style>
<div class="box1">
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores aspernatur
  illo inventore deleniti laudantium quaerat excepturi sed quidem tempore?
  Eaque, cumque porro. Fuga quam error cupiditate quasi eveniet in numquam!
</div>

效果

image20220830172908376png

image20220830172922423png

<style>
  .box1 {
    width: 200px;
    height: 200px;
    background-color: #bfa;
    overflow: auto;
  }
</style>
<div class="box1">
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Asperiores aspernatur
  illo inventore deleniti laudantium quaerat excepturi sed quidem tempore?
  Eaque, cumque porro. Fuga quam error cupiditate quasi eveniet in numquam!
</div>

效果

image20220830172958570png

边距折叠

垂直外边距的重叠(折叠):相邻的垂直方向外边距会发生重叠现象

兄弟元素

兄弟元素间的相邻,垂直外边距会取两者之间的较大值(两者都是正值)

特殊情况:

  • 如果相邻的外边距一正一负,则取两者的和
  • 如果相邻的外边距都是负值,则取两者中绝对值较大的

示例

.box1,
.box2 {
  width: 200px;
  height: 200px;
  font-size: 100px;
}

.boxl {
  background-color: #bfa;
  /*设置一个下外边距*/
  margin-bottom: 100px;
}

.box2 {
  background-color: orange;
  /*设置一个上外边距*/
  margin-top: 100px;
}

效果

f931e5ffe869cb7af81742c7f1ef712dpng

疑问

当浏览器缩放比例是 100%时,我们使用FastStone Capture工具自带的刻度尺测量,发现“兄弟”之间似乎没有我们想象的那么“亲近”

两者的垂直方向间距是 125px,我们明明上下元素设置的都是 100px 啊,这是为什么呢?

在网页布局中,通过谷歌浏览器或火狐浏览器预览时,发现我们定义的盒模型 width,height,margin,padding 值都是不准确的

谷歌、火狐浏览器 缩放为 80% 时,margin 值才正确[2]

总结

兄弟元素之间的外边距的重叠,对于开发是有利的,所以我们不需要进行处理

26ccb9a9096d2bfda42e2a3b2aa95047gif

父子元素

父子元素间相邻外边距,子元素会传递给父元素(上外边距)

示例

.box3{
width200px;
    height:200px;
    background-color: #bfa;
}

.box4{
    width: 100px;
    height: 100px;
    background-color: orange;
    /* margin-top: 100px; */
}

效果

不加 margin-top

watermark,typeZmFuZ3poZW5naGVpdGk,shadow10,textaHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1OTI1NTU4,size16,colorFFFFFF,t7020220830173213517png

加 margin-top

watermark,typeZmFuZ3poZW5naGVpdGk,shadow10,textaHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1OTI1NTU4,size16,colorFFFFFF,t70png

父子外边距的折叠会影响到页面的布局,必须要进行处理

24c1780e17f9b956261732c6d8bec903jpeg

处理方式 1

1、我们转换思路,将对子元素的调整转为对父元素的调整

.box3 {
  width: 200px;
  height: 200px;
  background-color: #bfa;
  padding-top: 100px; /* 不调整子元素的margin,而是转而调整父元素的padding */
}

.box4 {
  width: 100px;
  height: 100px;
  background-color: orange;
  /* margin-top: 100px; */
}

效果

5f0dc3466e5630ff04359a80a0205f38png

可以看到父元素位置虽然正确了,但是高度却被“撑大了”。我们之前说过,padding 属性会影响元素的大小

2、这里我们还需要计算并手动调整下父元素的高度

.box3 {
  width: 200px;
  height: 100px; /* height: 200px; */
  background-color: #bfa;
  padding-top: 100px;
}

.box4 {
  width: 100px;
  height: 100px;
  background-color: orange;
}

效果

765e417b0251acba822de090ddfdf6dbpng

处理方式 2

1、我们仍然保留子元素的margin-top属性,但是给父元素加一个上边框

.box3 {
  width: 200px;
  height: 200px;
  background-color: #bfa;
  border-top: 1px rebeccapurple solid; /* 在父元素上加一个border-top(上边框) */
}

.box4 {
  width: 100px;
  height: 100px;
  background-color: orange;
  margin-top: 100px; /* 不删除,保留 */
}

效果

c56fa4594b82be6a80f6fc34d84e531bpng

2、但是因为加了 1px 的边框,所以父元素盒子的高度也增加了 1px。那我们就需要手动调整父元素的高度,同时让边框颜色与父元素盒子颜色保持一致

.box3 {
  width: 200px;
  height: 199px; /* height: 200px; */
  background-color: #bfa;
  border-top: 1px #bfa solid;
}

.box4 {
  width: 100px;
  height: 100px;
  background-color: orange;
  margin-top: 100px;
}

f7446f62897af28d0cecdaa227510984png

但是我们没有发现一个问题不难发现一个问题,子元素也往下移动了 1px 的距离

因为父元素高度少了 1px,而子元素的 margin-top 是从边框下面开始算的

所以,凭借大家朴素的情感,哪个应该怎么判? 应该怎么改?

6a06c3e28a6a86ccfaff8715170b81c7gif

改法也很简单,margin-top 减去一个像素即可

.box3 {
  width: 200px;
  height: 199px;
  background-color: #bfa;
  border-top: 1px #bfa solid;
}

.box4 {
  width: 100px;
  height: 100px;
  background-color: orange;
  margin-top: 99px; /* margin-top: 100px; */
}

效果

9e66ca2ff5e5da3492054a3ebd49fdb4png

同时,我们用刻度尺测量,父子元素底部是在一条水平线上的

84d32f4309e7e2870d60334ec76b6809png

脱离文档流

上述示例 2 中,使用了 border 属性,就让子元素的外边距不去传递给父元素了,这是为什么呢?

margin (子元素远离父元素边框)[3]

如果父盒子没有设置 border 框着,那么他的子元素无法利用 margin-top 来远离父元素的上边框

如果使用了 margin-top 会使子元素和父元素一起往下移

(子想离,父不设置 border 边框 则离得是流 不是父盒子)

d8cca9d19c3e1688ee2572d9b6b85238jpeg

应该是 border 让元素脱离了文档流(margin 塌陷)

b17cf83f82b5698f2759a1a1e4700f9ajpeg

好吧好吧,至于什么是 margin 塌陷,我也是问了度娘,有兴趣的可以自行百度,这里就不再赘述了