深刻理解css盒子模型

css是一门具象语言,并不像js那样具备逻辑性,所以,就算入行了前端好久的工程师,也以为css难以掌握。下面咱们就一步一步揭开css的神秘面纱,深刻理解css盒模型,这对咱们在布局上会有一个质的提高。css

盒子模型

图片描述
相信不少人对这幅图都不陌生,盒子模型简单点理解就是外边距(margin)+边框(border)+内边距(padding)+内容(content),页面所呈现的效果其实就是一个个盒子堆叠而成的。每个元素实际上是包含了一个“外在盒子”和一个“内在盒子”,其中“外在盒子”负责元素是一行显示仍是换行显示,而“内在盒子”则负责宽高、内容展示。咱们都知道inline-block(inline对应于“外在盒子”,block对应于“内在盒子”),而block能够简单地理解为block-block,table为block-table(由于还有一个inline-table)。html

内联盒模型

  • 内容区域(content area)
  • 内联盒子(inline box)
  • 行框盒子(line box)
  • 包含盒子(containing box)

内容区域(content area)。内容区域指的是一种围绕文字看不见的盒子,其大小仅受字符自己特性控制,本质上是一个字符盒子(character box);可是图片这样的替换元素,其显示内容不是文字,所以内容区域能够当作是元素自身。 前端

内联盒子(inline box)。“内联盒子”不会让内容成块显示,而是排成一行,这里的内联盒子指的是元素的“外在盒子”,用来决定元素是内联仍是块级。该盒子又能够细分为“内联盒子”和“匿名内联盒子”。以下:
图片描述css3

行框盒子(line box)。每一行就是一个行框盒子,每一个行框盒子都是由一个个内联盒子组成,注意:line-height是做用在行框盒子上的,并最终决定高度(替换元素除外,后面会讲解什么是替换元素)。canvas

包含盒子(containing box)。此盒子由一行一行的“行框盒子”组成(css规范中,并无“包含盒子”的说法,更准确的称呼是“包含块”(containing block)。浏览器

width

width的默认值是auto,但不少人却都不理解这个值是什么意思,由于auto在不一样场景会有不一样的表现:ide

  • fill-available
  • fit-content
  • min-content
  • max-content

fill-available:充分利用可用空间,例如div、p这些元素的宽度是默认100%于父级容器的。可是width: auto却不一样于width: 100%,这是不少人不理解的地方。若是你设置了width: 100%,这里指的是内容区域100%,即css3中的content-box,这时若是你设置了padding、border或者margin,元素都会撑破父元素,从而破坏布局。你固然能够设置box-sizing: border-box,但惋惜的是css3中没有margin-box,这时候你若是设置了margin,依然会撑破父元素,可是width: auto却不会,以下所示:布局

图片描述

图片描述

fit-content:收缩到合适,典型表明浮动、绝对定位(有例外,设置了对立属性:left、right、top、bottom时,宽度和高度由祖先元素position非static的元素决定,可是替换元素除外:img、video、canvas等)、inline-block、table。利用这个特性咱们能够实现,文字总体居中,多行则居左显示,以下:字体

图片描述

图片描述

图片描述

min-content:收缩到最小。在表格中最多见,当每一列空间都不够的时候,文字能断则断,中文随便断,英文单词不能断。能够根据这个特性实现凹凸图形等效果,以下:spa

图片描述

图片描述

图片描述

max-content:超出容器限制,内容很长的连续英文或数字,或者内联元素被设置为了white-space: nowrap。

图片描述

图片描述

图片描述

height

height的默认值也是auto,指的是其高度由内部元素堆叠而成,内部元素盒子有多高,元素就有多高。但在绝对定位中,若同时设置了top与bottom,则其高度由父盒子高度减去top与bottom。

height: 100%。若是父元素height为auto,则子元素height:100%是无效的,要想子元素height: 100%生效,则:

  • 父元素设定显式高度值
  • 使用绝对定位(绝对定位元素的百分比是根据padding box计算的,非绝对定位元素百分比是根据content box计算的)

替换元素

因为替换元素在不少表现上都与普通内联元素不同,所以在这里着重介绍一下替换元素。

  • 根据“外在盒子”是内联仍是块级,咱们把元素分为内联元素和块级元素,而根据内容是否可替换,咱们把元素分为可替换元素和非替换元素。
  • <img>,<video>,<canvas>,<input>,<textarea>,<iframe>都是替换元素。
  • 替换元素外观不受页面css的影响,有本身的尺寸,通常为300 * 150,在不少css属性上有本身的一套表现规则,例如vertical-align默认就是元素下边缘对齐,而不是基线对齐。
  • 替换元素尺寸计算规则:css尺寸 > html尺寸 > 固有尺寸
  • 内联替换元素和块级替换元素规则一致,即display: block,其宽度也不会100%。
  • 替换元素固有尺寸没法更改,width和height改变的是content-box的宽高,而默认替换元素的object-fit是fill,也就是会填充content-box,所以看上去像是改变了固有尺寸。
  • 替换元素before和after伪元素无效。

padding

  • padding与内联元素
  • padding的百分比值

padding与内联元素。padding做用在块级元素上会影响盒子的宽高,可是若是做用在内联元素上(不包括替换元素),彷佛就只能做用在水平方向上,垂直方向上就没看到任何影响。但事实并非没有影响,只是视觉上咱们以为没有影响而已。由于内联元素没有可视宽度和可视高度的说法(clientWidth和clientHeight永远是0),垂直方向彻底受line-height和vertical-align的影响,视觉上并无改变上一行和下一行内容的间距,所以,给咱们的感受就是垂直方向上padding没有起做用。利用这个特性,咱们能够在垂直方向上增大可点击区域,这样既不会破坏现有布局,也能很好地响应用户的点击。特别是在移动端,一个关闭的“x”若是过小,用户就很难点击到,调大字体又会影响布局,这时候就能够用到padding。

padding的百分比值。padding不支持负值,padding百分比不管宽高都是相对于width来讲的,另外padding区域是跟着行框盒子走的。所以,若是padding做用于内联元素,则宽度和高度细节有差别,而且padding会断行,其缘由在于strut,意思是说每个行框盒子前面都有一个不可见的盒子,其line-height和font-size都继承于父元素,称为strut。利用padding的这些特性,咱们能够实现以下效果:

  • 利用padding实现一个正方形

图片描述

图片描述

图片描述

  • 内联元素padding高度差别(只需把font-size设为0便可变为正方形)

图片描述

图片描述

图片描述

  • padding断行(因为padding做用在行框盒子上,所以文字换行,padding也跟着换行,后面的背景盖住了前面的,就造成了这种效果)

图片描述

图片描述

margin

  • margin: auto
  • margin改变元素尺寸
  • margin负值
  • margin合并
  • margin无效的状况

margin: auto生效的前提是元素在width和height为auto的时候可以自动填充容器,这样,在设置width或height的值时,若是还有剩余尺寸,margin: auto就能够利用剩余尺寸。所以在绝对定位元素设置了top、bottom、left、right的状况下,就能够很方便地实现水平垂直居中,以下:

图片描述

图片描述

图片描述

margin改变元素尺寸。在元素width为auto的状况下,margin正值和负值都能改变元素的尺寸。以下:

图片描述

图片描述

图片描述

margin负值。margin支持负值,而且用途十分普遍,例如,在等宽的盒子中,最后一个元素不因margin-right而折行;实现等高布局等。以下:

盒子并列占满父元素:

图片描述

图片描述

图片描述

图片描述

等高布局,其原理是利用padding撑开一片足够大的高度,再用margin负值将顶下去的元素收回来:

图片描述

图片描述

图片描述

margin合并。块级元素的上外边距与下外边距有时会合并为单个外边距,这种现象称为“margin合并”。通常会有如下三种:

一、相邻兄弟元素margin合并

二、父级和第一个/最后一个子元素合并

margin-top合并,解决方案:

    父元素设置为块状格式化上下文元素
    父元素设置border-top值
    父元素设置padding-top值
    父元素和第一个子元素之间添加内联元素进行分隔

margin-bottom合并,解决方案:

    父元素设置为块状格式化上下文元素
    父元素设置border-bottom值
    父元素设置padding-bottom值
    父元素和最后一个子元素之间添加内联元素进行分隔
    父元素设置 height、min-height 或 max-height。

三、空块级元素的margin合并,即自身有margin-top和margin-bottom,但元素是空的,此时会合并为一个margin。

margin无效。margin在某些场景下会失效,但有些“失效”只是视觉上的表现而已。以下:

  • display 计算值 inline 的非替换元素的垂直 margin 是无效的,虽然规范提到有 渲染,但浏览器表现却未寻得一点踪影,这和 padding 是有明显区别的。对于内联替换元素, 垂直 margin 有效,而且没有 margin 合并的问题,因此图片永远不会发生 margin 合并。
  • 表格中的<tr>和<td>元素或者设置 display 计算值是 table-cell 或 table-row 的元素的 margin 都是无效的。可是,若是计算值是 table-caption、table 或者 inline-table 则没有此问题,能够经过 margin 控制外间距,甚至::first-letter 伪元素也能够解析 margin。
  • margin合并的时候,更改margin值可能无效。由于垂直方向上会发生margin合并。
  • 绝对定位元素非定位方位的margin值“无效”(其实margin是有效的,只是元素绝对定位了,并不影响其相邻元素的渲染)。
  • 定高容器的子元素的margin-bottom或者宽度定死的子元素的margin-right的定位“失效”。这里的失效也是假的,缘由跟绝对定位的margin无效相似,在一个默认流下,其定位方向是左侧和上方,此时只有margin-left和margin-top能够影响其定位,而margin-right和margin-bottom则只会影响其相邻元素,若此时没有相邻元素,则看上去像是margin无效。
  • 内联特性致使的margin值无效。一个div元素中有一个img图片,咱们对img使用margin-top负值,当margin-top负值达到必定值的时候,再往上图片也不会上移。

border

  • 制做图形
  • 等高布局

相信很多同窗都使用过border来制做图形,例如三角形、圆形等等,此处就不举例子,主要讲讲等高布局,代码和效果以下所示:

图片描述

图片描述

图片描述

其原理就是父元素撑开一个border-left,菜单栏左浮动,而且宽度跟父元素border保持一致,经过margin-left负值往左偏移到border位置,另外父元素设置伪元素after来清除浮动,这样就能够实现左侧固定,右侧自适应的两栏等高布局。

参考资料:《CSS世界》

相关文章
相关标签/搜索