CSS流体布局下的宽度分离原则
所谓的“宽度分离原则”,就是CSS中的width属性不与影响宽度的padding/border(有时候包括margin)属性共存,也就是不能出现以下的组合:
div {
width: 100px;
border: 1px solid #cd0000;
}
/* OR */
div {
width: 100px;
padding: 20px;
border: 1px solid #cd0000;
}
有人可能会问:不这么写,那该怎么写?很简单,分离。width独占一层标签,而padding、border、margin利用流动性在内部自适应呈现。
.father {
width: 100px;
}
.child {
margin: 0 20px;
padding: 16px;
border: 1px solid #cd0000;
}
为什么要宽度分离?
在前端领域,一提到分离,作用一定是便于维护。比方说,样式和行为分离、前后端分离或者这里的“宽度分离”。
道理其实很简单,当一件事情的发展可以被多个因素所左右的时候,这个事情最终的结果就会变数很大而不可预期。宽度在这里也是类似,由于盒子尺寸中的4个盒子都能影响宽度,自然页面元素的最终宽度就很容易发生变化而导致意想不到的布局发生。例如,下面这个简单的CSS:
.box {
width: 100px;
border: 1px solid #cd0000;
}
此时宽度是102px。然后,设计师希望元素边框内有20px的留白,这时候,我们会增加padding设置。
.box {
width: 100px;
padding: 20px;
border: 1px solid #cd0000;
}
结果此时宽度变成了142px,大了40px,跟原来宽度差异明显,显然布局很容易出问题。为了不影响之前的布局,我们还需要通过计算减去40px的padding大小才行:
.box {
width: 60px; // 通过计算,减去40px
padding: 20px;
border: 1px solid #cd0000;
}
但是,如果使用了宽度分离,事情就会轻松很多:
.father {
width: 102px;
}
.child: {
border: 1px solid #cd0000;
}
嵌套一层标签,父元素宽度,子元素因为width使用的是默认值auto,所以会如水流般自动填满父级容器。因此,子元素的content box宽度就是100px,和上面直接设置width为100px表现一样。
然后同样的场景,设计师希望元素边框内有20px留白,这时候,只要设置子元素padding即可:
.father {
width: 102px;
}
.child: {
padding: 20px;
border: 1px solid #cd0000;
}
然后……就没有然后了,宽度还是102px,子元素的content box自动变成了60px,和上面反例的表现一样。没错,自动变化了,就是这么智能!
虽然表现一样,但是写代码的人的体验却大不一样:width、padding、border混用的时候,任何修改我们都需要实时去计算现在width应该设置多大才能和之前的占用的宽度一样,而后面width分离的实现,我们没有任何计算,要padding留白,加一下就好,要修改边框宽度,改一下就好,浏览器会自动计算,完全不用担心尺寸的变化。不需要烧脑子去计算,页面结构反而更稳固。
有人可能会有这样的疑问:使用“宽度分离”之后,多使用了一层标签,增加了HTML成本。没错,过深的嵌套是会增加页面渲染和维护成本。但是,如果不考虑替换元素,这世界上绝大多数的网页,只需要一个width设定就可以了,没错,只需要一个width,就是最外层限制网页主体内容宽度的那个width,而里面所有元素都没有理由再出现width设置。所以,“宽度分离”虽然多了一层标签,但最终也就多了一层标签而已,这个成本跟收益比起来简直就是毛毛雨。