视窗单位已经存在好几年了,并且在主要浏览器中 几乎获得了完美支持,但我仍然不断地发现新的和令人兴奋的使用方法。我认为回顾基础知识,然后总结一些我最喜欢的用例会很有趣。
视窗单位是什么?
在 2011 年到 2015 年之间,CSS 规范中出现了四个新的“视窗相对”单位,作为 W3C 的 CSS 值和单位模块级别 3 的一部分。这些新单位——vw
、vh
、vmin
和 vmax
——与现有的长度单位(如 px
或 em
)的工作原理类似,但代表当前浏览器视窗的百分比。
- 视窗宽度 (
vw
) – 视窗全宽的百分比。10vw
将解析为当前视窗宽度的 10%,或者在480px
宽的手机上解析为48px
。%
和vw
之间的区别最类似于em
和rem
之间的区别。%
长度相对于本地上下文(包含元素)宽度,而vw
长度相对于浏览器窗口的总宽度。 - 视窗高度 (
vh
) – 视窗全高的百分比。10vh
将解析为当前视窗高度的10%
。 - 视窗最小值 (
vmin
) – 视窗宽度或高度的百分比,取较小者。10vmin
将在纵向方向上解析为当前视窗宽度的10%
,而在横向方向上解析为视窗高度的10%
。 - 视窗最大值 (
vmax
) – 视窗宽度或高度的百分比,取较大者。10vmax
将在纵向方向上解析为当前视窗高度的10%
,而在横向方向上解析为视窗宽度的10%
。遗憾的是,奇怪的是,vmax
单位目前在 Internet Explorer 或 Edge 上不可用。
虽然这些单位源自视窗高度或宽度,但它们都可以在接受长度的所有地方使用——从 font-size
到定位、边距、填充、阴影、边框等等。让我们看看我们能做些什么!
响应式排版
使用视窗单位进行响应式排版变得非常流行——建立根据当前视窗大小而增长和缩小的字体大小。使用简单的视窗单位进行字体大小设置有一个有趣(危险)的效果。正如您所看到的,字体缩放非常快——在一个很小的范围内从不可读的小字体调整到超大字体。

这种直接缩放显然对于日常使用来说过于剧烈。我们需要更细微的东西,带有最小值和最大值,以及对增长率的更多控制。这就是 calc()
变得有用的地方。我们可以将一个基本大小用更稳定的单位(比如 16px
)与一个更小的视窗相对调整(0.5vw
)结合起来,让浏览器进行计算:calc(16px + 0.5vw)
通过更改基本大小和视窗相对调整之间的关系,您可以更改增长率的剧烈程度。在标题上使用更高的视窗值,并观察它们比周围文字更快地增长。这允许在更大的屏幕上获得更动态的排版比例,同时在移动设备上保持字体约束——无需媒体查询。您还可以 将此技术应用于您的行高,让您可以以与 font-size
不同的速率调整行高。
body {
// font grows 1px for every 100px of viewport width
font-size: calc(16px + 1vw);
// leading grows along with font,
// with an additional 0.1em + 0.5px per 100px of the viewport
line-height: calc(1.1em + 0.5vw);
}
对我来说,这已经足够复杂了。如果我需要为快速增长的标题约束顶端,我可以使用一个单独的媒体查询,无论何时文本变得太大。
h1 {
font-size: calc(1.2em + 3vw);
}
@media (min-width: 50em) {
h1 {
font-size: 50px;
}
}
突然间,我真希望有一个 max-font-size
属性。
其他人已经开发了更复杂的计算和 Sass 混合宏来指定特定媒体查询处的精确文字大小范围。现有的几篇 CSS-Tricks 文章解释了这种技术并提供了代码段,帮助您入门
我认为在大多数情况下这有点过分了,但您的实际情况肯定会有所不同。
全高布局、英雄图片和固定页脚
全高(或高度受限)布局有很多变体——从桌面风格的界面到英雄图片、宽敞的设计和 固定页脚。视窗单位可以帮助解决所有这些问题。
在桌面风格的全高界面中,页面通常被分成单独滚动的部分——带有像标题、页脚和侧边栏这样的元素,这些元素在任何大小下都保持在适当的位置。这在如今的许多网络应用程序中很常见,而 vh
单位使它变得更加简单。以下是一个使用新的 CSS Grid 语法的示例
查看 CodePen 上 Miriam Suzanne (@mirisuzanne) 的 全高 CSS Grid 笔记。
在 body
元素上的单个声明 height: 100vh
将您的应用程序限制在视窗的高度内。确保在内部元素上应用 overflow
值,这样您的内容就不会被切断。您还可以使用 Flexbox 或 浮动 来实现这种布局。请注意,全高布局可能会在一些移动浏览器上造成问题。有一个 针对 iOs Safari 的巧妙解决方案,我们使用它来处理最明显的边缘情况之一。
固定页脚可以用类似的技术创建。将您的 body
元素的 height: 100vh
更改为 min-height: 100vh
,页脚将保持在屏幕底部,直到被内容推下。
查看 CodePen 上 Miriam Suzanne (@mirisuzanne) 的 使用 CSS Grid 的固定页脚 笔记。
将 vh
单位应用于不同元素的 height
、min-height
或 max-height,以创建全屏部分、英雄图片等等。在新的 OddBird 重构 中,我们用 max-height: 55vh
限制了我们的英雄图片,这样它们就不会将标题推离页面。在我的个人网站上,我使用了 max-height: 85vh
来营造更多以图片为主导的外观。在其他网站上,我将 min-height: 90vh
应用于部分。
以下是一个展示了 最大高度的英雄猫咪和最小高度的部分 的示例。结合所有这些技巧,可以让您对内容如何填充浏览器窗口以及如何 响应不同的视窗 有强大的控制。
流体纵横比
约束元素的高度与宽度之比也很有用。这对于嵌入内容(如视频)特别有用。 Chris 之前写过这方面的内容。在过去,我们会使用容器元素上的 %
基填充和内部元素上的绝对定位来实现这一点。现在,我们有时可以使用视窗单位来实现这种效果,而无需额外的标记。
如果我们可以依靠视频全屏显示,我们可以将高度设置为相对于视窗全宽
/* full-width * aspect-ratio */
.full-width {
width: 100vw;
height: calc(100vw * (9/16));
}
这种数学运算不需要在浏览器中使用 calc
完成。如果您使用的是像 Sass 这样的预处理器,它在预处理器中完成数学运算的效果一样好:height: 100vw * (9/16)
。如果您需要约束最大宽度,您也可以约束最大高度
/* max-width * aspect-ratio */
.full-width {
width: 100vw;
max-width: 30em;
height: calc(100vw * (9/16));
max-height: calc(30em * (9/16));
}
以下是一个演示了两种选项的示例,使用 CSS 自定义属性(变量)来使数学运算更具语义性。随意修改数字以查看事物如何移动,始终保持正确的比例
查看 CodePen 上 Miriam Suzanne (@mirisuzanne) 的 使用视窗单位的流体比例 笔记。
Chris 在他的预视窗单位文章中更进一步,我们也一样。如果我们需要实际的 HTML 内容在设定比例内缩放,就像演示文稿幻灯片通常所做的那样,该怎么办?
我们可以使用与容器相同的视窗单位来设置我们所有内部字体和大小。在这种情况下,我使用 vmin
来设置所有内容,这样内容会随着容器高度和宽度的变化而缩放
查看 CodePen 上 Miriam Suzanne (@mirisuzanne) 的 使用视窗单位的流体幻灯片比例 笔记。
打破容器
多年来,将受限文字与全宽背景混合在一起一直很流行。根据您的标记或 CMS,这可能会变得很困难。如何将内容从受限容器中分离出来,使其完全填充视窗?
同样,视窗单位可以派上用场。这是我们在新的 OddBird 网站上使用的另一个技巧,在该网站上,静态网站生成器有时会限制我们对标记的控制。只需要几行代码就能让它起作用。
.full-width {
margin-left: calc(50% - 50vw);
margin-right: calc(50% - 50vw);
}
在 Cloud Four 和 CSS-Tricks 上都有关于这种技术的更深入的文章。 CSS Tricks.
越来越奇怪
当然,如果您开始尝试,还可以使用视窗单位做更多的事情。看看这个纯 CSS 滚动指示器(由一位名叫 Mike 的人制作),它在背景图片上使用视窗单位。
查看代码笔 CSS only scroll indicator by Mike (@MadeByMike) on CodePen.
您还使用视窗单位看到了或做了什么?发挥创意,向我们展示结果!
滚动指示器纯粹是疯狂的 :)
同意!
同意!
的确
很棒的内容。视窗单位对于响应式网页设计非常有用,这篇文章很有帮助。谢谢
vw 和 vh 太棒了!虽然 iOS 10* 和最新的 Facebook 应用程序 Webview 目前在 100vh 大于 innerHeight 时存在一些问题,因此全页面 Web 应用程序会从屏幕底部消失。
这似乎可以解决问题:https://stackoverflow.com/questions/35421247/wrong-viewport-page-height-in-embedded-facebook-browser-in-ios-9-x
您能解释一下滚动指示器是如何工作的吗?它只是一个三角形渐变,被
body::before
覆盖,并且被z-index: -1
巧妙地夹在渐变和内容之间吗?就是这样。三角形是这样创建的
100%
) 减去窗口高度 (100vh
) (在标题 (129px
) 以下)。这会稍微限制三角形的的高度,因为滚动条位于页面顶部,您永远无法真正滚动到底部。好文章,Miriam。以下是我最近在视窗单位方面所做的事情:将它们与线性方程式和断点混合:多流体尺寸 (https://www.smashingmagazine.com/2017/05/fluid-responsive-typography-css-poly-fluid-sizing/)
相关地,使用视窗单位作为
font-size
的一个缺点是它们不可访问。调整浏览器文本大小会忽略使用纯视窗单位的任何内容。如果在calc()
中使用视窗单位,它们会调整大小,但它们的更改速率取决于方程式中使用的像素值。除了这个缺点之外,视窗单位非常棒!
好文章!我对浏览器跟不上已经存在多年的 CSS/HTML 规范感到非常沮丧。总是要等好几年才能实现我们昨天就需要的酷炫功能和工具。感谢 Miriam,这将被收藏起来。
视窗单位可以用来创建背景图片视差效果(类似于滚动指示器示例)吗?
您好 Miriam,
感谢您撰写这篇文章。
您提到了用于流体纵横比的 calc 或 sass,但我认为这些计算不需要它们。我们不能简单地写以下内容吗?
当然,这也有效。我总是喜欢用尽可能多的语义提示(如变量名)来展示我的数学运算,而不是粘贴一个看起来很随机的数字,比如
56.25
。我希望代码除了工作之外,还要有意义和可读性。您的注释做了类似的事情 - 添加了一些线索,您还可以添加更多 - 但为什么不直接在代码中显示数学运算呢?哦,这有道理。我的逻辑是,如果不需要为了使代码更易于访问(可怜的 Opera Mini 用户!)而使用
calc()
,以及性能(尽管我不知道使用 calc() 的性能成本……)。但正如您所说,它确实需要额外的注释……目前看来,Safari 10.1 中存在一个错误,它不支持包含视窗单位作为函数中值的 calc() 函数的字体大小值的流体调整大小。显然,这不会影响移动用户,但对于那些想要使用 macOS 中的 Safari 调整浏览器窗口大小的人来说,这确实很糟糕。我已经向苹果公司提交了这个错误,所以我们会看看是否能对此做些什么。
在您的粘性页脚示例中,您将列值设置如下
grid-template-columns: minmax(auto, 12em) 5fr;
那么,在这行代码中,5fr 单位是什么意思?因为,如果我们把它设置为 1fr,它不会改变任何东西!
是的,在那里没有区别,因为它们是唯一使用的“分数”。可以是 999999fr,效果相同,因为 999999/999999 = 1,就像 5/5 = 1 或 1/1 = 1 一样。
哈哈,是的。您抓住了。我认为我最初使用的是
fr
单位作为侧边栏,并且在移动到auto
和em
后,从未更改过主宽度。大多数这些都不适用于 IE 或 Edge,因此它们的使用价值有限。
IE 和 Edge 的使用价值也很有限。
如果您将视窗单位用于
font-size
,您将覆盖浏览器内置的缩放文本功能。无论您是在 calc() 函数中使用它,都是如此。这将破坏最基本的 Web 可访问性功能,并剥夺用户的控制权。用户唯一可以使用视窗单位大小缩放文本的方法是更改视窗大小。这看起来很随机,在很多情况下它将不起作用。
请不要破坏我的缩放功能!
请忽略我的评论 - 我想我理解错了。如果您使用带有 vw 和 px 或 em 的 calc 函数定义
font-size
,那么正常的浏览器缩放功能将完美无缺。“或在宽度为 480px 的手机上使用 48px”===》“或在宽度为 480px 的手机上使用 48vx”