口(viewport)代表当前可见的计算机图形区域。在Web浏览器术语中,通常与浏览器窗口相同,但不包括浏览器的UI, 菜单栏等——即指你正在浏览的文档的那一部分。
一般我们所说的视口共包括三种:布局视口、视觉视口和理想视口,它们在屏幕适配中起着非常重要的作用。
布局视口(layout viewport):当我们以百分比来指定一个元素的大小时,它的计算值是由这个元素的包含块计算而来的。当这个元素是最顶级的元素时,它就是基于布局视口来计算的。
所以,布局视口是网页布局的基准窗口,在PC浏览器上,布局视口就等于当前浏览器的窗口大小(不包括borders 、margins、滚动条)。
在移动端,布局视口被赋予一个默认值,大部分为980px,这保证PC的网页可以在手机浏览器上呈现,但是非常小,用户可以手动对网页进行放大。
我们可以通过调用document.documentElement.clientWidth / clientHeight来获取布局视口大小。
视觉视口(visual viewport):用户通过屏幕真实看到的区域。
视觉视口默认等于当前浏览器的窗口大小(包括滚动条宽度)。
当用户对浏览器进行缩放时,不会改变布局视口的大小,所以页面布局是不变的,但是缩放会改变视觉视口的大小。
例如:用户将浏览器窗口放大了200%,这时浏览器窗口中的CSS像素会随着视觉视口的放大而放大,这时一个CSS像素会跨越更多的物理像素。
所以,布局视口会限制你的CSS布局而视觉视口决定用户具体能看到什么。
我们可以通过调用window.innerWidth / innerHeight来获取视觉视口大小。
布局视口在移动端展示的效果并不是一个理想的效果,所以理想视口(ideal viewport)就诞生了:网站页面在移动端展示的理想大小。
如上图,我们在描述设备独立像素时曾使用过这张图,在浏览器调试移动端时页面上给定的像素大小就是理想视口大小,它的单位正是设备独立像素。
上面在介绍CSS像素时曾经提到页面的缩放系数=CSS像素 / 设备独立像素,实际上说页面的缩放系数=理想视口宽度 / 视觉视口宽度更为准确。
所以,当页面缩放比例为100%时,CSS像素=设备独立像素,理想视口=视觉视口。
我们可以通过调用screen.width / height来获取理想视口大小。
<meta> 元素表示那些不能由其它HTML元相关元素之一表示的任何元数据信息,它可以告诉浏览器如何解析页面。
我们可以借助<meta>元素的viewport来帮助我们设置视口、缩放等,从而让移动端得到更好的展示效果。
<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
上面是viewport的一个配置,我们来看看它们的具体含义:
Value 可能值 描述 width 正整数或device-width 以pixels(像素)为单位, 定义布局视口的宽度。 height 正整数或device-height 以pixels(像素)为单位, 定义布局视口的高度。 initial-scale 0.0 - 10.0 定义页面初始缩放比率。 minimum-scale 0.0 - 10.0 定义缩放的最小值;必须小于或等于maximum-scale的值。 maximum-scale 0.0 - 10.0 定义缩放的最大值;必须大于或等于minimum-scale的值。 user-scalable 一个布尔值(yes或者no) 如果设置为 no,用户将不能放大或缩小网页。默认值为 yes。
为了在移动端让页面获得更好的显示效果,我们必须让布局视口、视觉视口都尽可能等于理想视口。
device-width就等于理想视口的宽度,所以设置width=device-width就相当于让布局视口等于理想视口。
由于initial-scale=理想视口宽度 / 视觉视口宽度,所以我们设置initial-scale=1;就相当于让视觉视口等于理想视口。
这时,1个CSS像素就等于1个设备独立像素,而且我们也是基于理想视口来进行布局的,所以呈现出来的页面布局在各种设备上都能大致相似。
上面提到width可以决定布局视口的宽度,实际上它并不是布局视口的唯一决定性因素,设置initial-scale也有肯能影响到布局视口,因为布局视口宽度取的是width和视觉视口宽度的最大值。
例如:若手机的理想视口宽度为400px,设置width=device-width,initial-scale=2,此时视觉视口宽度=理想视口宽度 / initial-scale即200px,布局视口取两者最大值即device-width 400px。
若设置width=device-width,initial-scale=0.5,此时视觉视口宽度=理想视口宽度 / initial-scale即800px,布局视口取两者最大值即800px。
浏览器为我们提供的获取窗口大小的API有很多,下面我们再来对比一下:
SS 过去只有四个你需要知道的视口单元,它们几乎可以涵盖所有可以想象的用例。 然而,随着时间的推移和技术的变化,这四个视口单元不再足以处理所有用例。 由于CSS 增加了 20 个视口单元,这听起来很多,但它们被分解为六个主要的视口单元,并带有三个独特的修饰符,总共有 24 种组合。
主要的4种视口单元
主要的 CSS 视口单位是 vw、vh、vmin 和 vmax。 您以前可能使用过或看过这些单位,所以我在解释它们时会尽量简短。
VW
vw 代表 Viewport Width,代表视口宽度的百分比。 放置在 vw 之前的数字是视口宽度的百分比。 例如,如果您写了 10vw,那么这将代表视口宽度的 10% 的长度。
视口代表你屏幕的大小,如果你在一个宽度为 1920 像素的大桌面上,10vw 将代表 192 像素。 如果您使用的是宽度为 300px 的手机,那么 10vw 将只有 30px。
VH
vh 代表视口高度,与 vw 完全相同,但它代表高度而不是宽度。 这两个单元可以组合使用,以轻松地使元素填满屏幕的整个大小。
VMIN 和 VMAX
vmin 和 vmax 表示最大和最小视口尺寸。 例如,如果您使用的是 300 像素宽和 800 像素高的手机,则 vmin 将代表视口的宽度,而 vmax 将代表设备的高度。 如果您需要根据屏幕的最小/最大尺寸调整元素的大小,这些单位非常有用。 例如,下面的 CSS 将创建一个尽可能大的正方形,而不会在任何方向溢出,因为它永远不会大于最小屏幕尺寸的 100%。
两个新的视口单位
CSS 一直在尝试从严格的顶部/底部、左/右、高度/宽度模型转变为更动态的开始/结束、块/内联模型。 此更改的主要原因是它可以让你更容易地采用不同的编写方向。 如果您的整个应用程序从水平书写方向切换到垂直书写方向,则顶部/底部或宽度/高度的概念不一定意味着相同的事情,因为如果您想在文本上方和下方添加填充,这将被表示 作为垂直书写系统中的左右填充,而不是填充顶部和底部。 这就是 CSS 添加 vi 和 vb 视口单元的原因。
VI
vi 代表 Viewport Inline,代表文档的内联方向。 在水平书写方向上,这对应于视口的宽度,而在垂直书写方向上,这表示视口的高度。 记住 inline 方向的简单方法是记住它与文本的方向相同。 另一种记住这一点的方法是,如果您有两个彼此相邻的内联元素(例如两个跨度),那么它们堆叠的方向就是您的内联方向。
VB
vb 代表 Viewport Block,代表文档的块方向。 这与 vi 相反,因此在水平书写方向上,这将对应于视口高度,在垂直文档中,这将表示视口的宽度。 如果你很难记住这个单元,请记住块方向始终是块元素(例如两个 div)相互堆叠的方向。
视口单位修饰符
到目前为止,我们已经介绍了六种主要类型的视口单元,但是当您的视口可以改变大小时,您可以将三种不同的修改器添加到单元中以使它们表现不同。例如,当您在手机上浏览网页时,您可能会注意到向下滚动时 URL 栏会消失。发生这种情况时,您的视口在技术上会更改大小,因为现在 URL 栏不再占据您的视口的一部分。当前的 CSS 单元无法处理视口大小的这种变化,这就是添加这些修饰符的原因。
这些修饰符是 s、l 和 d。为了使用修饰符,您只需将修饰符放在数字之后和单位之前,例如 10svw。这为 6 个视口单元中的每一个提供了 4 个总组合。大众、svw、lvw 和 dvw。
到目前为止,我们在本文中介绍的所有内容都没有使用完全有效的修饰符。当您在单元上不使用修饰符时,例如 10vw 或 10vh,浏览器将自动默认使用基于浏览器实现的 3 个修饰符之一。
s修饰符
s 修饰符代表 Small 并表示可能的最小视口。 在我们的手机示例中,这将是显示 URL 栏时视口的大小。 如果您将一个元素设置为 100svh,它将占据屏幕高度的 100%,具体取决于显示 URL 栏时的屏幕大小。 URL 栏是否可见无关紧要,此单元将始终根据显示 URL 栏时的视口大小来确定其大小。
l修饰符
l 修饰符代表Large,代表最大可能的视口。 这几乎与 s 修饰符相反。 在我们的手机示例中,这将是没有显示 URL 栏时的视口大小。 如果您将元素设置为 100lvh,则当 URL 栏不显示时,它会根据屏幕大小占据屏幕高度的 100%。 URL 栏是否可见无关紧要,如果 URL 栏未显示,此单元将始终根据视口的大小确定其大小,这意味着如果您将元素设置为 100lvh 并且 URL 栏显示它在技术上将 比屏幕大。
d修饰符
d 修饰符代表动态,代表当前视口大小。 这就像 s 和 l 修饰符的组合。 在我们的手机示例中,无论 URL 栏是否显示,这始终是当前视口的大小。 如果我们的 URL 栏正在显示,则 d 修饰符与 s 修饰符大小相同,而如果 URL 栏未显示 d 修饰符与 l 修饰符大小相同。
在显示和隐藏 URL 栏之间的过渡期间,此单元将动态缩放大小,因此它始终会填满所有可用空间。 如果您需要确保元素始终根据视口调整大小,这很好,但可能会很费力,因为随着大小的不断变化,它会导致大量重绘。
浏览器支持
对于每一个很酷的 CSS 功能,您总是需要考虑浏览器支持,不幸的是,浏览器对这些新视口单元的支持不是很好。 目前,这些新单元的支持率为 15.2%,并且实际上仅在 Safari 和 Firefox 中得到支持。 缺乏支持的原因是该提案仍处于工作草案阶段,这意味着它还处于生命周期的早期阶段,距离成为官方 CSS 还很远。
结论
虽然 24 个单位可能听起来很多,但实际上只有 6 个单位和三个相对简单的修饰符。 然而,这些简单的组合给了我们构建完美 CSS 布局的强大能力。
*CSS Viewport units(视口单位)**在过去几年已经出现了,随着时间的推移,越来越多的开发人员开始使用它们。它们的好处在于为我们提供了一种不需要使用J avaScript 就能以动态的方式调整大小的方法。而且,如果它失效,也有很多备用方案。
在本文中,我们将学习 CSS Viewport units(视口单位)以及如何使用它们,并用列举一些常见问题及其解决方案和用例,让我们开始吧。
根据CSS规范,视口百分比单位相对于初始包含块的大小,它是web页面的根元素。
视口单位为:vw,vh,vmin和vmax。
vw单位表示根元素宽度的百分比。1vw等于视口宽度的1%。
vw单位表示根元素宽度的百分比,1vw等于视口宽度的1%。
假设我们有一个元素与以下CSS:
.element {
width: 50vw;
}
当视口宽度为500px时,50vw计算如下
width = 500*50% = 250px
vh单位表示根元素高度的百分比,一个vh等于视口高度的1%。
我们有一个元素与以下CSS:
.element {
height: 50vh;
}
当视口高度为290px时,70vh计算如下:
height = 290*70% = 202px
大家都说简历没项目写,我就帮大家找了一个项目,还附赠【搭建教程】。
vmin表示视口的宽度和高度中的较小值,也就是vw 和 vh 中的较小值。如果视口宽度大于其高度,则将根据高度计算该值。
我们以下面的例子为例。
我们有一个横屏手机,其中有一个元素具有vmin单元。在这种情况下,值将根据视口高度计算,因为它小于宽度。
.element {
padding-top: 10vmin;
padding-bottom: 10vmin;
}
这是vmin的计算方式:
正如你所猜测的,计算结果如下所示
padding-top = (10% of height) = 10% * 164 = 16.4px
padding-bottom = (10% of height) = 10% * 164 = 16.4px
vmax与vmin相反,该值是vw 和 vh 中的较大值。
我们以下面的例子为例。
.element {
padding-top: 10vmax;
padding-bottom: 10vmax;
}
计算结果如下:
padding-top = (10% of width) = 10% * 350 = 35px
padding-bottom = (10% of width) = 10% * 350 = 35px
视口单位基于页面的根元素,而百分比则基于它们所在的容器。因此,它们彼此不同,但各自都有各自的用处。
CSS 视口单位非常适合响应式排版。例如,我们可以将以下内容用作文章标题:
.title {
font-size: 5vw;
}
标题的font-size将根据视口宽度增加或缩小。就像提供的字体大小是视口宽度的5%一样。但是,如果没有适当的测试就直接使用它可能会踩到坑。让我们看下面的视频:
体大小变得非常小,这不利于可访问性和用户体验。据我所知,移动设备上的最小字体大小不应该不于14px。在GIF中,不小于10px。
要解决该问题,我们需要为标题提供最小字体大小,可以使用 calc()
.title {
font-size: calc(14px + 2vw);
}
calc()CSS函数将具有一个最小值14px,并在些基础上添加2vw的值,有了这些,字体大小值就不会变得太小。
另一个需要考虑的重要问题是字体大小在大屏幕上的表现,例如 27” iMac。会发生什么呢?你猜对了,字体大小为95px左右,这是一个很大的值。为了防止这种情况,我们应该在某些断点上使用媒体查询并更改字体大小。
@media (min-width: 1800px) {
.title {
font-size: 40px;
}
}
通过重置字体大小,我们可以确保大小不会太大。您可能还需要添加多个媒体查询,但这取决于你自己,也取决于项目的上下文。
事例地址:https://codepen.io/shadeed/pen/fa989837c6379770cce49f0be6daa3e3
有时,我们需要一个section来获取100%的视口高度,为此,我们可以使用viewport高度单位。
.section {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
通过添加 height: 100vh,我们可以确保section 高度将采取100%的视口。此外,我们添加了一些flexbox来处理水平和垂直居中的内容。
事例源码:https://codepen.io/shadeed/pen/dc4e82f3c873cc64ae5c5bc4a3f4ef9f?editors=1100
在大屏幕上,网站内容有时候很少,footer 没有粘在底部。这很正常,也不被认为是一种不好的做法。但是,还有改进的余地。考虑下面代表问题的示图:
为了解决这个问题,我们需要给内容(content)一个高度,它等于视口高度- (header + footer)。动态地做到这一点是很困难的,但是使用CSS的视口,这是很容易的。
如果header 和footer的高度是固定的,那么可以将calc()函数和视口单位结合起来,如下所示:
header,
footer {
height: 70px;
}
main {
height: calc(100vh - 70px - 70px);
}
不能保证此解决方案始终有效,尤其是对于footer而言。在我的职业生涯中,我没有使用固定高度的页脚,因为在例如不同的屏幕尺寸下,此footer是不可行的。
通过将100vh设置为body元素的高度,然后可以使用flexbox来使main元素占用剩余空间。
body {
min-height: 100vh;
display: flex
flex-direction: column;
{
main {
/* This will make the main element take the remaining space dynamically */
flex-grow: 1;
}
这样,问题就解决了,无论内容长度如何,我们都有一个粘性footer。
事例源码:https://codepen.io/shadeed/pen/c735b26b8fa97ee685b38084448b3f85?editors=1100
假设我们有一个作品集来展示我们的响应式设计工作,并且我们有三种设备(移动设备、平板电脑和笔记本电脑)。每个设备包含一个图像。目标使用 CSS 来响应适配这些页面。
通过使用CSS网格和视口单位,我们可以使其完全动态的响应式。
<div class="wrapper">
<div class="device laptop"></div>
<div class="device mobile"></div>
<div class="device tablet"></div>
</div>
视口单位也可以用于grid- *属性,也用于border,border-radius和其他属性。
.wrapper {
display: grid;
grid-template-columns: repeat(20, 5vw);
grid-auto-rows: 6vw;
}
.mobile {
position: relative;
z-index: 1;
grid-column: 2 / span 3;
grid-row: 3 / span 5;
}
.tablet {
position: relative;
z-index: 1;
grid-column: 13 / span 7;
grid-row: 4 / span 4;
border-bottom: 1vw solid #a9B9dd;
border-right: solid 3vw #a9B9dd;
}
.laptop {
position: relative;
grid-column: 3/span 13;
grid-row: 2 / span 8;
}
/* Viewport units are used for the bottom, left, right, height, and border-radius. Isn't that cool? */
.laptop:after {
content:"";
position:absolute;
bottom: -3vw;
left: -5.5vw;
right: -5.5vw;
height: 3vw;
background-color: #a9B9dd;
border-radius: 0 0 1vw 1vw;
}
事例源码:https://codepen.io/shadeed/pen/2da0f2b70699769f8de3220ff4465bc6?editors=1100
我注意到一个用例最适合编辑版面。一个子元素,即使父元素的宽度受到限制,它也会占据视口100%的宽度。考虑下面:
.break-out {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
让我们把它分解一下,这样我们就能一点一点地理解所有这些属性是如何工作的。
1.添加 width: 100vw
最重要的一步,将图像的宽度设置为100%的视口。
2.添加 margin-left: -50vw
为了使图像居中,我们需要给它一个负的边距,其宽度为视口宽度的一半。
3.添加 left: 50%
最后,我们需要将图像向右推,其值为父宽度的50%。
事例地址:https://codepen.io/shadeed/pen/828f12b1ef7fa7211584ff5c7b82d2fa?editors=1100
我想到的另一个有趣的用例是使用视口单位来表示元素之间的间距。这可以与margin、top、bottom和grid-gap等值一起使用。使用时,间距将基于视口宽度或高度,这对于使布局更具动态性可能很有用。
对于模态,我们需要将它们从视口顶部推入。通常,使用top属性进行此操作,并使用百分比或像素值。但是,对于视口单位,我们可以添加一个可以根据视口高度改变的间距。
.modal-body {
top: 20vh;
}
事例地址:https://codepen.io/shadeed/pen/f77a0d58947c64c2b3dadbd887700db5?editors=1100
页面header 是充当页面介绍的部分。它通常具有标题和描述,并且其中上下边缘的高度固定或填充
例如,有以下的CSS的样式:
.page-header {
padding-top: 10vh;
padding-bottom: 10vh;
}
.page-header h2 {
margin-bottom: 1.5vh;
}
使用vh单位用于页面标题的 paddding,以及标题下方的边距。注意间距如何变化!
事例源码:https://codepen.io/shadeed/pen/43024fa031519e316e95bb3ce47f2b22?editors=1100
该用例是关于页面标题元素的顶部和底部padding 。当视口较小(移动)时,通常会减少padding。通过使用vmin,我们可以在视口较小尺寸(宽度或高度)的基础上获得合适的顶部和底部 padding。
.page-header {
padding: 10vmin 1rem;
}
事例源码:https://codepen.io/shadeed/pen/f335c2f43b960a2c70ea057228ddc5b9?editors=0100
我们可以使用vw单位创建响应元素,以保持其纵横比,而不管视口大小如何。
首先,需要先确定所需的纵横比,对于此示例,使用9/16。
section {
/* 9/16 * 100 */
height: 56.25vw;
}
事例源码:https://codepen.io/shadeed/pen/dc4e82f3c873cc64ae5c5bc4a3f4ef9f?editors=0100
你知道大多数网站使用的顶部边框吗?通常,它的颜色与品牌颜色相同,这会赋予一些个性。
我们支持边框的初始值为3px。如何将固定值转换为视口对象?下面是如何计算它的等效的vw。
vw = (Pixel Value / Viewport width) * 100
视口宽度用于估计像素值与所需vw单位之间的比率。
对于我们的示例,我们为 header 添加以下样式:
.header {
border-top: 4px solid #8f7ebc;
}
在我的情况下,视口宽度为1440(这不是固定数字,请用你自己的数字替换)
vw = (4 / 1440) * 100 = 0.277
.header {
border-top: 0.277vw solid #8f7ebc;
}
更好的是,我们可以使用一个基本像素值,而视口单元可以是一个附加的。
.header {
border-top: calc(2px + 0.138vw) solid $color-main;
}
移动设备中存在一个常见问题,即使使用100vh,也会滚动,原因是地址栏的高度可见。Louis Hoebregts 写了一篇关于这个问题的文章,并给出了一个简单的解决方案。
.my-element {
height: 100vh; /* 不支持自定义属性的浏览器的回退 */
height: calc(var(--vh, 1vh) * 100);
}
// 首先,我们得到视口高度,我们乘以 1% 得到一个vh单位的值
let vh = window.innerHeight * 0.01;
// 然后,将`--vh`自定义属性中的值设置为文档的根目录一个属性
document.documentElement.style.setProperty('--vh', `${vh}px`);
事例源码:https://codepen.io/shadeed/pen/1d18ca2d23ec0038c759dc62dc3fd8c3?editors=0110
作者:Ahmad shaded 译者:前端小智 来源:sitepoint
原文:https://ishadeed.com/viewport-units/
*请认真填写需求信息,我们会在24小时内与您取得联系。