盒子模型,外边距合并,BFC

前言

保持写作但是想不到写什么…那就盒子模型吧。其实文章有些东西我都没试过,因为我身边没有 Windows 机器,更别说 IE6 这种古董了,我只记得,用上 Chrome 的时候上网冲浪更流畅了一点~

标准盒子模型

其实就是width = content width,整个元素的宽度是content width + 2padding + 2border + 2margin,其中的 2 是上下两边或者左右两边的意思,而你设置的宽高,仅仅代表内容的宽高。

怪异盒模型

既然写了标准两个字,那就肯定也有不标准的,就是那个搞事情的 IE,IE 的width并不是contetnt width,而是width + 2padding + 2border,仅仅只有margin不属于,如果空间不够,就往里面压缩。

box-sizing

这个属性有两个值,默认是content-box,就是标准的,第二个值是border-box,就能做到怪异盒的效果,有些情况还是能用上,这样看来喊怪异盒真的太冤枉了…

margin 合并

可以看下这个 🌰,设置明明两个都是margin,但是中间区域看上都不像有 200px,这就是margin合并,这还不止一种情况,还有两种:

这里的foo.marginTopbar.marginTop合并了

这里的 bar 完全不见了,而且也发生第一种的情况

MDN 这边详细写了三种情况在什么时候会发生和注意事项:

  • 相邻元素之间
    • 毗邻的两个元素之间的外边距会折叠(除非后一个元素需要清除之前的浮动)。
  • 父元素与其第一个或最后一个子元素之间
    • 如果在父元素与其第一个子元素之间不存在边框、内边距、行内内容,也没有创建块格式化上下文、或者清除浮动将两者的 margin-top 分开;或者在父元素与其最后一个子元素之间不存在边框、内边距、行内内容、height、min-height、max-height 将两者的 margin-bottom 分开,那么这两对外边距之间会产生折叠。此时子元素的外边距会“溢出”到父元素的外面。
  • 空的块级元素
    • 如果一个块级元素中不包含任何内容,并且在其 margin-top 与 margin-bottom 之间没有边框、内边距、行内内容、height、min-height 将两者分开,则该元素的上下外边距会折叠。
  • 一些需要注意的地方:
    • 上述情况的组合会产生更复杂的外边距折叠。
    • 即使某一外边距为 0,这些规则仍然适用。因此就算父元素的外边距是 0,第一个或最后一个子元素的外边距仍然会“溢出”到父元素的外面。
    • 如果参与折叠的外边距中包含负值,折叠后的外边距的值为最大的正边距与最小的负边距(即绝对值最大的负边距)的和。
    • 如果所有参与折叠的外边距都为负,折叠后的外边距的值为最小的负边距的值。这一规则适用于相邻元素和嵌套元素。

解决办法其实也很简单,全部给他加一个 1 像素paddingTop或者borderTop就可以了,但是也有其他办法

BFC

块格式化上下文(Block Formatting Context,BFC)可以解决这个问题,但是他是啥?他算是一个独立的空间,正如他中文一样,独立块格式化上下文,被他包裹的都不会出现margin合并,浮动没有包裹等问题,举个例子。

两个之间margin正常了,然后第二个浮动也包裹住了
这里展示了浮动和margin合并的示例,均可靠 BFC 解决,触发 BFC 的情况比较多:

  • body 根元素
  • floatnone以外的值
  • position (absolutefixed)
  • displayinline-blocktable-celltable-captiontabletable-rowtable-row-grouptable-header-grouptable-footer-groupflexinline-flex元素的直接子元素、gridinline-grid元素的直接子元素、flow-root
  • overflow除了visible以外的值 (hiddenautoscroll)
  • 多列容器(元素的column-countcolumn-width不为auto,包括column-count为 1)
  • column-spanall的元素始终会创建一个新的 BFC,即使该元素没有包裹在一个多列容器中