5

你有所不知的 margin 属性

 2 years ago
source link: https://tomotoes.com/blog/you-dont-know-the-margin-attribute/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

你真的了解的 margin 属性吗?

本文总结于 张鑫旭老师CSS 深入理解之 margin 课程,感谢张老师的辛苦付出!

难学的 CSS

作为前端狗的我们,每天都要和网页打交道。当 UI 将设计稿发给你时,CSS 的知识便显得尤为重要。而 CSS 这一标记性的语言,却时常让我很头疼:毫无逻辑性,并充满了各种坑爹的潜规则 ,以至于每次做项目时,大部分时间精力都浪费在了调整布局与样式上,详情可点击知乎上的为什么 CSS 这么难学?问题,道出了我的心声 :(

但谁叫我们是吃这碗饭的呢,不管怎样,有困难必须迎面解决,学好 CSS ,向张老师看齐!

margin 算是性格刚烈的属性了,下面,我将从各个方面讲解 margin 的可怕之处。

元素尺寸的影响

通常一个元素的尺寸可分为:可视尺寸 与 占据尺寸

  1. 可视尺寸 - clientWidth (border - padding - size)
  2. 占据尺寸 - outerWidth (border - margin)
元素尺寸示例图

margin 又是怎样影响这两个尺寸的呢?

首先,两个尺寸都需满足一定的条件。

可视尺寸的影响条件

  1. 适用于 没有设定 width/height 的块级元素 (宽高设死了,怎么会影响呢?) 其中不包括 float absolute fixed 元素 ,inline 水平 ,table-cell 元素
  2. 只适用于水平方向尺寸(margin-left/margin-right)

占据尺寸的影响条件

  1. 适用于 block/inline-block 水平元素
  2. 适用于 任何方向
  3. 与 width/height 值无关
  4. inline 元素只影响水平方向 (后面会提到)
  1. margin 影响元素的可视水平尺寸

  2. margin 影响占据尺寸 ,这个可以说是 margin 的本命技能了,就不举例了。

百分比单位

通常而言,margin 的单位中,百分比单位最容易让人头晕。

  1. 普通元素的百分比 margin 都是相对于 容器的宽度 计算的

    #parent {
    margin: 20px 400px;
    width: 100px;
    height: 200px;
    }
    #child {
    /* 等价于 margin: 5% * 父元素的宽度 10% * 父元素的宽度; */
    margin: 5% 10%;
    /* 父元素的宽度 * 50% */
    width: 50%;
    /* 父元素的高度 * 50% */
    height: 50%;
    }
    <div id="parent">
    <div id="child"></div>
    </div>
  2. 绝对定位的百分比 margin 是相对于 第一个具有定位属性的祖先元素的宽度 计算的(relative/absolute/fixed)

    #parent {
    width: 100px;
    }
    #child {
    /* 注意子元素已增加绝对定位,则百分比按照定位属性的祖先元素的宽度计算,
    本例中是浏览器视口 */
    position: absolute;
    /* 等价于 margin: 5% * 父元素的宽度 10% * 父元素的宽度; */
    margin: 5% 10%;
    }
    <div id="parent">
    <div id="child"></div>
    </div>

重叠可谓是 margin 中的最重要的潜规则了。

  1. 相邻的兄弟元素
  2. 父级和第一个/最后一个子元素
  3. 空的块级元素(自己和自己)
  1. 块级元素 (不包括 float 和 absolute 元素)
  2. 不考虑 writing-mode,只发生在垂直方向 (margin-top/margin-bottom)
  3. 父子 重叠条件

    • margin-top 重叠

      1. 父元素 非格式化上下文元素 没有设置 overflow:hidden
      2. 父元素没有 border-top 设置
      3. 父元素没有 padding-top 设置
      4. 父元素和第一个子元素之间没有 inline 元素分割
    • margin-bottom 重叠

      1. 父元素 非格式化上下文元素 没有设置 overflow:hidden
      2. 父元素没有 border-bottom 设置
      3. 父元素没有 padding-bottom 设置
      4. 父元素和第一个子元素之间没有 inline 元素分割
      5. 父元素没有 height ,min-height,max-height 限制
  4. 空的块级元素 margin 重叠条件

    1. 元素没有 border 设置
    2. 元素没有 padding 设置
    3. 里面没有 inline 元素
    4. 没有 height,或者 min-height
  1. 正正取大值

    #top {
    margin-top: 30px;
    }
    #bottom {
    margin-bottom: 20px;
    }
    <div id="bottom"></div>
    <div id="top"></div>
    两个元素垂直距离为 : #top 元素的 margin-top 值
  2. 正负值相加

    #top {
    margin-top: -30px;
    }
    #bottom {
    margin-bottom: 20px;
    }
    <div id="bottom"></div>
    <div id="top"></div>
    两个元素垂直距离为: #top 元素的 margin-top 值 加上 #bottom 元素的 margin-bottom 值
  3. 负负最负值

    #top {
    margin-top: -30px;
    }
    #bottom {
    margin-bottom: -20px;
    }
    <div id="bottom"></div>
    <div id="top"></div>
    两个元素垂直距离为 : #top 元素的 margin-top 值
  4. 父级和第一个/最后一个子元素 发生重叠 给子元素设置垂直方向的 margin ,等同于 给父元素设置相同的垂直方向的 margin 属性, 也就是说 父子元素发生 margin 重叠时, 它们俩共用一个 margin 属性

  • 连续段落或列表之类,如果没有 margin 重叠,排版会不自然。
  • 页面中任何地方,嵌套或直接放入任何空的 div,都不会影响原来的布局。
  • 遗落空的任意多个 p 元素,不会影响原来的阅读排版。

margin auto

当你使用 margin auto 时,就应该联想到一个词 :填充

一个没有设置宽高的块级元素,会自动填充宽度 如果 一侧是定值,一侧是 auto,则 auto 为剩余空间的大小 如果两侧均是 auto,则平分 剩余空间

示例如下:

<style>
#demo {
width: 500px;
margin-right: 100px;
/* margin-left: 100vw - margin-right - width*/
margin-left: auto;
}
</style>
<div id="demo"></div>

margin:auto 0 !== 垂直居中

以上,我们可得当一个块级元素设置了 margin: 0 auto 可以实现水平居中,

而为什么 margin:auto 0 不会垂直居中?

答:一个块级元素会自动填充可用的水平尺寸,但不会填充垂直尺寸,是因为其根本没有任何可用的垂直空间。也就是说 margin: 0 auto , 总是有尺寸可以来填充的! 而 margin: auto 0 是没有任何尺寸的可以来填充的。

当子元素的宽度大于父元素的宽度 ,是无法通过 margin: 0 auto 实现居中的 因为,这个时候已经没有任何空间可以填充了,当宽度超出父元素时,margin 已经为负值了。

  1. writing-mode 与垂直居中

    .father {
    writing-mode: vertical-lr; /* 更改流的方向为 垂直方向 */
    }
    .son {
    margin: auto;
    }
    <div class="father">
    <div class="son"></div>
    </div>
  2. 绝对定位元素

    .parent {
    position: relative;
    }
    .child {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    }
    <div class="parent">
    <div class="child"></div>
    </div>
  1. inline 水平元素的垂直 margin 无效(margin-top/margin-bottom)
  2. margin 重叠发生
  3. 绝对定位元素非定位方位的 margin 值 “无效” 因为 绝对定位元素 脱离了文档流,与相邻元素没有关系,所以它不可能像普通元素一样,设置 margin,推走其他元素
  4. margin 鞭长莫及 因为 有某些元素破坏了 文档流,设置了 float absolute,造成了假象,margin 不会根据 这些破坏元素作为标准
  5. display:table-cell/display:table-row 等声明的 margin 无效!某些替换元素除外,根据各个浏览器的实现方式作为区分。比如,给 button 元素声明 display:table-cell,但在 chrome 中,button 的 display 属性是 inline-block 。
  6. 内联特性导致 margin 失效 margin-top: 负无穷, 但是,小到 1em 便无效了。 因为它是内联元素,默认是基线对齐,x 字母下边缘对齐,margin 值再大,也不会起作用。 示例如下:
  1. margin-start

    • 正常流向,margin-start 等同于 margin-left,两者重叠不相加
    • 如果水平流向是从右向左,margin-start 等同于 margin-right
    • 在垂直流下 ( writing-mode:vertical-*; ) margin-start 等同于 margin-top
  2. margin-end 与 margin-start 相对

  3. margin-before 默认情况等同于 margin-top
  4. margin-after 默认情况等同于 margin-bottom

  5. margin-collapse

    • margin-collapse:collapse;

      (默认值) 发生重叠

    • margin-collapse:discard;

      取消重叠,margin 重叠部分为 0 ,没有 margin

    • margin-collapse:separate;

      不发生重叠,margin 重叠部分为 margin-top + margin-bottom


margin 课程就到此结束了,再次感谢张鑫旭老师的辛苦付出! 本系列就持续更新中,期待你的关注~

转载本站文章请注明作者和出处 tomotoes.com,请勿用于任何商业用途。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK