咱们先看手册中关于宽的描述:
语法:
width:<length> | <percentage> | auto
默认值:auto
继承性:无
动画性:当值为<length> | <percentage>时
计算值:指定的值
取值:
auto:
无特定宽度值,取决于其它属性值
<length>:
用长度值来定义宽度。不允许负值
<percentage>:
用百分比来定义宽度。百分比参照包含块宽度。不允许负值
怎么理解没有继承性?
首先我们先搞清楚什么是继承关系?什么又是参考计算关系?
尽管两个嵌套的div的宽度往往是一样的,但这不代表子元素div的宽度是继承而来的,而是子元素默认撑满它能占据的所有宽度,所以某些时候显得好似继承而来。但是如果子元素有margin、padding、border,那么子元素的width值就不会跟父元素的width值一致了,而是需要参考计算而来。
而继承是什么意思?是严格的一致,就是父元素width值为100px,子元素的width值必须是100px。现实中当然不一定是这样。
所以,子元素的宽度跟父元素的宽度是参考计算关系,不是继承关系。
这个默认值auto怎么理解?
分两种情况。
第一种情况是,元素自身设置width为auto,也仍具有自身形成的width值。一般来讲这种元素就是img元素。所以,img元素在没有设置任何width的时候,或者宽度设为auto的时候,它不参考任何父元素,它的width就是资源图片自身的width。
第二种情况是非图片元素的情况。它在没有设置任何width的时候,或者宽度设为auto的时候,它的width参考父元素的width。它的盒子宽度会充满父元素的内部空间,当然最终它的width是不是等于父元素的width,要看它有没有margin、padding、border。
width不为auto的时候,是什么情况?
width不为auto,要么是具体值,要么是百分比。其中一些长度单位是相对单位,另有一些是絶対単位。参考http://www.css88.com/book/css/values/length/index.htm
说说百分比,因为只有百分比是子元素宽度与父元素宽度相关。
比如50%,假设父元素的width是1000px,那么子元素的width就是500px。如果父元素没有设定明确的width,那么浏览器先计算出父元素的width值,然后在乘以50%。
当子元素有margin、padding、border,不影响width的计算。也因此,如果有margin、padding、border,就不要以为子元素的盒子宽度是父元素width的一半了,而是父元素width的一半加上子元素的margin、padding、border的值之和。
另外说一下margin/padding/border如果设置了50%,是参考什么计算这个50%?其实也是以父元素的width为参考来计算。所以,假如子元素打算充满父元素的width,子元素可以设置width: 50%; margin: 0 25%;
,这样合起来是100%,正好充满所有空间。
到此关于宽我想说的说完了。那么高呢?你以为高跟宽同理?我只能说:Too young, too simple!
为什么这么说呢?
因为width值是一般情况下父元素影响子元素,当父元素有overflow的时候父元素不影响子元素。
而height值是恰恰相反,一般情况下子元素影响父元素,而且又分成若干种情况:
如果父元素设了height:父子互不影响。
如果父元素没有设height:
大部分情况下,子元素的盒子把父元素撑开到多高,那么父元素的height就是多高。也就是子元素的盒子高=父元素的height值。
如果子元素是inline元素,它是没有宽高的,所以也不可能撑起父元素,但媒体元素除外,比如img元素天生具有width和height值,即使它是inline元素,也一样能撑起父div。
如果子元素具有float,或position值为absolute、fixed,那么它就算有高度值,也一样不能撑起父元素。
如果在body里放一个子div,没任何样式,里面再放一个div,里面再再放一个div,所有div的width都是body的width,而高度都是0,尽管body是有高度的。
height的值是百分数的时候怎么计算?
刚才我说“height值一般情况下子元素影响父元素”,注意这个“一般情况下”,因为百分数情况下又不同了,是父元素影响子元素。也就是说父元素的内容高度是1000px的话,当子元素height设了50%,那么子元素的height就是500px。
最佳实践
之所以有上述这些规定原因很简单,盒子模型的重要原理之一就是盒子的宽度尽量充满空间,高度尽量扁。
现在我们在写代码的时候应该遵循什么原则?
慎用height的百分比值
因为百分比值会导致上层元素影响下层,而没有百分比值的时候下层元素影响上层元素,就好像职场里,你的领导给你施压影响你的决断,而你的下属要也影响你的决断,这事是不是就复杂化了?
所以,虽然width用百分比是一个非常棒的主意,但是height用百分比是很糟糕的主意,除非你明确地要把一个div垂直分成两半。
顶级div
1、width应该由最顶级的一、两级div来定,再下级的div应该根据顶级的div来计算width。这是栅格结构解决的问题。
2、顶级div可以考虑写height,当然也可以不写。因为顶级div相当于大骨架,设定height等于是“圈地”,有助于视觉上划分大板块。当然你也可以不设height,只要你能保证下级div能把顶级div撑起到满意的高度,就可以不设。
中级div
1、中级div通常不要设width,除非同一行有多个块级元素。
2、中级div到底写不写height要根据情况而定,最佳实践是:先不写height,直接去写后代元素,一直写到最底层的div,然后从最底层div元素开始设置height,由底层div来撑起各级祖先元素。除非底层div一级级撑起来之后,中级div高度让你不满意,那么你就可以给中级div专设一个height。永远记住:给中级div设定height等于给自己设定枷锁,应当尽量避免。
底层div
1、底层div的width依然是尽量别写width,除非同一行有多个块级元素。
2、底层div的高度一定要写,因为祖先元素就是靠底层div一级级撑起来的。
3、各级元素中间的间距是margin、padding解决的事情,尽量不要用height来解决。道理很简单,做网页就像是搭积木,空中楼阁是不稳定的。比如父元素的height是1000px,子元素的height加起来是800px,虽然看起来暂时没问题,但是一旦增加一个400px高的新子元素,那么子元素的height之和就是1200px,就会产生溢出问题。然后这时候你又后悔写死了1000px,想把1000px改成1200px,这时候又要去找到底哪一级div写死了height,这不是自己给自己找病么?
一句话概括就是顶层div一定要width,底层div一定要height,其他看情况。
底层inline元素和inline-block元素
很简单的常识,给inline元素设置宽高是没有任何意义的(图片除外)。所以应当给它的上级block元素设置宽高。
给一组inline-block元素设置相同的高度,有助于减少不必要的麻烦。
不要依赖不确定的height
虽然我说过,上层div要依靠下层div来撑起来,前提是下层div必须是确定的height值。比如:
- 如果最下层是img,那么img要设固定宽高,然后这个img的height才可以认为是确定值。因为img是引入的资源,宽高不确定,你不能让一个超高的图片把你页面毁了。一千字的设计、运营规范,不如几个字符的样式声明来的高效。
*如果最下层是一个p段落,一定要设置p的line-height,因为同样是14px的两种字体,默认字高也可能是不一致的。而且,你要确认文字行数是定值。如果你无法确定它行数是定值,那么它就可能撑高或者塌陷容器,那么就必须给p段落的父元素(通常是div)设定高度值。
最后说说margin和padding
margin是有叠加效应的,只有垂直方向的margin才会折叠,也就是说,水平方向的margin不会发生折叠的现象。所以,margin尽量不要设置margin-top,而是尽量永远只设定margin-bottom。
如果你不打算让子元素贴着父元素的上沿,那么也不要给子元素设margin-top,你可以给父元素设padding-top,也可以给子元素设padding-top,具体用哪个,应该视情况而定:比如,如果子元素有border,那么毫无疑问是要给父元素设padding-top,然后子元素的border才不会贴着父元素的上沿。
再如果,有两个子元素横向浮动,我希望两个子元素的内容高低不一样,那么这时候,就不能给父元素设padding-top,而是给两个子元素分别设不同的padding-top。
所以,看情况而定。