width和height作用的具体细节

更新时间: 2024-03-08 08:14:56

# 深藏不露的width:auto

# 外部尺寸与流体特性

# 正常流宽度

在页面中随便扔一个<div>元素,其尺寸表现就会和这水流一样铺满容器。这就是block容器的流特性。这种特性在所有浏览器的表现都是一致的。

所谓流特性,并不是看上去的宽度100%那么简单,而是一种margin/border/padding和content内容区域自动分配水平空间的机制。

因此,想让一个div自动铺满是不需要写“width:100%”的,多此一举而。

# 格式化宽度

格式化宽度仅出现在“绝对定位模型”中,也就是出现在position属性为absolutefixed的元素中。

在默认情况下,绝对定位元素的宽度表现是“包裹性”,宽度由内部尺寸决定。

但是对于非替换元素,当left/righttop/bottom对立方位的属性同时存在时,元素的宽度表现为“格式化宽度”,其宽度大小相对于最近的具有定位特性(position属性不是static)的祖先元素计算。

“格式化宽度”具有完全的流体性,也就是margin、border、padding和content内容区域同样会自动分配水平(和垂直)空间。

# 内部尺寸与流体特性

所谓“内部尺寸”,简单来讲就是元素的尺寸由内部的元素决定,而非由外部的容器决定。

Q:如何快速判断一个元素使用的是否为“内部尺寸”

假如这个元素里面没有内容,宽度就是0,那就是应用的“内部尺寸”。

内部尺寸的三种表现形式:

# 包裹性

包裹的意思就是“shrink-to-fit”,即收缩到合适,除了“包裹性”,还有“自适应性”。

所谓“自适应性”,指的是元素尺寸由内部元素决定,但永远小于“包含块”容器的尺寸(除非容器尺寸小于元素的“首选最小宽度”)。

因此如果一个元素的display属性值是inline-block,那么即使其里面内容再多,只要是正常文本,宽度也不会超过父容器。

“按钮”元素是 inline-block 元素

按钮文字越多宽度越宽(内部尺寸特性),但如果文字足够多,则会在容器的宽度处自动换行(自适应特性)。(button标签按钮才会自动换行,input标签按钮默认 white-space:pre,需要将pre值重置为默认的normal)

“包裹性”对实际开发有什么作用呢?

请看这个需求: 页面某个模块的文字内容是动态的,可能是几个字,也能是一句话。然后希望文字少的时候居中显示,文字超过一行就居左显示。该如何实现呢?

核心css代码如下:

.box {
    text-align: center;
}
.content {
    display: inline-block;
    text-align: left;
}
1
2
3
4
5
6
7

这样,box的center控制的是 content元素居中,而content元素在文字少的时候没有那么长,因此整体文字看起来就是居中的,一旦超过一行,content元素的宽度占满box,box的center看起来就不起作用了(实际上还是起作用的,只不过是content太宽了,此时content上设置的text-align:left就显现出来了。)

文字内容

除了inline-block元素,浮动元素以及绝对定位元素都具有包裹性,均有类似的只能宽度行为。

# 首选最小宽度

所谓“首选最小宽度”,指的是元素最适合的最小宽度。

Q:假如外部容器宽度为0,请问里面的inline-block元素的宽度是多少?

是0吗?不是!!!在CSS世界中,图片和文字的权重要远大于布局。此时所表现的宽度就是“首选最小宽度”。如下的例子:

我是内容
display:inline-block;

“首选最小宽度”具体表现规则如下:

  • 东亚文字(如中文)最小宽度为每个汉字的宽度。
  • 西方文字最小宽度由特定的连续的英文字符单元决定

    并不是所有的英文字符都会组成连续单元

    一般会终止于空格(普通空格)短横线问号以及其他非英文字符等。

    如果想让英文字符和中文一样,每个字符都用最小宽度单元,可以试试使用CSS中的word-break:break-all

  • 类似图片这样的替换元素的最小宽度就是该元素内容本身的宽度

应用:实现凹凸效果


看不懂?把鼠标浮上去就知道了。核心css代码如下:

.ao {
    display: inline-block;
    width: 0;
}
.ao:before {
    content: 'love你love';
    outline: 2px solid #cd0000;
    color:#fff;
}
1
2
3
4
5
6
7
8
9

# 最大宽度

“最大宽度”就是元素可以有的最大宽度。如果内部没有块级元素或者块级元素没有设定宽度值,最大宽度实际上是最大的“连续内联盒子”的宽度。

连续内联盒子指的是全部都是内联级别的一个或一堆元素,中间没有任何的换行标签或其他块级元素。

# width值作用的细节

css盒模型
我们的内在盒子又被分成四个盒子:

  • content box
  • padding box
  • border box
  • margin-box
    margin(透明)
    border
    padding
    content

width:100px是如何作用到div元素上的呢?

width:100px 作用在 content box上,由于div元素默认的padding、border和margin都是0,因此,该div所呈现的宽度就是100像素。

所以,假如padding和border不为0,该元素的宽度就不止100了。

# CSS流体布局下的宽度分离原则

所谓“宽度分离原则”,就是CSS的widths属性不与影响宽度的padding/border(有时候包括margin)属性共存。

那怎么写呢?如下,width单独用一个标签:

.father {
    width: 180px;
}
.son {
    margin: 0 20px;
    padding: 20px;
    border: 1px solid;
}
1
2
3
4
5
6
7
8

这样写的好处是不用计算width了,但是会多一层嵌套标签。

# 改变width/height作用细节的box-sizing

# box-sizing的作用

box-sizing改变了width作用的盒子。默认情况下,width是作用在content box上的,box-sizing还可以是 border-box。此时,content-box从宽度值中释放,形成了局部的流动性,和padding,border一起自动分配width。

谨慎写 *{box-sizing:border-box}

  1. 这种做法易产生没必要的消耗
    通配符 * 应该是一个谨慎用的选择器,因为它会选择所有的标签。

  2. 这种做法并不能解决所有问题
    只有当元素没有水平margin的时候,box-sizing才能真正无计算,box-sizing绝不是发明来让那些对block水平元素滥用width属性的人少出bug的。

# 关于height:100%

height和width有个比较明显的区别就是对百分比单位的支持。

对于width属性,就算父元素width为auto,其百分比也是支持的。

但是对于height属性,如果父元素height为auto,只要子元素在文档流中,其百分比值完全就被忽略了。

注意

对于普通文档流中的元素,百分比高度值想起作用,其父级必须有一个可以生效的高度值!

# 为何 height:100% 无效

先来思考一下下面的红色父级元素宽度为什么没有进一步增大?

红色背景是父级

<div class="box">
    <img src="1.jpg">
    <span class="text">红色背景是父级</span>
</div>
1
2
3
4
.box {
    display: inline-block;
    white-space: nowrap;
    background-color: #cd0000;
}
.text {
    display: inline-block;
    width: 100%;
    background-color: #34538b;
    color:#fff;
}
1
2
3
4
5
6
7
8
9
10
11

为什么要这样表现呢?

要明白其中的原因要先了解浏览器渲染的基本原理。

首先,先下载文档内容,加载头部的样式资源(如果有的话),然后按照从上而下、自外而内的顺序渲染DOM内容。即:先渲染父元素,后渲染子元素,是有先后顺序的。

因此,当渲染到父元素的时候,子元素的width:100%并没有渲染,宽度就是图片加文字的内容的宽度;等渲染到文字这个子元素的时候,父元素宽度已经固定,此时的width:100%就是已经固定好的父元素的宽度。宽度不够怎么办?溢出就好了,overflow属性就是为此而生的。

为什么宽度支持,高度不支持100%呢?

规范中给出了答案,“如果包含块的高度没有显示指定(即高度由内容决定),并且该元素不是绝对定位,则计算值为auto”

因为解释成了auto,因此没有办法和百分比进行计算。

# 如何让元素支持 height:100% 效果

  1. 设定显示的高度

比较常见的就是

html,body { height: 100% }
1
  1. 使用绝对定位
div {
    height: 100%;
    position: absolute;
}
1
2
3
4

此时height:100%有计算值的,在绝对定位下,即使祖先元素的height计算为auto也是如此。

绝对定位元素 和 非绝对定位元素的百分比计算有区别

绝对定位的宽高百分比计算是相对于 padding-box 的,也就是说会把 padding 大小值计算在内。 非绝对定位元素则是相对于 content-box 计算的。