关于margin-padding实现等高布局的理解

  1. 前言
  2. 正文
    1. 等高布局的使用场景
    2. 环境搭建
    3. 卸去层层包装
      1. margin 和 padding 在这之中扮演的角色
      2. 关于”欺骗“这个理解的辅助demo
    4. 拉长-欺骗 组合拳
  3. 总结
  4. 反思

前言

利用超大的padding-bottom和相等且相反的margin-bottom 配合包含块的overflow:hidden 即可实现等高布局。

这种写法应该是属于比较古老又晦涩难懂的了。不亲自上手一步一步了解的话,很难知道它背后的道理,所以来记录一下。

本文采用倒推的思考路线来解释原理。

正文

等高布局的使用场景

当我们有好几列内容,且不希望直接写死高度,而是根据这几列中的最长的那一列,来让其余列自适应高度,等高布局的方式就发挥作用了。

环境搭建

<style>
    .son{
        display: inline-block;
    	vertical-align: top;
        background-color: salmon;
        width: 400px;
    }
    .father{
    	
    }
</style>
<div class="father">
    <div class="son">
        <pre>
            1
        </pre>
    </div>
    <div class="son">
        <pre>
            1
            2
            3
            4
            5
        </pre>
    </div>
</div>

这里如果给子元素设置float也能做到内容放到一行,但是会影响之后讲解(详见结尾反思),所以采用display:inline-block的方式,至于vertical-align的设置是为了两块不论内容多少都能顶部对齐,如果对这行代码不懂的可以去看看这个博客,强烈推荐!

关于 vertical-align 你应该知道的一切 - 政采云前端团队 (zoo.team)

首先,我们补充完成目标环境,为包裹div添加overflow:hidden,且子元素添加padding-bottommargin-bottom,为了更容易讲解,这里值设置为+-500px

卸去层层包装

可以看到已经达到了等高的效果,这个时候我们把包含块的overflow删掉看看?

我们会发现,实际上这种做法并不优雅,网上对这种等高方案多会说 “正反相互抵消” 这种话,其实是挺误导的,到这里思考一下我们很容易能想到,这种方案其实就是延长了每个元素的长度,然后让父元素齐着一刀切,从而达到的视觉上的对齐! 但是,在这其中,marginpadding 到底发挥了什么作用呢? 接下来就根据一步一步的实验进行探索!

margin 和 padding 在这之中扮演的角色

背景是实实在在的延长了,那究竟是 margin 还是 padding 导致的延长呢。冷静思考一下,背景色生效的范围是一个块元素包括 border 在内的所有区域(content+padding+border)border 内包含了 padding, 所以毫无疑问是padding的延长带来了背景色的延长,而 margin 在正值的时候,不管多大都不会影响到自己的内容区域,也就不会影响背景了。至于负margin的作用倒稍微复杂,可以阅读下面这篇文章,我摘录了对本次探索有用的一句话:

理解并运用 CSS 的负 margin 值 - SegmentFault 思否

当position为static时,当设置负值的 margin 的方向为 bottom 或者 right 的时候,元素本身并不会移动,元素后面的其他元素会往该元素的方向移动相应的距离,并且覆盖在该元素上面。

虽然这句话并不能直接适用我们这个demo,因为我们这只有一行,第一块元素的正下方并没有元素,但是我们其实可以换个角度来理解——负margin并不会影响自己盒子内的情况,而是”欺骗“其他元素对于自身边界的判断,而在我们这个demo中,会受到影响的就是父容器也就是包含块了,包含块会被误导,认为自己的子元素最大高度降低了。

关于”欺骗“这个理解的辅助demo

为了便于理解,这里再做一个单独的demo讲解。

我们在一个div>div 的简单布局中,设置子div的宽高,并将margin-bottom缩小100px。并设置父容器的border

这个时候就能清晰的看到,父容器被”欺骗“了,而通过控制台能看到,子元素实际盒子内部容量并没有发生变化:

虽然我说的和真实的原理应该是有区别的,但是我觉得可以按照这个想法来记忆,至少这套逻辑暂时还没有问题。

拉长-欺骗 组合拳

ok回到正题,这个demo举例的是一个子元素的情况,当有多个子元素,也就是最开始那个demo的情况时,因为==父容器会根据所有子元素的最大高度定高度==。由于marginpadding相等且相反,所以子元素虽然展示上由于padding的缘故被拉长了,但是因为负margin让元素对外欺骗了和padding相等的高度,综合起来的结果就是,子元素被视觉拉长了,但是并没有影响周围环境

所以各个子元素在经过了margin padding组合达到的一轮欺骗之后, 对外展示的高度和原高度一致;

所以父容器的高度就是我们预期的“最高子元素“的高度;

这个时候对父容器来一个overflow:hidden 也就顺理成章,从最高子元素的底部开始,截断往下的区域,也就达到了等高布局的效果。

总结

虽然这种等高布局在2021年的应用应该很少了,但是通过这种方案,能加深我们对 负margin 等一系列相关知识体系的认知,如果觉得本文对你有帮助,请点赞支持!有任何问题或者更好的理解也欢迎评论区交流!

反思

  • paddingmargin值为什么越大越好?

    这个时候就很容易进一步分析了,如果paddind过小,导致最低的子元素加上了这个padding也达不到最高子元素原本的高度,那包含块overflow之后依然达不到等高的视觉效果!

  • 为什么例子不用float做演示?
    float会引起包含块高度塌陷,利用浏览器控制台看不到一步一步推进的效果,而最终的overflow:hidden 又刚好清除浮动撑起了内容,这点其实很巧,所以从使用角度来说,float并没有问题,而关于清除浮动也不是一个简单的知识点,并不关联本文主线内容,只会让模型变得更复杂!


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 yionr99@gmail.com