块级元素与内联元素
定义
- 块级元素:一个水平流上只能单独显示一个元素,多个块级元素则换行显示。
- 内联元素:可以和文字在一行显示,多个内联元素可以在一行显示
这里就要注意了: 块级元素和display:block不是一个概念,块级元素的display不一定是block值,也可能是table,或者list-item等值,所以只要符合块级元素的基本特征,都属于块级元素的一种。
同理,内联元素和display:inline也不是一个概念,内联元素的display不一定是inline,也可能是inline-block,所以span,a,input,button,img等都属于内联元素。
display不同值的盒子组成
首先,我们引入一个抽象概念,其实每个元素都是由两层盒子组成:外在盒子与内在盒子,
- 外在盒子:负责元素是否可以在一行显示,还是只能换行显示
- 内在盒子:负责元素的宽高,内容呈现等
可能还不是很理解吧,我们来结合一个实际例子看一下:display:inline-block
我们想想为什么inline-block既可以像块级元素那样设置宽高,又可以像内联元素那样,在一行上显示呢?我们来通过我们的两层盒子理论来说一下:inline-block,其实就是由一个外层inline盒子,和一个内层block盒子组成,这样外层盒子就可以在一行中显示了,同时我们也可以对内层block盒子设置宽高。
类比,我们看一下其他display属性值:
- display:block;其实等价于display:block-block,这样我们就既可以保证换行显示,也可以设置宽高
- display:table; 其实等价于display: block-table, 这样可以保证表格既可以换行显示,也可以设置宽高
- display:inline-table; 顾名思义,可以保证表格在一行显示,不换行,也可以设置宽高。
相信大家通过这几个例子,能够真正理解这两层盒子的意思了吧,这里还有一个注意点,width/height是作用在哪个盒子上呢? 很显然,我们上面已经提到了,它是作用与内层盒子。
除了常用的这些display属性值,我们这里罗列的display的所有属性值:
width/height的具体作用细节
1. 深藏不露的width:auto
在实际开发过程中,width的默认值为auto, 所以我们可能也用的比较少,但是它实际在页面中几乎每个页面都会或多或少用到它的特性,所以我们更需要了解它的特性,这样才有助于我们能更好的理解为什么页面会这样渲染?为什么最后出来是这样一个效果呢。
我们首先来说两个名词:外部尺寸和内部尺寸
- 外部尺寸:元素的宽度由外部元素所决定
- 内部尺寸:元素的宽度由内部元素所决定,简单来讲就是 元素的尺寸由内部的元素决定,而非由外部的容器决定。如何快速判断一个元素使用的是否 为 “内部尺寸” 呢?很简单,假如这个元素里面没有内容,宽度就是 0,那就是应用的“内 部尺寸”。
不同的元素在不同的场景下,会表现为不同的尺寸,或者换句话说,元素默认的width:auto,在不同的场景下,也会表现为不同的宽度。
接下来,我们介绍一下常见的这种场景:
- 外部尺寸:
a. 块级元素:例如div,p等标签默认宽度是100%于它的父元素,也就是说此时div的宽度完全依托于外部尺寸的宽度,即此时表现为外部尺寸
b. 格式化宽度:格式化宽度仅出现在“绝对定位模型”中,也就是出现在 position 属性值为 absolute 或 fixed 的元素中。在默认情况下,绝对定位元素的宽度表现是“包 裹性”,宽度由内部尺寸决定,但是,有一种情况其宽度是由外部尺寸决定的,是什么情 况呢?对于非替换元素,当 left/top 或 top/bottom 对立方位的属性值同时 存在的时候,元素的宽度表现为“格式化宽度”,其宽度大小相对于最近的具有定位特性 (position 属性值不是 static)的祖先元素计算。
- 内部尺寸
所有表现为内部尺寸的元素都有以下三个特性:
a. 包裹性:即元素宽度由内部元素决定,同时,它的宽度永远小于它的父元素的宽度,就好像为该元素设置了一个max-width:100%的效果类似。我们常见的inline-block 元素,浮动元素以及绝对定位元素都具有包裹性,均有类似的智能宽度行为。
想要更深刻的理解,可以参考实际案例:demo.cssworld.cn/3/2-5.php
b. 首选最小宽度
首选最小宽度是指元素最适合的最小宽度,有一个问题:假如父元素的宽度是0px,那么它的子inline-block元素宽度是多少呢?会是0吗?不会,在 CSS 世界中,图片和文字的权重要远大于布局,因此,CSS 的设计者显然是不会让图文在 width:auto 时宽度变成 0 的,此时所表现的宽度就是“首选最小宽度”。
c. 最大宽度
最大宽度就是元素可以有的最大宽度。我自己是这么理解的,“最大宽 度”实际等同于“包裹性”元素设置 white-space:nowrap 声明后的宽 度。如果内部没有块级元素或者块级元素没有设定宽度值,则“最大宽度”实际上是最大的连 续内联盒子的宽度。
2. 实际代码中如何应用width属性
首先我们再强调一下box-sizing的作用细节:display: content-box/padding-box/border-box,默认情况下,我们所设置的width都是针对content-box而言的,如果想设置其他宽度,需要手动更改box-sizing的值,这点大家基本都知道了,
这里我们重点说一下如何在实际代码中设置宽度呢?
- 记住“无宽度”这条准则,
也就是说我们在实际代码中,尽量不要设置width,因为一旦设置了定宽,那么本身的流式布局特性就消失了,所以我们能不用就不用,
但是,在某些场景下,确实需要我们设置一个定宽,那么在这样的场景下,我们要遵循另外一个原则:宽度分离原则
- 宽度分离原则
即css中的width属性不与影响宽度的padding/border,有的时候也包含margin一起使用,
也就是说下面这样的代码尽量不要写
box { width: 100px; border: 1px solid; }
.box { width: 100px; padding: 20px; }
那有什么替代方案呢?我们可以再包一层父节点
.father {width:100px}
.father .box {border: 1px solid 100px; padding: 20px}
或者,我们手动修改box-sizing的值
.box{
box-sizing: border-box;
width: 100px;
border: 1px solid;
padding: 20px
}
3. 替换与非替换元素的宽度表现
对于非替换元素,如果我们将display设置为block,那么它则会具有流动性,即宽度是由外部元素决定,但是替换元素就不一样了,替换元素无论display是inline还是block, 它的宽度是有内部元素所决定的,它不受display的影响。
例如
input {
display:block;
}
这个时候,我们将一个替换元素的display手动变成了block,那么它的宽度会变成100%于它的父元素吗?哈哈,很显然不会,它还是原来的尺寸,我们要记住替换元素的这个特性。
这个时候,如何让一个替换元素的宽度撑满水平方向呢?有人可能想到,直接width:100%啊,但是有个问题,就是input本身是有padding和border的,如果我们直接设置width:100%,实际效果可能光标就直接紧贴两边了,那么,如何优化呢?把box-sizing改成border-box啊,
是的,这也是box-sizing:border-box最常用的一个应用场景:即解决替换元素的宽度自适应问题,所以我们在实际开发中,没有必要设置 * {box-sizing:border-box}, 即没有必要将所有元素的box-sizing属性值都变成border-box, 只需要将替换元素的box-sizing重置,即
input, textarea, img, video, object {
box-sizing: border-box;
}
4. height:auto 与 height:100%
height:auto 即元素的高度是由内容的高度所决定的,当然,对于绝对定位元素来说,也会存在格式化高度的效果,格式化高度和格式化宽度类似,参考我们之前讲的即可。
height 和 width 还有一个比较明显的区别就是对百分比单位的支持。对于 width 属性, 就算父元素 width 为 auto,其百分比值也是支持的;但是,对于 height 属性,如果父元素height 为 auto,只要子元素在文档流中,其百分比值完全就被忽略了。
那么,如何让height:100%生效呢?
-
- 给父元素设置显式的高度
.parent {
height: 300px;
padding: 20px;
}
.child {
height: 100%;// 此时子元素高度为300px;
}
-
- 给自己使用绝对定位
.parent {
height: 300px;
padding: 20px;
position: relative;
}
.child {
height: 100%;//此时子元素的高度是 340px
position: absolute;
}
我们看到上面两种方式的效果还不一样,为什么呢?
这是因为绝对定位元素的百分比计算和非绝对定位元素的百分比计算是有区别的,区别 在于绝对定位的宽高百分比计算是相对于 padding box 的,也就是说会把 padding 大小值计算 在内,但是,非绝对定位元素则是相对于 content box 计算的。
这里,我们引入一个实际开发中常见的一个效果?任意高度元素的展开收起动画技术
当然,可能有相当一部分人,直接控制display的属性在none和其他值之间切换即可,但是这种方式虽然可以实现,但是效果略显生硬,如何在收起和展开时有一个过度效果呢?
可能第一反应是,收起时height设置为0,展开时height设置为auto,这样看着好像是可以的,但是实际这样实现是有问题的,因为auto 是个关键字值,并非数值,正如 height:100%的 100%无法和 auto 相计 算一样,从 0px 到 auto 也是无法计算的,因此无法形成过渡或动画效果。
那么还有更好的方法吗?不妨试试max-height即可
.element {
max-height: 0;
overflow: hidden;
transition: max-height .25s;
}
.element.active {
max-height: 666px; /* 一个足够大的最大高度值 */
}
这样我们就可以为该元素添加动画效果了,不过此方法有一个注意点,我们说设置一个足够大的最大高度值,并不意味着我们要设置的无限大,如果设置的无限大,很有可能动画带来延迟,所以在实际开发中,我们只需要设置一个足够安全的max-height即可,这样即使收起时有延迟,时间也会很短,用户很难发现,也会不会影响用户体验。