margin和padding

盒模型

CSS 框模型 (Box Model) 规定了元素框处理元素内容、内边距边框外边距的方式。

ps:如果想要深入了解css盒模型,可以去w3cSchool找到关于盒模型的详细概述,这里只会简单的介绍部分盒模型相关的知识

什么是CSS盒模型?

盒模型

这是一个元素的盒模型展示,几乎所有元素都是使用这种盒模型构成的,盒模型分四个部分,从里到外分别为element(元素)padding(内边距)border(边框)margin(外边距)


element

element部分负责承载整个元素的内容,如文字、前景图片等

写在双闭合标签里面的内容通常会显示在元素的element部分,也就是内容区。

<div>这里是我的内容</div>

页面中的显示效果为:

仅有文字的div

在上面的中,我在div标签内部写了一段文字这里是我的内容,然后这个div的高度会被这段文字撑开,而宽度则是块级元素的默认宽度100%。

如果我在div内部再加一个图片,则div的内容区域被继续撑开:

  <div>
    这里是我的内容
    <img src="https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=502636781,1650308494&fm=58">
  </div>

呈现效果为:


文字+图片的div

padding

元素的内边距在边框和内容区之间。控制该区域最简单的属性是 padding 属性。
CSS padding 属性定义元素边框与元素内容之间的空白区域。

padding不会占据元素的内容区域,但是它会扩展一个元素的内部区域,可以打一个比方,我们每个人本身就好比是一个元素的element,而你身上穿的衣服就好比是元素的padding部分,你的衣服既是你又不是你本身,别人在找你的时候如果碰到你的衣服你可以感觉到是有人触碰了你,但是你的身体本身并不会延伸到衣服的内部

还是使用上面的那个div,我们现在给这个div加上一个padding,在这之前为了方便观察,我们先给这个div加上一个背景颜色和宽度,

div {
  padding: 10px;
  background-color: skyblue;
  width:400px;
}
<div style="padding:10px;background-color:skyblue;">
  这里是我的内容
  <img src="https://ss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=502636781,1650308494&fm=58">
</div>

现在呈现出来的效果:


padding:0;

我们可以看到,现在文字和图片还是在这个元素的底部的,我们现在给他加上一个50px的padding


padding:50px;

我们可以看到,这时这个元素本身的大小已经扩展出来了,此时我们可以达到了浏览器的审查元素,观察盒模型的变化:
设置padding后的盒模型

其中蓝色部分是element,也就是元素的内容区,400 * 125代表了我们设置了400px的宽度,里面的图片高度是125px,内容区被撑开,所以此时元素的内容区是400 * 125像素的大小,然后往外看,padding有4个50,这是代表了这个元素在上下左右四个方向上的padding都是50像素,此时我们整个元素的占位宽度就是400+50+50=500px,高度则是125+50+50=225像素,所以但是由于元素内容的部分不能延伸到padding区域,所以上面的文字和图片还是都在元素本身的内容区,不会随着元素尺寸被padding撑大而向外扩展。

可以被padding扩展的样式

再回到这张图片

padding:50px;

我们可以看到,这个元素虽然内容区没有向padding部分扩展,但是背景颜色却从内容区延伸到了padding的部分,这是因为元素的整体结构以border(边框)为界,border里面的均为元素的本身部分,而类似于background-color这种样式会延展到整个元素的所有内容区域,和这个类似的效果还有a标签的点击区域:

<a href="">这是一个超级链接</a>
a标签

现在我们有一个a标签构成的超级链接,点击这个a标签可以跳转到对应的页面,但是有的时候在页面中文字可能比较小,如果只有在点击到文字上时才能跳转的话会影响用户体验,所以我们要让a标签的点击区域变大,有两种方式可以解决这个问题:

给a标签宽度和高度

为了方便观察,我们同时给他一个背景色

    a{
      width: 300px;
      height: 200px;
      display: block;
      background-color: lightgreen;
    }
有宽高的a标签

这时,我们由于扩大了a标签的宽度和高度,所以整个绿色的区域都是a标签的范围,自然都可以实现点击效果。

给a标签设置padding

上面那种方式可以实现大多数需求,但是现在还有一个问题,就是当a标签的可点击范围不固定时,或者由于种种问题我们不能给a标签转成块级元素时,上面那种方法就不生效,比如下面这种场景:


菜单栏

这是一个通常网页中常见的菜单栏,现在我有一个需求,就是需要给被点击超级链接加大尺寸方便点击,同时加一个统一的背景颜色,以便于让用户区分哪些是可以被点击的区域。
按照上面的那种方式,我们可以这样设置

a{
  width: 80px;
  height: 30px;
  display: block;
  background-color: pink;
}

呈现的效果是


使用宽度设置a标签范围

这时如果我们想要给文字居中还需要设置两个样式:

text-align: center;
line-height: 30px;

然后出来的效果是这样的:


排版后的a标签

这时我们已经达到了我们所需要的效果,但是还有一种情况,就是当列表内的文字长短不一时,这种方式就会出现问题:


文字长短不一

如图所示,当我们的列表文字有长有短时,上面那种方法可能就不太实用了,因为这时如果我们设置统一的宽度,长的太长,短的太短,怎么都不好看,处理这样的情况时,如果不是设计稿需要统一长短,我们一般都会使用另一种方式排版,即使用统一的padding。
    a{
      padding: 0 20px;
      height: 30px;
      display: block;
      background-color: pink;
      text-align: center;
      line-height: 30px;
    }
image.png

border

元素的边框 (border) 是围绕元素内容和内边距的一条或多条线。
CSS border 属性允许你规定元素边框的样式、宽度和颜色。

边框的使用没有什么好说的,只有几个主要注意的地方:

  1. 双线类的边框(如border-style:double;等),设置宽度时最小宽度为3像素,否则不能正常显示
  2. border有四个方向,可以分开写,如果合写的话顺序同margin和padding的合写顺序
  3. 在使用有边框的hover效果时,不能直接将边框设置为none,要设置为border-color:transparent;,hover时再将颜色设置回需要的颜色,否则会出现高度显示异常的问题。

其中1、2比较容易理解,下面解释一下第3点。
我们在做页面的时候,有的时候会使用这样的特效:

border.gif

和这样的特效:
border-transition.gif

为了让效果看起来更明显,我延长了动画执行时间并且降低了帧数
下面是两个效果的代码:

border.gif
    a{
      padding: 0 20px;
      height: 30px;
      display: block;
      text-align: center;
      line-height: 30px;
    }
    a:hover{
      border-bottom: 4px solid red;
    }
border-transition.gif
    a{
      padding: 0 20px;
      height: 30px;
      display: block;
      text-align: center;
      line-height: 30px;
      border-bottom: 4px solid transparent;
      transition: all 1s;
    }
    a:hover{
      border-bottom: 4px solid red;
    }

这两种效果最大的区别在于2比1多了一个过渡的效果。
按照没有过渡效果的border(以下简称效果1)的思路,转变成有过渡效果的border(简称效果2)应该只需要加一个transition作过渡动画就可以了,但实际上如果我们只是在效果1的基础上加了一个transition的话则会出现这样的效果:

border2.gif

这是由于HTML在绘制元素生成时会从上至下绘制,而不是所有像素同时绘制,最开始时a标签内没有边框,hover时出现边框,HTML就会从没有边框开始一行行绘制,所以就会出现这样的效果,如果这个菜单是放在页面中可能会出现边框将上面的文字顶上去的效果。
因此我们这里需要先让a标签有一个透明的边框,鼠标放上去时只是让边框变颜色,才会出现我们想要的效果。


margin

围绕在元素边框的空白区域是外边距。设置外边距会在元素外创建额外的“空白”。
设置外边距的最简单的方法就是使用 margin 属性,这个属性接受任何长度单位、百分数值甚至负值。

在初学css时,margin和padding最容易混淆,实际上我们只需要注意两者最大的区别就可以,那就是padding可以延伸background的属性,主要是background-colorbackgound-image,而margin不会延伸这些属性。

  <style>
    div{
      width: 200px;
      height: 200px;
    }
    .div1{
      background-color: pink;
    }
    .div2{
      background-color: green;
    }
  </style>
</head>

<body>
  <div class="div1">这是div1的内容</div>
  <div class="div2"></div>
</body>

我在这里写了两个div,给他们加了同样的宽度并分别加了背景颜色,同时给div1加了几个文字内容,由于块级元素的特性,他们分别处于两排。


image.png

现在我给div1设置50px的padding

    .div1{
      background-color: pink;
      padding: 50px;
    }
image.png

可以看到,现在div1的元素本身被撑大了,现在div1的高应该是50 + 200 + 50 = 300px


审查元素

同样,由于上面提到的padding的特性,所以文字依然是在内容区,没有进入padding的部分。
此时我们可以看到,div1的整体尺寸被放大了,同时背景颜色延伸到padding的范围。
现在我再给div1设置5px的border

    .div1{
      background-color: pink;
      padding: 50px;
      border: 5px solid red;
    }

这时div1的整体高度应该是5 + 50 + 200 + 50 + 5 = 310px


div1有border

然后再设置20px的margin:

    .div1{
      background-color: pink;
      padding: 50px;
      border: 5px solid red;
      margin: 20px;
    }

div1带margin

设置的样式是margin:20px;由于截图问题,可能显示的有问题

我们先不用管其他方向,先看下面,也就是div1和div2交接的地方。

在这里我们可以看到div1和div2之间有20px的间距,这一部分就是div1的margin,而且和padding最大的区别是这一部分没有延伸div1的背景色和内容区域,同时也没有让div的元素尺寸发生改变


div1的高依然是310px

因此我们可以这样理解

  • element是你的身体,你的身体越胖element越大,而你体内的元素(如血液、氧气)可以在你体内自由流动
  • padding是你身上衣服的薄厚,你的身体占位(尺寸)和padding正相关,但是你体内的元素不能接触到padding
  • border是你衣服最外层的皮革,皮革同样会延展你的身体占位
  • margin是你的气场,虽然没有元素阻隔,但是如果你的气场够强大,其他人也不能靠近你

这里看完了,我们现在再回头看margin右侧的问题


盒模型.gif

我们可以发现,Chrome在审核元素时会自动将对应部位改变颜色,在右侧鼠标放在对应的位置时,左侧的元素也会实时响应出对应位置,如图所示,在element、padding、border时显示均正常,margin时上、左、下三个方向也没有问题,唯独右侧会比我设置的margin要大得多(margin:20px),这是因为块级元素独占一行的特性,让他在自己元素本身同行的位置会有默认的margin:auto;,即同行下所有元素没有占的位置均为这个元素的margin,这也是块级元素不能和其他元素同行的原因。

给div1设置float:left之后元素的margin显示正常,但是由于脱离文档流导致下面的元素挤了上来,如需要解决这个问题则需要清浮动


应用技巧

元素的盒模型会有各种各样特殊的问题,下面举几个常见的例子以及经常出现的问题和解决方式:

元素高度问题

我们在布局时,由于元素的高度通常为后台提供,所以前端页面的部分通常不会给固定的高度以免结构混乱,所以我们在布局时需要灵活运用padding和清浮动。



上面一个div内部有一个ul无序列表,div上下均距离ul有一定的距离。

在我们写静态页面时无序列表的数量可能是固定的(4个),但是js加载时通常数量不固定,可能少于4个也有可能更多,这时如果我们给一个固定的高度则会出现内容溢出的问题


固定高度内容溢出

所以这里我们需要给div设置上下相等的padding,而不是固定高度。


使用padding留间距

在使用padding进行内容填充时需要注意padding会延展这个元素本身的尺寸,所以如果同时设置了元素的heightpadding时,要将元素的盒模型改成border-box或在height里面减去padding所占的像素;如元素本身的高度是100px,如果你又设置了padding:10px 0;,那么你需要将高度减去20px,即改为80px。

margin-top的bug

在HTML中,一个元素内部的第一个子元素如果有margin-top的话即会将子元素的margin-top赋给父元素:

  <style>
    body{
      background-color: lightblue;
    }
    div {
      background-color: #eee;
      height: 300px;
    }
    h1 {
      margin-top: 50px;
    }
</head>

<body>
  <div>
    <h1>标题部分</h1>
  </div>
</body>
margin-top的bug

如图所示,我在元素中给h1设置了margin-top,但是h1的margin-top并没有生效,而是传递给了它的父元素div,导致div整个被拉了下来,布局错乱。

触发原因

一个盒子如果没有上补白(padding-top)和上边框(border-top),那么这个盒子的上边距会和其内部文档流中的第一个子元素的上边距重叠。

解决方法:
  1. 给父元素设置border-top:1px;
  2. 将子元素的margin-top改成同等数量的padding-top,并赋给父元素
    两种解决方法中,方法2最常用
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,737评论 1 92
  • HTML元素分类 顶级(top-level)元素包括html, body, frameset, 表现如Block-...
    葶寳寳阅读 540评论 0 5
  • margin和padding margin ——边框的外面可以有一层边外补白(margin),边外补白可以把块级元...
    艳晓阅读 975评论 0 0
  • •前端面试题汇总 一、HTML和CSS 21 你做的页面在哪些流览器测试过?这些浏览器的内核分别是什么? ...
    Simon_s阅读 2,220评论 0 8
  • 本课来自http://www.imooc.com/learn/9请不要用作商业用途。 HTML5 HTML介绍 H...
    PYLON阅读 3,212评论 0 5