nicepainkiller 2019-06-28
本文将从盒模型开始,一步步涉及一些常见的前端笔试和面试点
主要参考自第一篇文章,然而笔者在读的时候未觉详尽,便又去网上查阅了一番,扩充了其内容,希望也能给同学们提供一些参考。
下面本文章将会从以下几个方面谈谈盒模型。
- 基本概念:标准模式和怪异模式,标准模型和IE模型
- CSS如何设置这两种模型
- JS如何设置获取盒模型对应的宽和高
- 实例题(根据盒模型解释边距重叠)
- BFC(边距重叠解决方案)
2018搜狐前端笔试题
盒模型本质上是用以封装HTML元素的概念盒子,它包含了边距,边框,填充以及实际内容。
即由外向里是 margin, border, padding, content
在了解两种不同的盒模型之前,需要先了解一下为什么会产生两种不同的盒模型。
当年,Netscape4(译注:网景公司早期的浏览器)和IE4(微软公司早期的浏览器)实现CSS机制时,并没有遵循W3C提出的标准。Netscape4 提供了糟糕的支持,而IE4 虽然接近标准,但依旧未能完全正确的支持标准。尽管IE 5 修复了IE4 许多的问题(bugs),但是依然延续CSS实现中的其它故障(主要是盒模型(box model)问题)。
然而随着标准一致性变得越来越重要,浏览器开发商不得不面临一个艰难的抉择:逐渐遵循W3C的标准是前进的方向。但是改变现有CSS的实现,完整去遵循标准,会使许多网站或多或少受到破坏。如果浏览器突然以正确的方式解析现存的CSS,陈旧的网站显示必然受到影响。
于是,所有的浏览器开始提供两种模式:怪异模式(即兼容模式 Quirks Mode/Compalibility Mode)
服务于旧式规则,严格模式(即标准模式 Standard Mode/Strict Mode)
服务于标准规则。Mac平台的IE浏览器最先实现这两种模式,Mozilla, Safari、Opera和Windows平台的IE6也相继实现了这两种模式。Windows平台的IE5和Netscape4则只提供了怪异模式。
选择使用哪种模式需要一个触发器,而 “DOCTYP切换” 则用于此目的。依照标准,任何一个(X)HTML文档必须拥有一个DOCTYPE(译注:DTD(文档类型定义)是一组机器可读的规则,它们指示(X)HTML文档中允许有什么,不允许有什么,DOCTYPE正是用来告诉浏览器使用哪种DTD,一般放在(X)HTML文档开头声明)用以告诉其他人这个文档的类型风格
所有IE的触发 —— 在DTD声明前加上HTML注释
<!--Let IE into quirks mode--> 只要在DTD声明前加注释或者任何标签即可
<!DOCTYPE html>xml
对于以上两种不同的网页模式,产生了两种不同的盒模型,一个是标准模型
,一个是IE模型
。
标准模型的宽高 = 内容(content)的宽高,
IE盒模型的宽高 = 内容(content) + 填充(padding) + 边框(border)的总宽高。
这里用到了 CSS3
的属性 box-sizing
标准模型
box-sizing:content-box;
IE模型
box-sizing:border-box;
通过JS获取盒模型对应的宽和高,有以下几种方法:
为了方便书写,以下用dom来表示获取的HTML的节点。
<div class="container"> <div id="contentBox" class="contentBox"></div> </div> var body = document.getElementsByClassName('container'); var dom = document.getElementById('contentBox');
这种方式只能取到dom元素内联样式所设置的宽高,也就是说如果该节点的样式是在style标签中或外联的CSS文件中设置的话,通过这种方法是获取不到dom的宽高的。
<div id="contentBox" class="contentBox" style="width: 100px;"></div> console.log('Dom.style.width:' + dom.style.width); //100px
这种方式获取的是在页面渲染完成后的结果,就是说不管是哪种方式设置的样式,都能获取到,但这种方式只有IE浏览器支持。
console.log('Dom.currentStyle.width:' + dom.currentStyle.width); //Cannot read property 'width' of undefined
这种方式的原理和2是一样的,这个可以兼容更多的浏览器,通用性好一些。
console.log('Window.getComputedStyle(dom).width' + window.getComputedStyle(dom).width); //100px
getBoundingClientRect 用于获取某个元素相对于视窗的位置集合
通过计算元素的位置,来获取对应的宽高
console.log('Dom.getBoundingClientRect().width: ' + dom.getBoundingClientRect().width); //160
对象所在元素的实际宽度
console.log('Dom.offsetWidth: ' + dom.offsetWidth); //160
具体情况如图所示
其中,盒模型为标准模型,元素内容宽度为100px, padding宽度为10px,border宽度为20px, margin宽度为30px
OffsetWidth 对象所在元素的实际宽度
dom.offsetWidth = dom_content + padding + border(包含滚动条)+ margin
ClientWidth 对象内容的可视区域的宽度
dom.clientWidth = dom_content + padding(不包含滚动条)
ScrollWidth 对象的实际内容的宽度(包含滚动区域中未显示完全的部分)
dom.scrollWidth = real_content + padding
什么是边距重叠
如下图,父元素没有设置margin-top,而子元素设置了margin-top:20px;可以看出,父元素也一起有了边距。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> *{ margin:0; padding:0; } .demo{ height:100px; background: #eee; } .parent{ height:200px; background: #88f; } .child{ height:100px; margin-top:20px; background: #0ff; width:200px; } </style> </head> <body> <section class="demo"> <h2>此部分是能更容易看出让下面的块的margin-top。</h2> </section> <section class = "parent"> <article class="child"> <h2>子元素</h2> margin-top:20px; </article> <h2>父元素</h2> 没有设置margin-top </section> </body> </html>
首先要明确BFC是什么意思,其全英文拼写为 Block Formatting Context 直译为“块级格式化上下文”
<div class="container"> <div class="backgroundDom"> <div class="top"> Top margin-bottom: 30px</div> <div class="bottom"> Bottom margin-top: 50px</div> </div> </div> .top{ margin-bottom:30px; } .bottom{ margin-top: 50px; } .top, .bottom{ width: 100%; height: 100px; line-height: 100px; background: cornflowerblue; }
效果图
用BFC可以解决垂直margin重叠的问题
float: left; position: absolute;// 或者fixed
display: inline-block;
<div class="container"> <div class="backgroundDom"> <div class="top"> Top margin-bottom: 30px</div> <div style="overflow: hidden"> <div class="bottom"> Bottom margin-top: 50px</div> </div> </div> </div>
参考链接
- 《深入理解CSS盒模型》 https://www.cnblogs.com/cheng...
- 《怪异模式和严格模式》 http://blog.sina.com.cn/s/blo...
- 《标准模式与怪异模式的共存缘由及其使用》 https://blog.csdn.net/liyuans...
background-color: blue;background-color: yellow;<input type="button" value="变蓝" @click="changeColorT