此文档是关于高度随宽度变化的固定宽高比。
一个简单固定宽高比的例子
我们知道display: block
的元素 (即块级元素) 的宽度会占满父元素的 content area/box 宽度,当我们在body
元素下放一个div
元素设置其高度为0并且设置padding-bottom
的值为百分比时就得到了一个“高度随宽度变化的固定宽高比的div
”。比例的值即为padding-bottom
的值。
实现上面 gif 里的效果,用到的 HTML 是在 body 元素里添加
<div class="container"></div>
CSS 是
body {margin: 0;}div.container {height: 0;padding-bottom: 20%;background-image: linear-gradient(45deg, #2989d8 0%, #7db9e8 100%);}
原理
这种形式的固定宽高比的原理是因为当元素的上下padding
值用百分比的形式时是相对于包含块的宽度而言的。
div.container
元素的包含块就是body
元素,判断依据是这的第一条,div.container
元素的默认position
是static
,它的父元素body
是一个 block 元素,所以body
就是它的包含块。设置在div.container
上的padding-bottom
的值当用百分比时就是相对于body
的宽度而言的。
在浏览器里,当通过调整窗口大小使页面body
的宽度变化时,div.container
的高度会按照padding-bottom
设置的百分比相对应body
的宽度来变化,又由于div.container
的宽度始终是父元素body
的宽度,所以实际上div.container
的高度是按照padding-bottom
设置的百分比相对自身的宽度来变化的,这样就实现了div.container
的固定宽高比。
注意事项
这里面需要注意区分一点的是:在 CSS 里我们设置元素的width
或者height
值并不是在浏览器端检查元素时看到的元素的宽度或者高度值。我们在浏览器端检查元素时看到的宽度或者高度始终等于内容区 (content area/box)、内边距 (padding) 和边框 (border) 之和的,而 CSS 里设置元素的width
和height
包不包括内边距和边框受box-sizing
的影响,默认box-sizing: content-box
是不包括内边距和边框的。
我们平时说的一个元素的宽度或者高度是指在浏览器端检查元素时看到的宽度或者高度,始终是内容区、内边距和边框之和。
由于div.container
的height
设置为0,在浏览器端我们看到div.container
高度的大小就是padding-bottom
的大小。div.container
显示背景图是因为background-image
默认会在内边距里显示,跟background-color
一样都受background-clip
(默认值为border-box
) 的影响。
一个有内容的固定宽高比例子
因为div.container
的height
为0,即没有 content area/box 无法容下文字。
这时如果我们想在div.container
里嵌一个元素放置文字并且也让该元素固定宽高比该怎么做呢?有的同学可能会回答说:嵌入一个块级元素div
时设置它的height
为 100% 不就行了。尝试过的同学会知道这样做是不行的,当
div.container {height: 0;padding-bottom: 20%;}div.container div {height: 100%;background-image: linear-gradient(45deg, #2989d8 0%, #7db9e8 100%);}
由这的第一条:
…, the containing block is formed by the edge of thecontent boxof the nearest ancestor element…
可知,嵌入的div.container div
元素的height
用百分比写时是相对包含块内容区的高度而言的。而嵌入元素div.container div
的包含块div.container
元素内容区的高度默认就是height
的值,这里设置的是0。所以“嵌入一个块级元素div
时设置它的height
为 100%”是不行的。
这里我们需要嵌入的元素的height
用百分比写时是相对包含块内容区加上内边距的高度而言,这的第二条
If the
position
property isabsolute
, the containing block is formed by the edge of thepadding boxof the nearest ancestor element that has aposition
value other thanstatic
(fixed
,absolute
,relative
, orsticky
).
就是我们需要的。CSS 改成下面即可。
div.container {position: relative;height: 0;padding-bottom: 20%;}div.container div {position: absolute;height: 100%;width: 100%;background-image: linear-gradient(45deg, #2989d8 0%, #7db9e8 100%);}
由这的absolute
解释 (… no space is created for the element in the page layout …) 可知div.container div
的width
为 0,并非占满父元素的 content area/box 宽度,所以需要添加width: 100%;
。
接下来,我们可以将文字放入div.container div
里并添加额外的样式。比如这里我们加入文字 “Hello World!” 并向div.container div
额外添加以下 CSS
display: flex;justify-content: center;align-items: center;font-size: 5vw;
就可以得到下面的效果。