深入理解CSS盒模型

 本文是学习中传思客在慕课网开的课程《前端跳槽面试必备技巧》的学习笔记。课程地址:https://coding.imooc.com/class/evaluation/129.html#Anchor

 如果你在面试的时候面试官让你谈谈对盒模型的理解,你是不是不知从何谈起。这种看似简单的题其实是最不好答的。

  下面本文章将会从以下几个方面谈谈盒模型。

  • 基本概念:标准模型 和 IE 模型
  • CSS 如何设置这两种模型
  • JS 如何设置获取盒模型对应的宽和高
  • 实例题(根据盒模型解释边距重叠)
  • BFC(边距重叠解决方案)

 

基本概念

盒模型的组成大家肯定都懂,由里向外 content,padding,border,margin.

盒模型是有两种标准的,一个是标准模型,一个是 IE 模型。

 

 从上面两图不难看出在标准模型中,盒模型的宽高只是内容(content)的宽高,

而在 IE 模型中盒模型的宽高是内容 (content)+ 填充(padding)+ 边框(border) 的总宽高。

 

css 如何设置两种模型

这里用到了 CSS3 的属性 box-sizing

/* 标准模型 */
box-sizing:content-box;

/IE 模型/
box-sizing:border-box;

 

JS 获取宽高

通过 JS 获取盒模型对应的宽和高,有以下几种方法:

为了方便书写,以下用 dom 来表示获取的 HTML 的节点。

1.  dom.style.width/height 

  这种方式只能取到 dom 元素内联样式所设置的宽高,也就是说如果该节点的样式是在 style 标签中或外联的 CSS 文件中设置的话,通过这种方法是获取不到 dom 的宽高的。

 2. dom.currentStyle.width/height 

  这种方式获取的是在页面渲染完成后的结果,就是说不管是哪种方式设置的样式,都能获取到。

  但这种方式只有 IE 浏览器支持。

 3. window.getComputedStyle(dom).width/height

  这种方式的原理和 2 是一样的,这个可以兼容更多的浏览器,通用性好一些。

 4. dom.getBoundingClientRect().width/height

  这种方式是根据元素在视窗中的绝对位置来获取宽高的

 5.dom.offsetWidth/offsetHeight

  这个就没什么好说的了,最常用的,也是兼容最好的。

 

边距重叠

什么是边距重叠

如下图,父元素没有设置 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)

首先要明确 BFC 是什么意思,其全英文拼写为 Block Formatting Context 直译为“块级格式化上下文”

BFC 的原理

  1. 内部的 box 会在垂直方向,一个接一个的放置
  2. 每个元素的 margin box 的左边,与包含块 border box 的左边相接触(对于从做往右的格式化,否则相反)
  3. box 垂直方向的距离由 margin 决定,属于同一个 bfc 的两个相邻 box 的 margin 会发生重叠
  4. bfc 的区域不会与浮动区域的 box 重叠
  5. bfc 是一个页面上的独立的容器,外面的元素不会影响 bfc 里的元素,反过来,里面的也不会影响外面的
  6. 计算 bfc 高度的时候,浮动元素也会参与计算

 怎么取创建 bfc

  1. float 属性不为 none(脱离文档流)
  2. position 为 absolute 或 fixed
  3. display 为 inline-block,table-cell,table-caption,flex,inine-flex
  4. overflow 不为 visible
  5. 根元素

应用场景

  1. 自适应两栏布局
  2. 清除内部浮动 
  3. 防止垂直 margin 重叠

看一个垂直 margin 重叠例子

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        .top{
            background: #0ff;
            height:100px;
            margin-bottom:30px;
        }
        .bottom{
            height:100px;
            margin-top:50px;
            background: #ddd;
        }
    </style>
</head>
<body>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">section </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="top"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>上<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
    margin-bottom:30px;
</span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">section</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">section </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="bottom"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>下<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
    margin-top:50px;
</span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">section</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

</body>
</html>

 

 效果图

 用 bfc 可以解决垂直 margin 重叠的问题

关键代码

<section class="top">
        <h1></h1>
        margin-bottom:30px;
    </section>
<span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 给下面这个块添加一个父元素,在父元素上创建bfc </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">style</span><span style="color: rgba(0, 0, 255, 1)">="overflow:hidden"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">section </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="bottom"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
        <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>下<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">h1</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span><span style="color: rgba(0, 0, 0, 1)">
        margin-top:50px;
    </span><span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">section</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>

 

效果图 

 

关于 bfc 的应用的案例这里就不在一一举出了,大家去网上找一些其他的文章看一下。

 

欢迎补充