框架
基本概念
CSS 框模型实质上是一个包围每个 HTML 元素的框
标准模型和ie模型的区别是计算宽width高height的不同。
标准模型width不计算padding和border;
ie模型width计算padding 和border;
标准盒模型(W3C)
设置的宽高是对实际内容content的宽高进行设置,内容周围的border和padding另外设置;
即元素实际的宽高为:
width【height】= 设置的content的宽【高】 + padding + border
IE盒模型(怪异)
设置的宽高是对实际内容content + 内边距(padding)+边框(border)之和的width和height进行设置的;
总之就是:
标准模型的宽高为content的宽高
IE模型的宽高包括border
标准模型:box-sizing:content-box
IE模型:box-sizing:border-box
相关规则
块级元素
在块级元素的水平七属性中,只有margin和width可以使用auto的值
也就是说,只有margin-left、width和margin-right这三个属性可以使用auto值。这正是此处要讨论的核心问题,即在上述三个属性分别取不同的auto值和长度值,形成不同组合的情况下,相应块级元素盒子中各部分的宽度是如何确定的?如图
总结:
在width属性的值设置成auto的情况下,块级元素内容区的宽度取决于左右外边距是否明确设置了值。如果左右外边距值都是auto,则左右外边距的值都会被重置为默认的值0;如果左右外边距中只有一个值是auto,则该值被重置为0,另一个值有效;如果左右外边距都设置了明确的值,两个值都将有效,此时元素内容区的宽度就是父元素的宽度减去左右外边距后的值。需要说明的是,左右外边距的默认值是0,这意味着如果没有在CSS规则中声明margin-left或者margin-right,它们就会使用默认值0。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
在width属性的值设置为大于0的值的情况下,块级元素内容区的宽度就是由width属性设置的值。此时,左右外边距的值如果都是auto,则会使块级元素在其父元素中居中;如果左右外边距中只有一个值是auto,则明确设置的值有效,auto值会自动适应剩余的宽度;如果左右外边距都设置了明确的值,那么在从左往右阅读的语言中,会把右外边距的值重置为auto。
行内元素
行内元素的例子有a、img、span、input等。对于行内元素,又可以进一步分为可替换行内元素和不可替换行内元素,两者的区别在于元素中所包含的内容是否直接显示在页面中。
不可替换的行内元素,如a元素中的链接文本会直接显示在网页中;而可替换的行内元素,如img,当它在网页中显示时会被其src属性指向的图像替代,还有input , textarea , select , object,。
行内元素设置width, height无效(对于行内非替换元素来说)。行内元素不能包含块级元素
对于大部分行内元素都是不可替换元素,因此针对这部分元素有以下特性:
对于padding和margin:
上下margin无效
上下padding不正常
上边说有也有 但是很明显有bug
下边框确实有,但是只是扩大的范围而为扩大盒子本身大小,可以看到把下边的元素覆盖了一部分。
行内可替换元素
有些资料也把这些元素称为行内块元素
他们可以设置宽高 padding margin也是正常的
JS如何设置/获取盒模型对应的宽高
dom.style.width/height:内联样式的宽高
dom.currentStyle.width/height:渲染后的最终宽高(IE)
window.getComputedStyle(dom).width/height:DOM标准,不支持IE
dom.getBoundingClientRect().width/height:计算元素的绝对位置(视窗左顶点为起点,含left/right/height/width)
dom.offsetWidth/offsetHeight【常用】
dom.style.width/height
通过style样式获取,只能取到行内样式的宽和高,style 标签中和 link 外链的样式取不到
element.style.xxx 这种只能取得内嵌样式的属性,获取样式能读能写
dom.currentStyle.width/height
取到的是最终渲染后的宽和高,如果有设置宽高,则不论哪种盒模型获取到的都是设置的宽高,只有IE兼容
element.currentStyle[xxx] 可以取得内部和外部样式,但是只兼容ie浏览器,获取的样式只能读
document.getComputedStyle(dom,null).width/height
取到的是最终渲染后的宽和高,如果有设置宽高,则不论哪种盒模型获取到的都是设置的宽高,和currentStyle相同,但是兼容性更好,IE9 以上支持。
getComputedStyle()方法,
第一个参数:取得计算样式的元素;
第二个参数:一个伪元素字符串(例如“:after”),如果不需要伪元素信息,默认为null;
eg:
let targetDom = document.querySelector('.box');
let width = window.getComputedStyle(targetDom).width
let height = window.getComputedStyle(targetDom).height
console.log("width",width)
console.log("height",height)
如果没有设置宽高而是由内容自动撑开,那么获取到的宽高是其设置宽高的实际意义
则标准盒模型通过getComputedStyle获取到的宽高是content的值;
IE盒模型通过getComputedStyle获取到的宽高 = border + padding + content,不包括外边距;
dom.getBoundingClientRect().width/height
得到渲染后的宽和高,大多浏览器支持。IE9以上支持。
获取的都是content +padding+border的值
这个方法还可以获取到相对于视窗的位置集合
dom.offsetWidth/offsetHeight(常用)
同前一个API,获取到的都content +padding+border的值,兼容性最好
关于边距重叠
外边距重叠是指两个【垂直】 【相邻】的块级元素,当上下两个边距相遇时,其外边距会产生重叠现象,且重叠后的外边距,等于其中较大者。(水平方向不会发生)
解决边距重叠
嵌套带来的外边距合并
对于两个嵌套关系的块元素,如果父元素没有padding-top及border,则父元素的margin-top会与子元素的margin-top发生合并,合并后的外边距为两者中的较大者,父级与外面的间隔变成了该数据
法1,2,3
法4:
.parent-box::before {
content : "";
display :table;
}
兄弟元素垂直外边距坍塌
margin-bottom与margin-top之和,而是两者中的较大者
下面的BFC解决
两个inline-block并排造成的边距影响
input没加margin或者margin不够大:
但是当margin足够大时就会携带者img一起走
原因:
内联元素的默认垂真对齐方式是和基线对齐并不是和底部对齐,即默认vertical-align:baseline。
解决:
vertical-align的值设置为top(当然会改变布局 所以margin需要重新计算)
ps:水平方向上两个行内元素之间有空隙是因为html标签之间有空格,解决办法:
html不换行(不太行)
设置父元素的font-size为0,然后再单独设置需要写文字元素的font-size
BFC
块级格式化上下文
如何开启
- float不为none
- overflow的值不为visible
- display的值为inline-block、table-cell、table-caption
- position不为static/relative
- 根元素
布局规则
(黄色标记的用于下方的应用)
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
- BFC的区域不会与float box重叠
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此
- 计算BFC的高度时,浮动元素也参与计算
应用
自适应两栏布局
<style>
body {
width: 300px;
position: relative;
}
.aside {
width: 100px;
height: 150px;
float: left;
background: #f66;
}
.main {
height: 200px;
background: #fcc;
}
</style>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
.main {
overflow: hidden;
}
根据 BFC的区域不会与float box重叠 ,所以可以触发main生成BFC实现自适应两栏布局
原本:
开启BFC后:
新的BFC不会与浮动的aside重叠。因此会根据包含块的宽度,和aside的宽度,自动变窄
防止垂直margin重叠
由于属于同一个BFC的两个相邻Box的margin会发生重叠
因此只要两个元素不属于同一个BFC即可
那么就可以在其中一个盒子的外面再包裹一个父盒子,在父盒子上开启BFC。这里容易直接在原本的盒子上开启BFC,但我是这样理解的,根据
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素
原本的元素不过是变成了这个容器而已,它本身仍和另外一个元素处于同一个BFC容器里,所以要清除margin带来的影响,还是需要使两个元素不属于同一个BFC。
清除内部浮动
清除内部浮动,则把装浮动元素的容器开启BFC即可
因为计算BFC的高度时,浮动元素也参与计算
最后 关于DOCTYPE
我们在编写页面代码时应尽量使用标准的W3C模型(需在页面中声明DOCTYPE类型),这样可以避免多个浏览器对同一页面的不兼容。
因为若不声明DOCTYPE类型,IE浏览器会将盒子模型解释为IE盒子模型,FireFox等会将其解释为W3C盒子模型;若在页面中声明了DOCTYPE类型,所有的浏览器都会把盒模型解释为W3C盒模型。
参考:
W3C规范
CSS盒模型的面试六问你能答出几个?
前端面试2:CSS盒模型
CSS盒模型详解
透彻理解块级元素的宽度
简要剖析CSS之vertical-align