[Day 19] 阿嬷都看得懂的盒模型

阿嬷都看得懂的盒模型

各位阿嬷,我们今天要来寄自己腌渍的酱瓜给乖孙。

我们找来 4 个纸盒,想在里面各自放入 1 罐酱瓜。不过为了怕玻璃瓶在运送的过程中撞坏了,我们会先在纸盒中放入碎报纸,再把酱瓜罐放进去。接着,我们要把 4 个纸盒放进大的邮局纸箱中。同样地,我们担心纸盒在邮局纸箱中碰坏了,所以会在纸盒外面塞入保丽龙,让这 4 个纸盒间,还有纸盒与邮局纸箱间,都保持些距离。

问题来了,如果我们的酱瓜罐是 100cm X 100 cm,那纸盒的尺寸会是多大呢?就算我们不放碎报纸,让纸盒紧贴着酱瓜罐,这个纸盒有可能是 100cm X 100cm 吗?不可能对吧?因为纸盒还是有厚度的,所以整个纸盒的宽度就会超过 100cm X 100cm。

我们曾经在介绍区块样式的时候,讨论过 border (边框) 这个属性。这个边框,就好像我们的纸盒,把我们的区块给包起来。不知道各位阿嬷有没有怀疑过一件事情,我的区块在加上边框之後,尺寸会不会维持原样呢?还是会变胖了呢?我们可以来尝试一下,把几个区块加上不同的边框粗细,然後看看最後的结果。

我们先来想想,该怎麽制作同样大小与背景颜色的区块呢?没错,我们可以用类别的方式,把这些区块的大小和背景颜色独立写出来。让我们把这个类别叫做 "box",并且把几个区块指定到这个类别吧:

<div class="box">区块一</div>
<div class="box">区块二</div>
<div class="box">区块三</div>
<div class="box">区块四</div>

小秘诀:输入 .box*4,就可以产出 4 个类别为 "box" 的区块元素罗~这个类别的样式我们会这样写,非常直觉对吧:

.box{
  height:100px;
  width:100px;
  background-color:pink;
}

接下来,我们再把不同的区块各自加上不同的样式:

<div class="box">区块一</div>
<div class="box" style="border: 10px orange solid">区块二</div>
<div class="box" style="border: 20px orange solid">区块三</div>
<div class="box" style="border: 30px orange solid">区块四</div>

等等,这个加上样式的方法也太不 DRY 了吧!让我们想想可以怎麽把 border 这个样式抽出来。还记得我们前面提到粉红色的 gavagai 怎麽做吗?没错,我们可以用行内样式把类别的样式盖掉,所以我们的样式和标签会长这样:

<div class="box">区块一</div>
<div class="box" style="border-width: 10px">区块二</div>
<div class="box" style="border-width: 20px">区块三</div>
<div class="box" style="border-width: 30px">区块四</div>
.box{
  height:100px;
  width:100px;
  background-color:pink;
  border: 0px orange solid;
}

不过,我们前面其实也有提到,我们其实不太喜欢写行内样式,而是喜欢将样式都收整到 .css 档中。所以,我们会把那些行内样式也都写成类别,并且在 .css 档中指定这些类别的样式。在 .css 档中,通常越後面写到的样式,会覆盖掉前面写到的。因此,我们的结果就会长这样:
https://codepen.io/LogosChen/pen/bGRwQWw

我们可以看见,所有区块的粉红色部分,大小都还是维持相同,但是边框变宽以後,会把整个区块撑大,所以就不再是 100px X 100px 这样的尺寸大小了!觉得看不太清楚的阿嬷们,可以再次呼唤出发展者工具,选择想观察的区块元素,然後点选底下的 Styles,再拉到最底下,就可以看见整个元素的详细尺寸:

可以看见,整个区块还是 100px X 100px,不过边框 border 的部分,是 20px 宽。讨论到这边,阿嬷们应该会有 2 个问题:

  1. 图片中的 padding 和 margin 是什麽?
  2. 那如果我想无论如何都固定区块大小就是 100px X 100px,该怎麽办呢?莫非要自己计算?

关於第一个问题,我们可以回想一下,在我们打包酱瓜的时候,在纸盒中放了碎报纸,让酱瓜罐和纸盒盒壁保持距离,对吧?padding 其实就像是这些碎报纸,让我们区块中的内容物,和边框之间,保持适当的距离。这个距离,因为是在区块的边框内部,中文通常翻成「内距」。

相反地,在纸盒外的保丽龙,是为了维持纸盒和其他纸盒,还有邮局纸箱间的距离。margin 就像是这些保丽龙,让我们区块的边框,和其他区块的边框之间,保持适当的距离。同理,这个距离,中文通常翻成「外距」。

在刚刚的范例中,我们是不是会觉得每个区块都黏在一起,而且里面的文字都黏在边框旁边,看起来丑到爆炸呢?没错,让我们塞点碎报纸和保丽龙进去吧!让我们在 .box 类别中,把 margin 和 padding 都设成 10 px。

.box{
  height:100px;
  width:100px;
  background-color:pink;
  border: 0px orange solid;
  margin: 10px;
  padding: 10px;
}

这样调整後,我们就让区块间,还有区块边框与内部的内容物,都保持适当间距罗!换句话说,我们的整个区块分成 4 层,从外到内分别是:

  1. margin 外距
  2. border 边框
  3. padding 内距
  4. 内容物,英文叫作 content。
    就像是我们寄酱瓜给乖孙那样,我们用纸盒里面放入碎报纸,和内容物酱瓜推个内距,在纸盒外面填满保丽龙,和其他纸盒间推个外距,再加上纸盒本身边框的宽度,决定了所有元件间的排版。这样的排版模式,我们称作「盒模型」。

上面第二个问题比较简单,我们只要设定

  • 区块尺寸 (box-sizing) 这个样式就可以了。预设的值是 "content-box",也就是宽和高不计入内距和边框。如果我们希望整个区块的尺寸,计入边框和内距的宽度,我们可以把值改为 "border-box"

大家可以把上面的范例 fork 出去以後,自己改变 box-sizing 玩玩看喔!


想一想:我们加上外距後,上面那 4 个区块应该彼此距离多少呢?应该是 10px + 10px = 20px 吧?但是仔细观察上面的例子,是这样吗?


<<:  每日挑战,从Javascript面试题目了解一些你可能忽略的概念 - Day19

>>:  D32 - 自我挑战铁人赛完赛

【把玩Azure DevOps】Day22 建立自管的Azure DevOps Agent(Linux Container agent)

前一篇文章建立了Azure DevOps Agent的Windows Container Image...

Youtube Analytics API 教学 - 打破地理位置的界线 'country' 维度

「鲑鱼均,因为一场鲑鱼之乱被主管称为鲑鱼世代,广义来说以年龄和脸蛋分类的话这应该算是一种 KNN 的...

课堂笔记 - 物联网概论(2)

感知层 将具有感测与辨识能力的元件嵌入连结上真实的物体里面,进而能够对环境进行监控与感知。 分别有...

倒计时按钮文字闪烁问题

缘由: UIUX提出一个新功能,要在按钮上加上倒数秒数,这个功能算是常见,但开始动手作完了之後,问题...

【Day-29】我们是怎麽开始的?:一间传统软件公司从 0 开始建置的 DevOps 文化(心态篇)- 提供选择,别找藉口

前言 最後两天就让我们来谈谈做 DevOps 与软件的心态。 很多时候解释常常会变成一种藉口的感觉,...