盒尺寸中padding负责内边距,一般情况下(抛开上一章的诡异现象)不会给使用者带来太多的麻烦,因此作者称之为温和的padding,而margin则有些激进,虽说负责外边距,但有时候还能做一些"内边距"的事情(负边距),还自带了些特殊属性(如叠压),本文会通过实例深入探究margin负边距的使用以及叠压问题的产生和计算方式

1.margin负边距的正确打开方式

说到margin,通常我们会想到一层透明的外边距,用于划分元素与元素之间的界限,然而margin除了可以划分边界,还可以改变元素"可视尺寸",注意这里我没有用内部尺寸,因为margin和padding在改变元素可视尺寸方面几乎是互补的。对于设定了width或者元素保持"包裹性"的时候,padding会改变元素的可视尺寸,而margin正好相反,margin只会在元素“充分利用空间”状态的时候,才能改变元素的可视尺寸 。当然这两个也不是完全互补的,这里当作一个思考,请自己体会。

刚才说到了设定了宽度的元素和保持“包裹性”的元素不能通过margin影响可视尺寸,设定width这个很好理解,那么保持包裹性的元素有哪些呢?

这里来列举一下常见的有:absolute,fixed,float ,inline-box(inline-block, table-cell, table-caption, flex, inline-flex)。

所以我们在遇到上述元素的时候,就不需要尝试用margin去改变他的可视区了,无效。由于我平时最爱用的inline-block元素也在其中,所以我很少用margin负边距去管理元素可视区。下面,我们来看一个最简单的margin负边距影响元素可视区的演示,代码如下:

<div class="father"><div class="son"></div>
</div>
<style>
.father{width: 300px;height: 200px;background: #F56C6C;
}
.son{margin: 0 -20px;height: 100px;background: #E6A23C;
}
</style>
复制代码

由于markdown编辑器支持标签语言,因此我们可以直接预览最终效果如下(小提示:你可以通过浏览器直接检查下面的元素看到CSS样式)

这里有两个要注意的点,首先son是display默认为block的元素,符合充分利用水平空间的规则,其次son自身不带width申明,所以width在负边距的作用下最终width = father.width + 20*2 ,如上图所示。

负边距除了能够改变"充分可利用空间"的可视区域之外,还可以利用其可以改变尺寸的特性,实现一些特殊的布局效果。如作者给出的例子如下:

<div class="box box-right-same"><div class="full"><p>DOM文档流中,图片定宽在右侧,视觉呈现也在右侧,顺便表现此时一致。</p></div><img src="1.jpg" class="img">
</div>
<style>
/* 右浮动,图片DOM在后,和视觉表现一致 */
.box-right-same > .full {width: 100%;float: left;
}
.box-right-same > .full > p {margin-right: 140px;
}
.box-right-same > img {float: left;margin-left: -128px;
}
</style>
复制代码

结果如下图所示:

结果如上图,在本例中,由于full的宽度是100%,且他和img元素均为浮动元素,因此img元素在没有设置margin之前应当流到full元素下面,而加了负边距之后,img元素的宽度增加了128px,正好等于图片的宽度,此时图片元素全部跑到了增加的负边距中去,导致img元素本身变成了"0宽度",于是0宽度元素就浮上来了,因为他“不需要”占据宽度,他的宽度由负边距提供了。(这一段测试个人持保留意见,有不同观点的可在下方留言)

2.深入探究margin合并的三个条件

块级元素的上外边距(margin-top)和下外边距(margin-bottom)有时会发生“重叠”,这样的现象叫做margin合并。从定义上来看,可以确认两个信息。

(1)块级元素

(2)垂直方向。不考虑writing-mode的情况下,文档流默认为水平方向,因此这里的垂直方向是指垂直于文档流的方向,而不是简单的上下左右。

margin合并一般有三种场景

(1)相邻兄弟元素margin合并。

(2)父级和第一个/最后一个子元素。(作者的这个表达可能有一些问题,需要配合第三点来看)

(3)空块级元素的margin合并。

下面我将列举一些场景,来探究一下每个场景的哪些margin发生了叠压。

<p>一段话</p>
<p>一段话</p>
<p>一段话</p>
<p>一段话</p>
<style>
p{margin: 1em 0;
}
</style>
复制代码

结果如下图所示:

这个例子中,显然是相邻兄弟元素的margin合并,可以看到p标签的上下外边距是1em,但每两行之间的的距离并不是1+1=2,而是1和1叠压之后 = 1。下面来看第二个场景。

<div class="father"><div class="son"></div>
</div>
<style>
body{margin: 0;
}
.father{background: green;height: 400px;
}
.son{margin-top: 200px;height: 200px;background: red;
}
</style>
复制代码

结果如下图所示:

在本例中,父元素高度400,子元素高度200,上外边距200,想象之中,子元素应该"定位"在父容器底部,但由于父级和第一个/最后一个子元素的margin叠压(这个理论是否完全正确我们在后面的例子中证明),子元素的margin-top"借"给了父元素,然后自己的margin-top似乎变成了0,在实际开发的时候,父子元素的margin合并也会给我们带来许多麻烦,那么,如何解决这个烦恼呢?作者提供了几种方案(满足任何一种即可),这里我会有一些自己的观点在里面。

  • (1)父元素设置为块状格式化上下文元素(听不懂没关系,overflow:hidden就可以)

  • (2)父元素设置border-top/bottom(>0)的值(border-top解决margin-top,border-bottom解决margin-bottom)

  • (3)父元素设置padding-top/bottom(>0)的值(同border)

  • (4)父元素和第一个子元素之间添加(非空)内联元素进行分隔(针对margin-top)

  • (5)父元素和最后一个子元素之间添加(非空)内联元素进行分隔(针对margin-bottom)

  • (6)父元素设置height,min-height或max-height(注意本条只对margin-bottom有效)

经过本人测试,CSS世界似乎对申明这个玩意不感冒,作者说设置border/padding的值即可,我设置0,"竟然"不行,所以补充了>0的限制条件,但由于这条规则破坏了容器的大小,所以不推荐这两种解决方案。

在实际验证的时候,第四条/第五条在谷歌浏览器中也会由于“0”值不生效,因此我把它划掉了,因为这个解决方案实在是太蠢了,你必须要在内联元素里面写点什么才能解决margin叠压问题,这可比破坏容器大小严重多了,直接就影响文本显示了。因此最佳的解决方案就是第一条,父元素设置为块状格式化上下文元素,虽然我并不知道这个是什么意思。

进入今天的重头戏,我觉得作者写的有问题的一个点,我们先在刚才父子叠压代码的基础上添加一个空块级标签。

<div class="father"><!-- 我是一个空块级元素 --><div></div><div class="son"></div>
</div>
<style>
body{margin: 0;
}
.father{background: green;height: 400px;
}
.son{margin-top: 200px;height: 200px;background: red;
}
</style>
复制代码

此时你会发现页面无任何变化,其实这里涉及到两个知识点,首先是空块级标签的margin叠压,由于其本身没有任何宽高,也没有margin值,因此他只会和相邻的son元素进行叠压,空div的margin-bottom:0 和 son元素的margin-top:200合并之后,可以认为空div的margin-bottom变成200了,此时,空块级元素的margin-bottom:200又和自身的margin-top:0合并,使得自身的margin-top也受到了感染,最后叠压成垂直margin=200的空块级元素,这时候父元素感应到他的第一个子元素有margin-top,就和他进行了一波margin-top叠压,所以最终的表现和第二个例子的结果相同。

测试到这里,我还觉得没什么问题,然后我又想到刚才内联空标签对第二个例子也不会有任何影响,那么问题来了,父级和第一个/最后一个子元素的叠压这句话究竟是什么意思?惊觉这句父元素和第一个子元素之间添加内联元素进行分隔似乎还有什么别的意思,我个人猜测作者是想表达内联元素破坏了发生叠压的三个规则,因为内联元素不会发生margin叠压,因此可以用这个进行分割(即使该内联元素为空,当然实际测试中为空是没有任何效果的)。根据测试结果,我提出的一个大胆的假设:margin叠压,会直接忽略掉所有空标签(当然空标签不能有什么奇奇怪怪的样式)。这么一来,内联空标签的问题就解决了。当然这个假设还有待验证,去作者提供的论坛碰碰运气。

3.margin合并的计算规则

关于margin合并的计算规则,我个人倾向于完全套用作者的三句精辟总结:

  • “正正取大值”
  • “正负值相加”
  • “负负最负值”

这里我只说明正负值相加的情况,虽然这东西其实并没有什么软用,看下面的例子

.a{margin-bottom:50px}
.b{margin-top:-20px}
<div class="a"></div>
<div class="b"></div>
复制代码

此时a和b的间距=-20+50 = 30px

4.深入理解margin:auto

总是喜欢以深入命名,其实就是一个?测试,根据浏览器的表现结果,来猜测原理,在理解margin:auto之前,先来看下面这个例子。

<div class="father"><div class="son"></div>
</div>
<style>
body{margin: 0;
}
.father{height: 400px;background: yellow;
}
.son{width: 200px;margin-right: 100px;margin-left: auto;height: 200px;background: red;
}
</style>
复制代码

结果如下图所示:

可以从结果中得出如下结论:

(1)margin:auto是有用的,去掉margin-left:auto后,margin-right失效

(2)margin:auto属性管理的是容器的剩余空间

何为容器的剩余空间?最寻常的情景就是你在body里添加了一个宽度

那么问题又出现了,为什么此时在垂直方向上没有垂直居中呢?原因在于触发margin:auto计算有一个前提条件,就是width或height为auto时,元素是具有对应方向的自动填充属性的。从本例来看,当son的width为auto时,son的宽度为100%,也就是可计算的剩余空间为100%-width具体值,当son的height为auto时,不好意思,son的高度变0了,看都看不见了,你还要居中他干啥。同时height:auto也不符合自动填充特性。

利用margin:auto管理剩余空间的特性,我们除了可以做到元素的水平居中,还可以实现元素的"右浮动"。只需要如下设置即可.

<div class="father"><div class="son"></div>
</div>
<style>
body{margin: 0;
}
.father{height: 400px;background: yellow;
}
.son{width: 200px;margin-left: auto;height: 200px;background: red;
}
</style>
复制代码

这里我们通过margin-left:auto管理剩余空间,元素就自动右对齐了。

除了水平居中和右对齐,margin:auto还可以实现水平垂直居中。刚才也说到了,要实现垂直居中,只需要让元素在垂直方向上也就是height:auto具有自动填充属性即可。那么什么情况下height:auto有自动填充属性呢?有一种情况就可以,绝对定位元素设置了top和bottom属性之后,元素垂直方向上就会自动填满父容器。如下所示

<div class="father"><div class="son"></div>
</div>
<style>
body{margin: 0;
}
.father{height: 400px;background: yellow;position: relative;
}
.son{position: absolute;width: 200px;height: 200px;background: red;margin: auto;left: 0;top: 0;right: 0;bottom: 0;
}
</style>
复制代码

由于设置了right,left,top,bottom值,子元素在水平垂直方向上都有用自动填充属性,通过margin管理剩余空间,就实现了垂直和水平方向的填充。

margin部分的内容就写到这。

不忘初心,方得始终

喜欢博主的童鞋可以扫描二维码加博主好友~ 也可以扫中间二维码入驻博主的粉丝群(708637831)~当然你也可以扫描二维码打赏并直接包养帅气的博主一枚。

转载于:https://juejin.im/post/5d030827e51d4556d86c7ab4

CSS进阶(5)—— 深入理解margin相关推荐

  1. 「前端早读君007」css进阶之彻底理解视觉格式化模型

    今日励志 不论你在什么时候开始,重要的是开始之后不要停止. 前言 对于部分前端工程师来讲,有时候CSS令他们很头疼,明明设置了某个样式,但是布局就是不起作用. 如果你也有这种问题,那么是时候学习下什么 ...

  2. CSS进阶(10)—— 深入理解BFC结界

    本章继续来探讨CSS世界的流破坏和流保护,延续的是上一章float的内容,在上一章中我们已经知道了clear属性并不是真正的清除浮动,本章将继续深入探索,引入BFC结界的概念.如果对浮动和清浮动属性还 ...

  3. css margin padding 0,CSS 彻底理解margin与padding

    我们在刚开始接触CSS的时候总是被margin和padding闹的晕头转向,什么时候设置margin,什么时候设置padding,不是太清楚,设置了以后在界面上看到的效果也差不多呀. 如何理解marg ...

  4. 【前端学习】D3:CSS进阶

    文章目录 前言 系列文章目录 1 CSS的三大特性 1.1 层叠性 1.2 继承性 1.3 优先级(*) 2 盒子模型 2.1 看透网页布局的本质 2.2 盒子模型(Box Model)的组成 2.3 ...

  5. CSS进阶-盒子与动画

    CSS进阶-盒子与动画 文章目录 CSS进阶-盒子与动画 前言 Chapter04 CSS3动画 1. Animation动画 1.1 关键帧 1.2 定义关键帧 1.2.1 定义示例 1.2.2 效 ...

  6. [css] 说说你对css盒子模型的理解

    [css] 说说你对css盒子模型的理解 css盒模型由两个盒子组成,外在的控制是否换行的盒子,以及内在的控制元素内容的盒子.比如:display: inline-block, 则它的外在的盒子就是i ...

  7. css属性之padding和margin

    css属性之padding和margin,并探究给行内元素设置内外边距是否有效! padding和margin的作用(重要) padding:内边距(影响盒子的大小) padding-top:上内边距 ...

  8. CSS进阶之关于网格布局(Grid) 你了解哪些

    CSS 进阶:网格布局(Grid)及其基本属性 网格布局(Grid)是最强大的 CSS 布局方案.起初我也认为 flex 布局就可以完成绝大部分布局场景,但谁不希望用更直观.更简洁的方式来布局自己的网 ...

  9. 《Web前端开发精品课 HTML与CSS进阶教程》——1.4 id和class

    本节书摘来自异步社区<Web前端开发精品课 HTML与CSS进阶教程>一书中的第1章,第1.4节,作者: 莫振杰 更多章节内容可以访问云栖社区"异步社区"公众号查看. ...

最新文章

  1. 函数的参数与函数的嵌套调用
  2. About Instruments
  3. CString、std::string格式化字符串
  4. excel图表交互联动_如何使用高大上的多级联动交互式图表来分析人员结构?
  5. 全面讲解Python列表数组(二),列表分区/片,列表操作符,比较操作符,逻辑操作符,连接操作符,重复操作符,成员关系操作符;
  6. ORACLE 错误:oralce record is locked by another user
  7. python parser count_8个超实用的Python脚本,收藏备用
  8. 虽说下班时间自己说了算
  9. 开发小程序遇协同、平台兼容难题,该如何破局?
  10. Panasonic: FP-X0 L30R 使用 FPWIN GR7 通讯及编程
  11. tomcat8.0安装及配置
  12. window server 2012 win7 远程桌面报错问题,无法远程
  13. 数字盲打怎么练_小键盘数字盲打练习
  14. deepin 切换输入法
  15. 斯坦福大学-自然语言处理入门 笔记 第十九课 单词含义与相似性
  16. Java程序设计 试卷A
  17. 第三十四篇-Palette(调色板)的使用
  18. 情态动词+have+done用法整理
  19. 使用instantclient_19客户端(免安装)远程连接Oracle服务器端数据库
  20. 计算机网络:速率、带宽、延迟、时延带宽积、丢包率、吞吐量

热门文章

  1. 小组焦点座谈的基本过程
  2. 工业智能网关是工厂设备数据采集解决方案工具
  3. 华为FusionSphere超融合个人学习理解
  4. 【Java】获取星座匹配度
  5. android平板触控笔,解锁平板的这些隐藏 配个手写笔就可以了
  6. 火狐、谷歌等浏览器打印页面PDF
  7. 论文阅读(一) 注意力机制
  8. PCHunter —— 很强大的系统信息查看工具
  9. 场地测量的方法和程序_简述水准测量的操作程序和方法步骤
  10. 前端:Good Features to Track