CSS-深入理解之margin

在一次面试过程中,面试官问到margin的塌陷的问题,以及margin负值的问题。当时有点蒙,对这块知识点的理解一点都不深入。为了补充这方面的知识,特意去查了一下相关的资料,发现张鑫旭大神在慕课网上有视频讲解。在这里,梳理和总结一下其中的知识点。

1. margin可以改变容器的尺寸

1.1 margin能够改变可视区域的尺寸的条件

  • 适用于没有设定width/height的普通block水平的元素(float元素,absolute/flex元素,inline水平,table-cell元素)
  • 只适用于水平方向的尺寸

1.2 margin能够改变元素占据的空间

  • block/inline-block元素均有效
  • 与有没有设置width/height无关
  • 水平和垂直方向均有效

2. 百分比margin的计算规则

一般的,在CSS中,尺寸除了使用px以外,还可以使用百分比,当使用百分比的时候,是相对于父元素的宽和高的。比如width: 10%是相对于父元素的width,
height: 10%是相对于父元素的height。

  • 但是margin的话,left,top等设置百分比的时候,都是相对于第一个父元素宽度的尺寸。
  • 如果是绝对定位了的话,则不一定是相对于第一个父元素的宽度的尺寸了,而是相对于第一个position为absolute,relative,fixed的父元素或者是html

3. magin重叠

3.1 margin重叠的特性

  • 只发生在block水平的元素(不包含float和absolute的元素);
  • 只发生在垂直方向(margin-top,margin-bottom);

3.2 margin重叠发生的三种情景

  • 相邻的兄弟元素;
  • 父级和第一个/最后一个子元素;
  • 空的block元素;

3.3 父子margin重叠的其他条件

3.3.1 margin-top重叠

1.父元素非BFC
2.父元素没有border-top设置
3.父元素没有padding-top设置
4.父元素和第一个子元素之间没有inline元素隔开

3.3.2 margin-bottom重叠

1.父元素非BFC
2.父元素没有border-top设置
3.父元素没有padding-top设置
4.父元素和第一个子元素之间没有inline元素隔开
5.父元素没有height,min-height,max-height设置

3.4 空block元素margin重叠的其他条件

1.父元素没有border-top设置
2.父元素没有padding-top设置
3.父元素和第一个子元素之间没有inline元素隔开
4.没有height,min-height,max-height设置

3.5 margin重叠的计算规则

1.正正取大值
2.正负值相加
3.负负最负值

3.6 margin重叠的意义

  1. 连续段落或者列表之类,如果没有margin重叠的话,首尾项间距会和其他兄弟标签1:2关系,排版不自然。
  2. web中任何地方嵌套或者直接放入裸div,不会影响原来的布局。
  3. 遗落的任意多个空p标签,不要影响原来的阅读排版。

3.7 善用margin

做列表的时候,虽然只设置margin-top也可以达到布局的目的,但是为了健壮性,可以设置margin-top和margin-bottom,比如最后一个元素被移除或者位置被置换了,都不会破坏原来的布局样式。

4. magin: auto

4.1 margin: auto的作用机制

原本应该自动填充的尺寸被width/height强制变更,而margin: auto就是为了填充这个变更的尺寸而设计的。

4.2 如果一侧是定值,一侧是auto,auto为剩余空间的大小;

例子:

div{ width: 500px; margin-right: 50px; margin-left: auto }

此时div距离右侧的为50px,而左侧是自适应的。

4.3 如果两侧都是auto,则会让元素水平居中

4.4 margin: auto只对block元素有效,对于inline和inline-block水平的元素。并且只对水平方向有效而对垂直方向是无效的,因为水平方向会自动填充至父元素的宽度大小,而垂直方向不会。

4.5 父元素设置writing-mode: vertical-lr,子元素设置margin: auto,子元素会垂直居中,但是不会水平居中。

.father { wrting-mode: vertical-lr; }
.son {margin: auto}

4.6 absolute与margin垂直居中

.father { width: 100px; height: 100px; position: relative; }
.son { width: 50px; height: 50px; position: absolute; left: 0; top: 0; bottom: 0; right: 0; margin: auto; }

这种方式适用于IE8+。这种方式之所以可以水平垂直居中,是因为绝对定位的元素,如果left, right, top, bottom都设置为0的话,是自动拉伸到父元素的宽和高的100%,当对子元素设置了宽和高之后,这时候auto就可以起作用了。

5. margin负值定位的实例

5.1 margin负值下的两端对齐

这主要是用了margin改变元素尺寸大小的原理来实现的。
比如说有一个两端对齐的列表需要实现,正常情况下是这么布局的。

HTML

<div class="box">
    <div class="ul">
        <div class="li">列表1</div>
        <div class="li">列表2</div>
        <div class="li">列表3</div>
    </div>
</div>

CSS

.box {
    width: 660px;
    height: 200px;
    background-color: yellow;
}
.ul {
    overflow: hidden;
}
.li {
    width: 200px;
    height: 200px;
    margin-right: 20px;
    background-color: green;
    float: left;
}

这里写图片描述

这样出来的效果是,右侧有一个margin-right的20px,不太好去除掉。
这时候可以给div.ul设置一个margin-left=-20px,将div.ul扩大到680px宽度。这时候再次计算一下每一个li应该设置的宽度就可以了。布局如下:

HTML

<div class="box">
    <div class="ul">
        <div class="li">列表1</div>
        <div class="li">列表2</div>
        <div class="li">列表3</div>
    </div>
</div>

CSS

.box {
    width: 660px;
    height: 200px;
    background-color: yellow;
}
.ul {
    overflow: hidden;
    margin-right: -20px;
}
.li {
    width: 206.66px;
    height: 200px;
    margin-right: 20px;
    background-color: green;
    float: left;
}

这里写图片描述

5.2 margin负值下的两端对齐

这种布局的原理是利用margin改变元素占据空间来实现的。
比如有两列布局,需要实现的是,任意一列布局的高度改变后,另外一列的高度也跟着变化,实现二者是等高的。正常的布局如下:

HTML

<div class="box">
    <div class="child-orange">左侧</div>
    <div class="child-green">右侧</div>
</div>

CSS

.box {
    width: 400px;
    overflow: hidden;
}
.child-orange {
    width: 200px;
    height: 100px;
    background-color: orange;
    float: left;
}
.child-green {
    width: 200px;
    height: 100px;
    background-color: green;
    float: left;
}

这里写图片描述

当改变左侧div的高度为200px的时候,则变为这样了:

这里写图片描述

这样的话,左右两侧的高度就不是等高了。为了实现等高的效果,则需要给这两个div设置margin-bottom负值,同时设置padding-bottom负值来让元素的实际高度显示出来。(ps:此处不明白是什么意思)
CSS

.box {
    width: 400px;
    overflow: hidden;
}
.child-orange {
    width: 200px;
    height: 100px;
    background-color: orange;
    float: left;
}
.child-green {
    width: 200px;
    height: 100px;
    background-color: green;
    float: left;
}
.child-orange, .child-green {
    margin-bottom: -500px;
    padding-bottom: 500px; 
}

这里写图片描述

可见,利用这种方法,就实现了等高的效果。这种方法兼容性可以,支持IE6+。但是有其副作用,会在overflow: hidden的文章里面细讲。

6. margin失效的情景

6.1 inline水平元素的垂直margin无效

这里面有两个前提:

  • 非替换元素,比如不是 img 元素
  • 正常书写模式,不是writing-mode: vertical-*

6.2 display: table-cell的元素margin无效

6.3 绝对定位元素的非定位方向的margin“无效”

所谓非定位方向指的是left, right, top, bottom中没有设置数值的方向。比如一个图片设置了绝对定位:

img {position: absolute; left: 10px; top: 10px;}

这样的话,right和 bottom是非定位方向。设置margin-right和margin-top是“无效”的。
细心的同学可能观察到,“无效”这两个字一直都是打上了引号的,这是因为其实绝对定位的元素在各个方向的margin都是有效的,只是因为绝对定位的元素脱离了文档流,所以跟普通文档流中的元素不同,其margin对相邻元素的布局没有影响,所以看起来是无效的,但是如果margin足够大时,触碰到了所依靠定位的父元素的边缘,则margin的作用就显现出来了。

7 参考资料

张鑫旭,CSS深入理解之margin

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值