一个实例带你透析CSS盒子模型

CSS盒子模型简介

当对一个文档进行布局(lay out)的时候,将所有元素表示为一个个矩形的盒子(box)。每个盒子由四个部分(或称区域)组成。如图,与盒子的四个组成区域相对应,每个盒子有四个边界:内容边界 content、内边距边界 padding、边框边界 border、外边框边界 margin
在这里插入图片描述

这是chrome开发者工具element面板中style部分的一个盒子模型图,如果有对chrome开发工具此面板不熟悉的朋友可以参看我的这篇博客:element面板介绍
从上图不难看出,此盒子的content宽度为385.75px,高度为154px,padding为20px,border为3px,margin为20px。

盒子模型与width/height之间的关系

明白了盒子模型,但是在真正的实际应用布局中我们更加关注的是此盒子的width(height同理,我这里只以width来讲述)。
相信大家经常会遇到如下问题,明明我设定了一个盒子的width为某一固定数值或者百分比数值,结果实际的width却并不是我所设定的结果或者是实际效果也并非是我预期的结果。
其实原因很简单,因为实际width的效果受到盒子模型的影响,即与content,padding,border以及margin有关系。
首先,在默认情况下我们自己设定的width只代表content的宽度,而最终浏览器所显示出的width是content的width加上padding和border的大小。这也就为什么设定的width不一定与实际生效的width相同。
扩展一点:在实际应用中使用js获取某个元素的width有两种方式,见如下代码:

elem.style.width;
getComputedStyle(elem).width;

前者获取到的是开发者给此元素显式设定的width,这种方式往往并不能获取到此元素真正生效的width,所以想要获取到元素实际生效的width需要使用第二种获取方式。(在性能方面,第二种方式会使得强制刷新dom树,对性能的影响很大,所以建议尽可能少的使用此方式)
默认情况下的width与盒子模型的关系可用如下一段css代码表示:

box-sizing: content-box;

说起box-sizing相信大家更熟悉更喜欢使用的应该是如下css代码:

box-sizing: border-box;

喜欢使用border-box不知道大家是否真正了解其实际功能含义。相比于默认情形的content-box,border-box的作用就是使得开发者设定的width就是代表content加上border再加上padding的总width,从而也就是使得开发者设定的width与实际生效的width保持一致,在很多情况下可以提高开发者的开发效率。只不过当元素有border或者padding时,内部的content的width会相应减小而已。
talk is cheap,show you the example.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width:300px;
            height: 200px;
            background-color:aqua;
            border: solid 10px black;
            padding: 40px;
            box-sizing: content-box;
        }
    </style>
</head>
<body>
    <div>

    </div>
</body>
</html>

这是默认情况下的实际表现:
在这里插入图片描述
然后我们将content-box改成border-box:
在这里插入图片描述
对于效果图如我们预期所料,这个example很简单,大家可以自己动手试试。
讲到这里,细心的朋友应该会发现说了这么多咋没见width与margin之间的关系,它俩之间是不是没有关系。
对,没错,上述两种方式的width与margin都无任何关系,但是margin却会影响到我们实际的应用布局,即因为margin经常会产生那种实际效果与预期效果不一致的现象。

一个玩转margin的实例

我先给出接下来要讲述的实例的效果图:
在这里插入图片描述
图中红蓝上下两块区域的效果一模一样,都是实现有margin水平等分,但是它俩的布局方式却截然不同。
首先,最外层的div我使用的是flex布局,flex的使用我这里不做介绍,有兴趣的朋友可以参看我给的flex的学习链接:flex布局教程
其代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .contain {
      display: flex;
      flex-flow: row wrap;
      align-content: flex-start;
      justify-content: space-around;
      padding: 0;
      margin: 0;
      list-style: none;
      justify-content: flex-start;
    }
  </style>
</head>

<body>
  <div class="contain">
    
  </div>
</body>

</html>

下面我分别说说上下两种实现方式的思路:
首先,要求需要水平4等分,所以很直接的想到使用四个div盒子每个盒子的width为25%。接下来考虑margin,我们知道margin是外边距换句话说就是会挤压内部元素的大小,所以不能直接设定在已被等分的div上。到此,就有两种解决方案
第一种方案:在每个大div里包一个小div,在小div上设置margin然后被挤压的元素就是小div。
第二种方案:继续在大div里设置margin,但是需要根据margin值动态的改变大div的width,因为随着margin的改变,大div势必会被压缩,我们需要手动调整其width来保证其25%的等分占比。

也许在这里有朋友会有疑问,不是说margin与width没关系,那这里为什么margin会影响width,原因很简单,没关系也是相对而言,子元素的margin就是父元素的padding,既如此子元素的margin不会影响子元素的width但是会影响父元素的width。所以在实际应用中margin是否会影响到width以及如何影响还得看自己如何布局。
完整code:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .contain {
      display: flex;
      flex-flow: row wrap;
      align-content: flex-start;
      justify-content: space-around;
      padding: 0;
      margin: 0;
      list-style: none;
      justify-content: flex-start;
    }

    .box {
      width: 25%;
    }

    .smallBox {
      background-color: rgb(40, 193, 253);
      margin: 20px;
      height: 200px;
    }

    .bigBox {
      width: calc(25% - 40px);
      background-color: rgb(190, 14, 43);
      margin: 20px;
      height: 200px;
    }
  </style>
</head>

<body>
  <div class="contain">
    <div class="box">
      <div class="smallBox"></div>
    </div>
    <div class="box">
      <div class="smallBox"></div>
    </div>
    <div class="box">
      <div class="smallBox"></div>
    </div>
    <div class="box">
      <div class="smallBox"></div>
    </div>
    <div class="bigBox"></div>
    <div class="bigBox"></div>
    <div class="bigBox"></div>
    <div class="bigBox"></div>
  </div>
</body>

</html>

百看不如一试,大家赶紧自己动手试试吧。

结语

到此,本篇博客的内容就告一段落了,不知大家有看明白没,如果仍有对盒子模型不清楚的朋友欢迎评论区留言,我看到后会及时回复。

猜你喜欢

转载自blog.csdn.net/asd0356/article/details/108291179