css移动端页面单位,视窗单位在移动端上的使用技巧

视窗单位一直都存在争议,部分原因是因为移动端浏览器对如何实现视窗单位有着自己的看法,这样就让本来简单的事情变得更加复杂化。

一个典型的示例是:vw的计算是否要包含浏览器的滚动条?那么网站的导航或页面控件呢?这些应该算在计算中吗?还有一些设备本身的物理属性(比如iPhone X的刘海)是不容忽视的。

首先,了解一下背景

有关于如何计算视窗单位的规范描述的相当模糊。对于移动设备,我们通常关心的是高度,所以让我们具体来看一下视窗单位中的vh:

vh unit:Equal to 1% of the height of the initial containing block.

直译过来,大致的意思是“vh等于初始包含块高度的1%”。

所以,在处是设备和特定的浏览器的区别方面,没有明确的指导。

vh最初是由浏览器的当前视窗计算的。如果你打开浏览器开始加载一个网站,1vh等于你屏幕高度的1%(减去浏览器界面)。

1vh = window.innerHeight。

但是!如果你开始滚动,那就另当别论了。一旦你通过了一个浏览器界面,比如地址栏,vh值就会更新,结果就是内容的跳跃。

iOS的Safari浏览器是最早更新其实现的移动端浏览器之一,它选择根据屏幕的最大高度为vh的计算值(为vh定义一个固定值)。这样,一旦地址栏离开视窗,用户在页面上也不会看到内容的闪跳。Chrome的移动端浏览器大约在一年前也相应的做了这样的调整。

虽然使用固定值很好,但这也意味着如果地址栏在视窗中,就不能有一个全屏高度的元素。元素的底部将被裁剪。

1aac0e6c8695a2270669819881e8247b.png

正如上图所示,当地址栏在视窗中时(左图),元素的底部被裁剪,但我们想要的是元素底部不被裁剪(右图)。

CSS自定义属性:调整大小的技巧

我突然想到,CSS自定义属性和几行JavaScript代码可能是获得所需的一致和正确大小的完美解决方案。

在JavaScript中,你始终可以使用全局变量window.innerHeight获得当前视窗的值。这个值考虑了浏览器的界面,并在其可见性(visibility)发生变化时进行了更新。诀窍就是将视窗(viewport)值存储在CSS自定义属性(CSS变量)中,并将其应用于元素,而不是vh单位。

假设我们在例子中设置一个CSS自定义属性:--vh。这意味着我们将在CSS像下面这样使用这个自定义属性:

.my-element {

height: 100vh; /* 为不支持自定义属性的浏览器做降级处理 */

height: calc(var(--vh, 1vh) * 100);

}

好了,这就搞定了,就是这么的简单。现在让我们使用JavaScript来获得视窗的内部高度(window.innerHeight):

// 首先获取视窗高度,再乘以1%得到vh单位的值

let vh = window.innerHeight * 0.01;

// 把--vh的值设置到文档的根元素中

document.documentElement.style.setProperty('--vh', `${vh}px`);

因此,我们告诉JavaScript获取视窗的高度,然后占这个值的1%,所以我们就可以将值指定为视窗高度单位值。然后使用JavaScript在:root中创建CSS自定义属性--vh。

因此,我们现在就可以像使用其他单位一样使用--vh作为高度值,然后乘以100就能得到我们想要的高度值。

亲自体验一下,调整视窗的高度,在根元素html中可以看到--vh值是动态变化的:

b34faf72309db25ff522c97616da4c16.gif

还有一个小细节

虽然我们的工作看上去已经完成了,但是对于追求细节的同学而言,可能已经发现了,当视窗的高度改变时,不会自动更新元素的大小。那么我们接着在上面的示例上进行调整。

我们可以监听window的resize事件来更新--vh的值。如果用户旋转设备屏幕,比如从横向到纵向,或者导航移动到滚动视窗之外,这样就非常方便。

// 监听resize事件

window.addEventListener('resize', () => {

let vh = window.innerHeight * 0.01;

document.documentElement.style.setProperty('--vh', `${vh}px`);

});

更新--vh的值将会触发页面重绘,用户可能会感觉页面在跳动。因此,我并不是说这个技巧应该用于每个项目,或者替换vh单位的所有用法,但是只有当你需要你的用户拥有一个确切的视窗单位值时才使用。

此外,你可能希望resize事件实现debounce方法,以避免在用户调整浏览器窗口大小时触发许多事件。通过本文,你可以了解更多相关信息:通过示例解释Debouncing和Throtting。

你现在可以调整视窗大小查看上面的示例,并注意CSS自定义属性--vh值的变化:

6d977d725b74448f76e1292cb81746e7.gif

虽然我最近在一个项目中使用了这种技术,它确实很有用,但是在替换浏览器的默认行为时,你应该要三思而后行。(例如,这会在::focus一起出现)。另外,现在的浏览器更新速度非常快,所以要小心,今天的解决方案明天可能就行不通了。

同时,我希望这篇文章对你有所帮助。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值