作者: 倪志航 时间: 2020-11-23
盒模型是 css 布局的基础,浏览器在渲染一个元素时会根据盒模型将元素表示为一个矩形盒子,而这个盒子由四部分组成,从内到外依次是:
盒子模型目前可分为两种,标准盒子模型(W3C 标准)和 IE 盒子模型(怪异模式)。
标准盒子模型(W3C 标准):
图中可以很明显看出标准盒子模型的 width、height 只由 content 的大小,在宽高固定改变 padding、border 会影响盒子大小。
盒总宽/高度 = width/height + padding + border + margin;
IE 盒子模型(怪异模式):
图中可以很明显看出 IE 盒子模型的 width、height 是由 content+padding+border 共同决定,也就是宽高固定下,改变 padding、border 不会改变盒子大小。
盒总宽/高度 = width/height + margin = 内容宽/高度 + padding + border + margin;
自定义盒模型:
如果是定义了完整的 doctype 的标准文档类型,无论是哪种模型情况,最终都会触发标准模式,否则 doctype 协议缺失,会由浏览器自己决定,在 IE 浏览器中 IE9 以下(IE6.IE7.IE8)的版本触发怪异模式,其他浏览器中会默认为 W3c 标准模式。
通过box-sizing
属性我们可以自定义盒子类型:
/** (W3C标准盒模型)**/
box-sizing: content-box;(默认值)
/**(IE盒子模型——怪异盒模型)**/
box-sizing: border-box
/** 规定应从父元素继承 box-sizing 属性的值。**/
box-sizing: inherit;
两种盒模型的优缺点:
同时设置了两个子元素宽度都是父元素的 50%;当想在子元素内加 padding 或者 border 时,标准模型盒子的实际宽度就会超过 50%,导致换行。如果强行想让子元素在同一行内,就不能设置宽度为 50%,而应该通过计算 width:cacl(50% - 2 _ padding - 2 _ border);
而对于 IE 盒模型,内容的宽度会根据 padding 和 border 进行调整,元素的真实宽度始终是 50%,所以不会导致换行。但是这样的处理方式可能就会导致 content 区域内的元素布局发生改变。所以需要根据具体需求采用不同方式。
视觉格式化模型是用来处理和在视觉媒体上显示文档时使用的计算规则.
视觉格式化模型会根据 CSS 盒子模型将文档中的元素转换为一个个盒子,每个盒子的布局由以下因素决定:
视觉格式化模型会根据盒子的包含块的边界来渲染盒子.盒子会创建一个包含其后代元素的包含块,但盒子并不由包含块所限制,当盒子的布局跑到包含块外面时称为溢出.
常见名词定义: 块: block,一个抽象的概念,一个块在文档流上占据一个独立的区域,块与块之间在垂直方向上按照顺序依次堆叠. 包含块:containing block,包含其他盒子的块称为包含块,一般来说盒子生成的块就是盒子子元素的包含块. 块级元素: Block-level elements,元素的 display 为 block、list-item、table 时,该元素将成为块级元素.视觉上呈现为块,竖直排列.每个块级元素生成一个主要的块级盒来包含后代盒和生成的内容,并参与定位. 块级盒: Block-level box, 由块级元素生成,参数块级格式化上下文(BFC).描述元素和它的父元素与兄弟元素之间的表现. 块容器盒: Block container box, 只包含其他块级盒,或生成一个行内格式化上下文(IFC),只包含行内盒.描述元素和它后代之间的关系. 块盒: Block boxes, 同时是块容器盒的块级盒. 匿名块盒: Anonymous block boxes, 没有名字,不能被 css 选择符选中.块容器盒只包含块级盒或者行内盒,当两者都存在时,将会创建匿名块盒来包含相邻的行内盒. 行内级元素:inline-level element,display 为 inline、inline-block、inline-table 的元素称为行内级元素。 行内级盒: inline-level boxes, 由行内级元素生成,参与行内格式化上下文的创建. 行内盒:inline box, 一个其内容会参与创建其容器的行内格式化上下文的行内级盒子. 原子行内级盒子:atomic inline-level box, 内容不参与行内格式化上下文创建的行内级盒子,在同一个 IFC 中,原子行内级盒子不能被拆分成多行 匿名行内盒:类似于块盒子,CSS 引擎有时候也会自动创建一些行内盒子。这些行内盒子无法被选择符选中,因此是匿名的,它们从父元素那里继承那些可继承的属性,其他属性保持默认值 initial.
块级元素有着盒子模型的结构,而且独占一行
不独占一行,所占空间由元素内容(字体大小,图像尺寸)决定,不能设置宽高,对齐
所有内联元素的样式表现都与行内框盒子模型有关。所以这个概念是非常重要的。
<p>这是一段文字,这里有个<em>em</em> 标签。</p>
如上面一段普普通通的代码,却包含了4种盒子
“内容区域”(content area),是一种围绕文字看不见的盒子,可理解为选中文字蓝色背景区域,如图“内容区域”的大小与 font-size 大小、font-family 相关;
“内联盒子”(inline-boxes),“内联盒子”不会让内容成块显示,而是排成一行。如果文字外部含 inline 水平的标签(如 span,a,em 等),则属于“内联盒子”,如下图 em 框处。如果是光秃秃的文字,则属于“匿名内联盒子”,如下图框处;
“行框盒子”(line boxes),每一行就是一个“行框盒子”,每个“行框盒子”又是由一个一个“内联盒子”组成,“行框盒子”如下图红框处;
标签所在的“包含盒子”(containing box),如下图红框处。此盒子由一行一行的“行框盒子”组成
Element.clientWidth
内联元素以及没有 CSS 样式的元素的 clientWidth
属性值为 0。Element.clientWidth
属性表示元素的内部宽度,以像素计。该属性包括内边距 padding,但不包括边框 border、外边距 margin 和垂直滚动条(如果有的话)。clientWidth
是只读的。
Element.clientHeight
内联布局盒子或者没有 CSS 样式的元素属性值为 0,否则,Element.clientHeight
属性表示元素的内部高度,以像素计。该属性包含内边距,但不包括水平滚动条、边框和外边距。clientHeight
是只读的。
可以通过 CSS height
+ CSS padding
- 水平滚动条高度 (如果存在)来计算
Element.clientTop
一个元素顶部边框的宽度(以像素表示)。不包括顶部外边距或内边距。clientTop
是只读的。
Element.clientLeft
一个元素的左边框的宽度,以像素表示。如果元素的文本方向是从右向左(RTL, right-to-left),并且由于内容溢出导致左边出现了一个垂直滚动条,则该属性包括滚动条的宽度。clientLeft
不包括左外边距和左内边距。clientLeft
是只读的。
Element.getBoundingClientRect()
方法返回元素的大小及其相对于视口的位置,返回 DOMRect 对象。
Element.getClientRects()
方法返回一个指向客户端中每一个盒子的边界矩形的矩形集合,返回 DOMRectList 为 DOMRect 对象的数组。
如果是标准盒子模型,元素的尺寸等于width/height
+ padding
+ border-width
的总和。如果box-sizing: border-box
,元素的的尺寸等于 width/height
。
返回结果DOMRect属性值为:
bottom: 距离窗口底部距离
height: 当前元素高度
left: 距离窗口左侧距离
right: 距离窗口右侧距离
top: 距离窗口底部距离
width: 当前元素宽度
x: 原点的x坐标
y: 原点的y坐标
Window.getComputedStyle()
方法返回一个对象,该对象在应用活动样式表并解析这些值可能包含的任何基本计算后报告元素的所有 CSS 属性的值。 私有的 CSS 属性值可以通过对象提供的 API 或通过简单地使用 CSS 属性名称进行索引来访问。
// 进行样式的获取
let style = window.getComputedStyle(element, [pseudoElt]);
// 获取样式相对位置左偏移
const left = style.left;
// 获取样式相对位置上偏移
const top = style.top;
// 获取样式宽度
const width = style.width;
// 获取到样式高度
const height = style.height;
element
用于获取计算样式的Element
。
pseudoElt 可选
指定一个要匹配的伪元素的字符串。必须对普通元素省略(或null
)。
描述
返回的对象与从元素的 style
属性返回的对象具有相同的类型;然而,两个对象具有不同的目的。从getComputedStyle
返回的对象是只读的,可以用于检查元素的样式(包括由一个<style>
元素或一个外部样式表设置的那些样式)。elt.style
对象应用于在特定元素上设置样式。