CSS盒模型

盒模型是CSS布局的基础,因为所有的HTML元素都能看做是一个一个的盒子。

CSS盒模型

CSS盒模型包含四个部分:

image-20180910145515691

  • Content:盒内容,文本和图片显示在这里
  • Padding:内容周围的空白部分,padding是透明的
  • Border:边框,边框围绕padding和内容
  • Margin:边框外的空白部分,margin是透明的

相关属性

padding

padding是透明的,我们可以分别设置padding的宽度:padding-top,padding-left,padding-bottom,padding-right

margin

margin也是透明的,我们也可以分别设置margin的宽度:margin-top,margin-left,margin-bottom,margin-right

**需要注意的是,当两个盒子相邻时,它们之间的距离是两个盒子中较大的margin,而不是两个margin之和。这个现象叫margin-collapse**。

border
  • border可以分别设置宽度:border-top,border-left,border-bottom,border-right
  • 设置边框的样式
    • border-width设置边框的宽度(可以设置数值,也可以设置thick,medium,thin
    • border-style设置边框样式,如(dotted点状,solid实线,inset嵌入)
    • border-color设置边框颜色
    • 以上三个属性可以通过border简写直接设置border: 1px solid black
  • 混合设置,如border-top-width,border-right-color

元素宽高

widthheight属性

元素的宽高通过widthheight属性来设置。但是widthheight属性设置的是内容即content area的宽高,元素的实际宽高需要将padding,border,margin计算进去。

IE盒子模型和W3C盒子模型

如上所述,W3C标准的盒模型在计算宽高时,是计算的内容部分的宽高。

image-20180910161914949

但IE盒模型包含paddingborder,所以在计算widthheight时,会得到不一样的值。

image-20180910161932994

指定盒模型

box-sizing属性可以指定使用元素的哪个宽高作为元素的整体宽高。

box-sizing: content-box:以内容为宽高

box-sizing: border-box:以content+border+padding为宽高

还可以将设定放在CSS reset部分:

1
2
3
4
5
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}

设定盒子的最大/最小宽高

min-width,max-width,min-height,max-height属性可以设定元素的最大/最小宽高。

设置元素的宽高可以使用数值,也可以设置百分比,百分比会按照元素父元素的宽高来计算元素的对应宽高。

内容溢出

当盒子内放置的内容超出盒子大小时,就会溢出。我们使用overflow来控制这种情况:

  • overflow: auto 当内容过多时,溢出内容被隐藏,使用滚动条来滚动查看所有内容
  • overflow: hidden 溢出内容被隐藏
  • overflow: visible 溢出内容显示在盒子外面(默认行为)

image-20180910154720272

CSS盒子类型

块级盒子(Block box)

可以堆放在其他盒子上的盒子(内容会单独占一行),可以设置宽高

行内盒子(inline box)

  • 多个行内元素在一排时,会出现在一行
  • 对行内盒子设置宽高无效
  • padding,margin横向有效,垂直方向无效
  • 行内盒子的高度可以通过line-height来设置

行内块级盒子(inline-block box)

  • 会像行内盒子一样,和其他行内盒子出现在一行
  • 但是不会像行内盒子那样出现断行,也就是说,如果一行剩下的空间不够行内块级盒子放下全部内容,那么它会在新的一行开始内容
  • 可以像块级盒子一样设置宽高

BFC

BFC(Block Formatting Context),即“块级格式化上下文”。它是页面中CSS渲染的一部分,在布局过程中生成块级盒子的区域。它像一个隔离的独立容器,容器里面的子元素不会影响到外面元素。容器内的长度大于容器长度时,会出现内部滚动,但是滚动不会影响父容器之外的布局。

触发条件

  • 根元素本身就是BFC

  • float值不为none

  • overflow值不为visible

  • display值为inline-block,table-cell,table-caption

  • position值为absolutefixed

应用场景

自适应两栏布局

通常文本会围绕浮动元素,但有些时候,我们并不希望发生这样的情况:

image-20180910171859165

我们想要Figure2的样式,

我们将元素内容列出来:

1
2
3
4
5
6
<div class="container">
<img src="url" />
<p>
...... a lot of text
</p>
</div>
1
2
3
4
5
6
7
.container {
background-color: lightgreen;
overflow: hidden;
}
img {
float: left;
}

image-20180910172715934

但我们注意看W3C给BFC的规范:

In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).

在BFC中,每一个盒子的左边外部边缘会挨着父容器的左边缘(如果是从右向左排版,则盒子右边缘挨着父容器的右边缘)。即使是浮动布局的情况下,这一点也不会改变(尽管父容器的子元素可能会因为浮动而尺寸缩小)。除非子元素创建一个新的BFC,这样它也会因为浮动布局而变窄。

也就是说,如果我们希望p元素不要围绕图片,那么可以通过给p建立一个BFC来实现。

1
2
3
p {
overflow: hidden;
}

image-20180910173444021

清除内部浮动

我们经常会遇到容器里面是浮动元素,于是容器的高度就塌陷到0的情况。

1
2
3
4
<div class="container">
<div>Sibling</div>
<div>Sibling</div>
</div>
1
2
3
4
5
6
7
8
.container {
background-color: red;
}
.container div {
float: left;
background-color: lightgreen;
margin: 10px;
}

image-20180910171545341

页面中只有两个孤独的div漂浮。.container因为没有高度,并不会显示出来。通常我们会设置一个空的伪元素去把容器敞开,但利用BFC,我们能更容易地处理这个情况。

1
2
3
4
5
6
7
8
9
.container {
background-color: red;
overflow: hidden;
}
.container div {
float: left;
background-color: lightgreen;
margin: 10px;
}

image-20180910171744389

防止垂直的margin重叠
1
2
3
4
5
<div class="container">
<p>Sibling 1</p>
<p>Sibling 2</p>
<p>Sibling 3</p>
</div>

我们创建一个div,中间包含3个p元素,此时如果给p元素设定margin值,上下相邻的两个margin是会塌陷的。

1
2
3
4
5
6
7
8
.container {
background-color: red;
overflow: hidden;
}
p {
background-color: lightgreen;
margin: 10px 0;
}

image-20180910170359549

此时p元素之间的margin值是10px,而并不是20px

image-20180910170743174

如果我们还记得根元素整体也是一个BFC,那么我们就能理解,同一个BFC中是会发生margin collapse的,要想解决它,需要让元素属于不同的BFC。所以我们要建立一个新的BFC。

1
2
3
4
5
6
7
<div class="container">
<p>Sibling 1</p>
<p>Sibling 2</p>
<div class="newBFC">
<p>Sibling 3</p>
</div>
</div>

给新的BFC也设置overflow

1
2
3
4
5
6
7
8
9
10
11
.container {
background-color: red;
overflow: hidden;
}
p {
background-color: lightgreen;
margin: 10px 0;
}
.newBFC {
overflow: hidden;
}

image-20180910171124209

通过设置元素在不同的BFC中避免了垂直方向的margin collapse