box model应该是CSS当中最核心的概念之一了,本篇主要讲述CSS当中的box model(盒模型)。css
在看本篇内容以前,能够先本身回答下面几个问题:html
CSS2.1 specification 8.box model 第一句话就很好的描述了它的定义:react
The CSS box model describes the rectangular boxes that are generated for elements in the document tree and laid out according to the visual formatting model.浏览器
从这句话中咱们能够得出来box model
是什么: box model
是用来描述DOM树中元素生成的矩形盒子的,而且UAs会根据 visual formatting model
来布局这些盒子。bash
这一小节是用来描述具体的矩形盒子的,每一个盒子会有4块区域:布局
padding
, border
, margin
能够被分割成top, bottom, left, right
四个小区域,并由具体的属性来定义。下面咱们来引入新的名词(为了后面的内容),edge
: 每一个盒子的周长被称为edge
,即边界。相应的,咱们能够知道每一个box都会有四个edge
.flex
width
和 height
两个属性,元素的内容以及它的containing block决定Note: 一个box的content area, padding area 和 border area的 background样式由该元素的 background
属性决定。也就是说background
默认会一直延伸到 border area,而 margin老是透明的。在CSS3中,咱们可使用background新属性来修改默认状况。flexbox
CSS Box model 3 新增长一段: When a box fragments—is broken, as across lines or across pages, into separate box fragments—each of its boxes (content box, padding box, border box, margin box) also fragments. How the content/padding/border/margin areas react to fragmentation is specified in [css-break-3] and controlled by the box-decoration-break property.spa
这一段主要讲的是当一个盒子跨行或者跨页时会被分割成多个box片断,那么对于该盒子的content,padding,border,margin在不一样的box 片断中该如何表现?这些内容定义在css-break-3中,而且可使用box-decoration-break
来控制。 另外其实在CSS2.1也有描述这样的场景,在8.6中描述了inline box跨行时盒模型该如何表现。代理
margin-top
, margin-bottom
, margin-left
, margin-right
和 margin
这些属性都是初学时就已经用的很熟的。所以,这里只强调几个注意事项: 先看属性的定义
'margin-top', 'margin-bottom', 'margin-left', 'margin-right'
Value: `<margin-width>` | inherit
Initial: 0
Applies to: all elements except elements with table display types other than table-caption, table and inline-table
Inherited: no
Percentages: refer to width of containing block
Media: visual
Computed value: the percentage as specified or the absolute length
复制代码
value
能够是 <margin-width>
,包含3种具体的取值:
<length>
: 指定固定的宽度,好比3px
, 1em
等<percentage>
: 百分比取值在由computed value
转换成used value
的时候计算,基数是generated box's containing block
的width
(也就是该元素的包含块的width). 而若是containing block的width会依赖该元素,那么具体表如今CSS 2.1中未定义的。margin-top
和 margin-bottom
对于 non-replaced inline elements
不起做用。margin-block-start
,margin-block-end
(这些属性跟文档的writing mode
相关)。(logical margin和physical margin控制的是一样的margin区域,只是不一样的表现形式而已。CSS3加入这个特性是由于不一样国家的文档排列形式是不同的,好比阿拉伯语就是从右往左写的)Note: CSS3中添加的margin-trim
属性因为目前没有任何浏览器支持,这里不作介绍(当前时间为2019年2月)。
在CSS当中,2个或多个盒子相邻的垂直方向margins会合并成一个margin,这种合并被咱们称为collapse
(塌陷),而合并后的margin被叫作collapse margin
. 首先,咱们先强调一些margin不会合并的例外状况:
clear
属性致使元素位置移动产生的间隙)的元素的top margin和 bottom margin 存在相邻的margin,该元素的相关margin会和紧挨着的兄弟元素的相邻外边距合并,但合并后的外边距不会再和父级块的下外边距合并那么,如何判断两个盒子的margin是相邻的(adjoining)呢? 须要同时知足下面那几个条件:
block-level boxes
,而且处于同一个block formatting model
。line box
, clearance
, padding
, border
将它们间隔开(这里高度为0的line box
会被忽略)。in-flow
孩子节点的上外边距in-flow
中的兄弟节点的上外边距in-flow
孩子节点的下外边距block formatting model
,min-height
为0,height的computed value为0
或者auto
,没有in-flow
孩子节点。另外须要注意的是折叠外边距也可以与另外一个外边距相邻,只须要其外边距的任意一部分与另外一个外边距相邻就算。
Note:由上面的collapse margin 的定义咱们能够得出如下的推论:
floated box
的margin和任何其余盒子的margin都不会合并(包括它流内的孩子节点)- 由于 float box
不是流内的。block formatting context
的元素的margin不会与它的流内孩子节点的margin合并(好比floated box)inline-block
盒子的margin不会与其余盒子的margin合并(包括它的流内孩子节点)- 建立了新的block formatting model
而且不是block-level box
.in-flow block-level box
的下外边距会与相邻的in-flow block-level
兄弟节点的上外边距合并,除非该兄弟节点存在clearance
in-flow block element
的上外边距会与它的第一个流内孩子节点(该孩子节点是block-level
盒子)的上外边距合并,这里须要该元素不存在top border
,不存在top padding
,而且孩子节点也没有clearance
height
为auto
而且min-height
为0
的in-flow block-level box
的bottom margin
会与它的最后一个流内block-level
的孩子节点的bottom margin
合并,条件是该盒子没有bottom padding
,bottom border
而且其孩子节点的bottom margin
没有与具备clearance的top margin合并min-height
为0
, 既没有上下边框,也没有上下内边距,height为0或者auto,且不包含line box(而且全部流内孩子的外边距都会合并)那么合并后的margin该如何取值呢?
下面咱们讨论最后一种特殊状况: 若是一个盒子的上下外边距相邻,那么有可能外边距合并会穿透该盒子。在这种状况下,该元素的位置取决于合并margin的其余元素之间的关系:
须要注意的是,被折叠外边距穿过的元素的位置不影响其余外边距正要被合并的元素的位置,其上边框边界的位置仅仅是用于布局这些元素的后代元素。
padding-top
, padding-right
, padding-bottom
, padding-left
和 padding
padding属性定义了盒子的内边距区域的宽度。
'padding-top', 'padding-right', 'padding-bottom', 'padding-left'
Value: `<padding-width>` | inherit
Initial: 0
Applies to: 除table-row-group,table-header-group,table-footer-group,table-row,table-column-group和table-column外的全部元素
Inherited: no
Percentages: 参照包含块的宽度
Media: visual
Computed value: 指定的百分比或者绝对长度
复制代码
padding属性和margin属性主要由下面几个不一样:
auto
和margin同样的是,百分比的基数是generated box's containing block
的width
(也就是该元素的包含块的width).
note:这里的padding-top
等4个属性仍然是physical 属性。在CSS3当中添加了logical padding - padding-block-start
等。
'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width'
Value: `<border-width>` | inherit
Initial: medium
Applies to: 全部元素
Inherited: no
Percentages: N/A
Media: visual
Computed value: 绝对长度,或者'0',若是border style为'none'或者'hidden'的话
复制代码
对于border-width
须要注意:
<border-width>
只有关键字和<length>
这两种选择,关键字是thin
, medium
, thick
,大小依次变大,具体大小由用户代理决定'border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color'
Value: `<color>` | transparent | inherit
Initial: 'color'属性的值
Applies to: 全部元素
Inherited: no
Percentages: N/A
Media: visual
Computed value: 从'color'属性取值的话,取'color'的计算值,不然,就按指定值
复制代码
这里须要注意的是: border-color
的初始值是 color
属性的值,咱们有些时候能够利用这个特性来实现一些特殊的要求。
对于每个line box, UAs必须为每个元素产生的inline box渲染margin,border,padding以visual order的方式(而非logical order) 主要分为两种状况:
direction: ltr
: 元素出现的第一个line box的最左端生成的盒子具备左外边距,左边框,左内边距,而且元素出现的最后一个line box最右端生成的盒子具备右内边距,有边框,右外边距direction: rtl
:元素出现的第一个line box的最右端生成的盒子具备右内边距,有边框,右外边距,而且元素出现的最后一个line box的最左端生成的盒子具备左外边距,左边框,左内边距