vw 和 rem 是两个神奇的 CSS 长度单位,认识它们之前,我一度认为招聘广告上的“像素级还原”是一种超能力,我想具备这种能力的人,一定专业过硬、有一双高分辨率的深邃大眼睛。

时间一晃,入坑两年,我敏捷地移动有点僵硬不算过硬的小手,将一些固定的 px 尺寸复制到代码,等待编译阶段的 vw/rem 转换,刷新浏览器的功夫,完美还原的界面映入眼前,我推了推眼镜,会心一笑。多亏了 vw 和 rem。

TLDR:极简配置 postcss-mobile-forever 增强 vw 的宽屏可访问性,限制视图最大宽度。

用 vw 和 rem 适配移动端视图的结果是一致的,都会得到一个随屏幕宽度变化的等比例伸缩视图。一般使用 postcss-px-to-viewport 做 vw 适配,使用 postcss-px2rem 配合 amfe-flexible 做 rem 适配。由于 rem 适配的原理是模仿 vw,所以后面关于适配的增强,一律使用 vw 适配做对比。

vw 适配有一些优点(同样 rem):

  • 加速开发效率;
  • 像素级还原设计稿;
  • 也许更容易被自动生成。

但是 vw 适配也不完美,它引出了下面的问题:

  1. 开发过程机械化,所有元素是固定的宽高,不考虑响应式设计,例如不使用 flexgrid 布局;
  2. 助长不规范化,不关注细节,只关注页面还原度和开发速度,例如在非按钮元素的 <div> 上添加点击事件;
  3. 桌面端难以访问,包容性降低。

前两个问题,也许要抛弃 vw、回归响应式布局才能解决,在日常开发时,我们要约束自己以开发桌面端的标准来开发移动端页面,改善这两个问题。

马克·吐温在掌握通过密西西比河的方法之后,发现这条河已经失去了它的美丽——总会丢掉一些东西,但是在艺术中比较不受重视的东西同时也被创造出来了。让我们不要再注意丢掉了什么,而是注意获得了什么。 ——《禅与摩托车的维修艺术》

后面,我们将关注第三点,介绍如何在保持现状(vw 适配)的情况下,尽可能提高不同屏幕的包容性,至少让我们在三折屏的时代能得到从前 1 倍的体验,而不是 1/3。

移动端 桌面端

上面是一个页面分别在手机和电脑上展示的截图,可以看到左图移动端的右上角没有隐藏分享按钮,所以用户是允许(也应该允许)被分享到桌面端访问的,可惜,当用户准备享受大屏震撼的时候,真的被震撼了:他不知道这个页面的技术细节是神奇的 vw,也不知道他只能用鼠标小心地拖动浏览器窗口边缘,直到窗口窄得和手机一样,最崩溃的是,当他得意地按下了浏览器的缩小按钮,页面像冰冷的机器纹丝不动,浇灭了他的最后一点自信。

限制最大宽度

由于 vw 是视口单位,因此当屏幕变宽,vw 元素也会变大,无限变宽,无限变大。

现在假设在一张宽度 600 像素的设计图上,有一个宽度 60px 的元素,最终通过工具,它会被转为 10vw。这个 10vw 元素是任意伸缩的,但是现在我希望,当屏幕宽度扩大到 700px 后,停止元素的放大。

出现了一堆枯燥的数字,不用担心,后面还有一波,请保持耐心。

首先计算 10vw 在宽 700 像素的屏幕上,应该是多少像素:60 * 700 / 600 = 70。通过最大宽度(700px)和标准宽度(600px)的比例,乘以元素在标准宽度时的尺寸(60px),得到了元素的最大尺寸 70px

接着结合 CSS 函数:min(10vw, 70px),这样元素的宽度将被限制在 70px 以内,小于这个宽度时会以 10vw 等比伸缩。

除了上面的作为正数的尺寸,可能还会有用于方位的负数,负数的情况则使用 CSS 函数 max(),下面的代码块是一个具体实现:

/**
* 限制大小的 vw 转换
* @param {number} n
* @param {number} idealWidth 标准/设计稿/理想宽度,设计稿的宽度
* @param {number} maxWidth 表示伸缩视图的最大宽度
*/
function maxVw(n, idealWidth = 600, maxWidth = 700) {
if (n === 0) return n; const vwN = Math.round(n * 100 / idealWidth);
const maxN = Math.round(n * maxWidth / idealWidth);
const cssF = n > 0 ? "min" : "max";
return `${cssF}(${vwN}vw, ${maxN}px)`;
}

矫正视图外的元素位置

上一节提供的方法,包容了限制最大宽度尺寸的大部分情况,但是如果不忘像素级还原的️初心,就会找到一些漏洞。

下面是一个图例,移动端页面提供了 Top 按钮用于帮助用户返回顶部,按照上一节的方法,Top 按钮会出现在中央移动端视图之外、右边的空白区域中,而不是矫正回中央移动端视图的右下角。

假设 Top 按钮的样式是这样的:

.top {
position: fixed;
right: 30px;
bottom: 30px;
/* ... */
}

按照标准宽度 600、最大宽度 700,上面的 30px 都被转换成了 min(5vw, 35px)bottom 没错,但 right 需要矫正。

对照上面右图矫正过的状态,right 的值 = 右半边的空白长度 + Top 按钮到居中视图右边框的长度 = 桌面端视图的一半 - 视图中线到 Top 按钮的右边框长度。

沿着第二个等号后面的思路,fixed 定位时桌面端视图一半的尺寸即为 50%,中线到 Top 按钮右边框的长度,分两种情况:

  • 在屏幕宽度大于最大宽度 700 时,为 700 / 2 - 30 * 700 / 600,即为 315px(其中 700 / 2 是中线到移动端右边框长度,30 * 700 / 600 是屏宽 600 时的 30px 在屏宽 700 时的尺寸);
  • 在屏幕宽度小于最大宽度 700 时,为 (600 / 2 - 30) / 600,即为 45%

结合 calc()min() 和上面得到的 50%315px45%,参考第二个等式,可以得到 right 的新值为 calc(50% - min(315px, 45%))。当尺寸大于移动端视图的一半时,会出现负数的情况,这时使用 max() 替换 min()

上面的计算方法是一种符合预期的稳定的方法,另一种方法是强制设置移动端视图的根元素成为包含块,设置之后,right: min(5vw, 35px) 将不再基于浏览器边框,而是基于移动端视图的边框。

postcss-mobile-forever

上面介绍了增强 vw 以包容移动端视图在宽屏展示的两个方面,除了介绍的这些,还有一点点边角情况,例如:

  • 逻辑属性的判断和转换;
  • 矫正 fixed 定位时和包含块宽度有关的 vw% 尺寸;
  • 矫正 fixed 定位时leftrightvw% 尺寸;
  • 为移动端视图添加居中样式;
  • 各种情况的判断和转换方法选择。

postcss-mobile-forever 是一个 PostCSS 插件,利用 mobile-forever 这些工作可以在编译阶段完成,上面举了那么多例子,汇总成一份 mobile-forever 配置就是:

{
"viewportWidth": 700,
"appSelector": "#app",
"maxDisplayWidth": 600
}

上面是 mobile-forever 用户使用最多的模式,max-vw-mode,此外还提供:

  • mq-mode,media-query 媒体查询模式,生成可访问性更高的样式,同样限制最大宽度,但是避免了 vw 带来的无法通过桌面端浏览器缩放按钮缩放页面的问题,也提供了更高的浏览器兼容性;
  • vw-mode,朴素地将固定尺寸转为 vw 伸缩页面,不限制最大宽度。

postcss-mobile-forever 相比 postcss-px-to-viewport 提供了更多的模式,包容了宽屏展示,相比 postcss-px2rem,无需加载 JavaScript,不为项目引入复杂度,即使用户禁用了 js,也能正常展示页面。

scale-view 提供运行时的转换方法。

优秀的模版

postcss-mobile-forever 的推广离不开开源模版的支持、尝试与反馈,下面是这些优秀的模版,它们为开发者提供了更多元的选项,为用户提供了更包容的产品:

  • vue3-vant-mobile,一个基于 Vue 3 生态系统的移动 web 应用模板,帮助你快速完成业务开发。【查看在线演示
  • vue3-vant4-mobile,基于Vue3.4、Vite5、Vant4、Pinia、Typescript、UnoCSS等主流技术开发,集成 Dark Mode(暗黑)模式和系统主题色,且持久化保存,集成 Mock 数据,包括登录/注册/找回/keep-alive/Axios/useEcharts/IconSvg 等其他扩展。你可以在此之上直接开发你的业务代码!【查看在线演示
  • fantastic-mobile,一款自成一派的移动端 H5 框架,支持多款 UI 组件库,基于 Vue3。【查看在线演示

增强后的 vw/rem 看起来已经完成了适配宽屏的任务,不过回想最初的另外两个问题,机械化的开发过程与不规范化的开发细节,没有解决。作为一名专业的前端开发工程师,请考虑使用响应式设计开发你的下一个项目,为三折屏带来 3 倍的用户体验吧。

增强 vw/rem 移动端适配,适配宽屏、桌面端、三折屏的更多相关文章

  1. 利用vw+rem实现移动web适配布局

    基本概念 1.单位 Px(CSS pixels) 像素 (px) 是一种绝对单位(absolute units), 因为无论其他相关的设置怎么变化,像素指定的值是不会变化的 其实是相对于某个设备而言的 ...

  2. 了解css中px、em、rem的区别并使用Flexible实现vue移动端的适配

    本人java菜鸟一名,若有错误,还请见谅. 1.px和em和rem的定义和区别 px:px像素,是相对单位,相对于屏幕的分辨率而言,也就是说,当屏幕的分辨率不同那么px相同,实际看到的大小也会不同. ...

  3. 移动 web 端屏幕适配 - rem

    前言 最近整理了一下以前学习前端的笔记,发现自己对移动 web 端屏幕适配(rem)这一块并没有真正理解,只是会用.接下来,把自己的一些对移动 web 端屏幕适配(rem)的思考记录下来. rem 介 ...

  4. 九、响应式发:rem和less(适配移动端)

    一.响应式开发 响应式开发优先适配移动端又兼容到pc端 官网:https://less.bootcss.com/usage/ 教程:https://www.w3cschool.cn/less/ rem ...

  5. 移动端屏幕适配(rem+js)

    什么是移动端适配 在制作webapp时,一个很关键的问题就是适配各种机型不同屏幕的大小,让每种机型上的布局看起来都尽量一样. 也就是说用同一套代码在不同分辨率的手机上跑时,页面元素间的间距.留白,以及 ...

  6. webapp新体验Rem实现移动端网页适配详解资源

    本来想写一篇,webapp使用Rem的问题,查了一下相关rem的介绍之后,发现很多平台已经解释的很清楚了,图文并茂,于是我便想将其解释资源整理一些,方便以后自己查阅. 腾讯ISUX:web app变革 ...

  7. 移动端font-size适配方案

    概述 这是我研究移动端页面时的思考,记录下来供以后开发时参考,相信对其他人也有用.由于我写移动端页面写的还比较少,一些问题都还没遇到,所以我的这篇博文不免有些错误的地方,还请大佬多多指正. 这篇文章是 ...

  8. Web 端屏幕适配方案

    基础知识 像素相关 1.像素 :像素是屏幕显示最小的单位. 2.设备像素 :设备像素又称物理像素(physical pixel),设备能控制显示的最小单位,我们可以把这些像素看作成显示器上一个个的点. ...

  9. 国内外移动端web适配屏幕方案

    基础知识点 设备像素:设备像素又称物理像素(physical pixel),设备能控制显示的最小单位,我们可以把这些像素看作成显示器上一个个的点. iPhone5的物理像素是640X1136. PS: ...

  10. 移动端font-size适配方案(续)

    概述 之前写过一篇移动端font-size适配方案,但是在实践过程中,还是发现当时的思维太局限了,视野太窄了,所以现在补充更新一下,记录下来,供以后开发时参考,相信对其他人也有用. 我上一篇博文主要有 ...

随机推荐

  1. 018.CentOS升级内核

    一 更新yum源 1 [root@localhost ~]# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org 2 [root@lo ...

  2. 【牛客刷题】HJ10 字符个数统计

    题目链接 简单的说这题就是字符串去重以后检查长度.如果用Java的话,可以遍历字符串,然后利用Set来进行去重,最后统计Set的size就可以了.但是如果是Go语言,则稍微麻烦点.基本思路就是用map ...

  3. 2. 基于MCU应用的EMC指南

    1. 硬件 主要的噪声感受器和发生器是印刷电路板(PCB)上的轨道和布线,特别是MCU附近的轨道和布线.因此,防止噪声问题的第一步行动涉及到PCB布局和电源设计.一般来说,MCU周围的元器件数量越少, ...

  4. DMS:直接可微的网络搜索方法,最快仅需单卡10分钟 | ICML 2024

    Differentiable Model Scaling(DMS)以直接.完全可微的方式对宽度和深度进行建模,是一种高效且多功能的模型缩放方法.与先前的NAS方法相比具有三个优点:1)DMS在搜索方面 ...

  5. GC终结标记 SuspendEE 是怎么回事

    一:背景 1. 讲故事 写这篇是起源于训练营里有位朋友提到了一个问题,在 !t -special 输出中有一个 SuspendEE 字样,这个字样在 coreclr 中怎么弄的?输出如下: 0:000 ...

  6. NeoVim 安装

    NeoVim 官网 安装 macOS brew install neovim Windows 使用 winget: winget install Neovim.Neovim 也可以使用 scoop: ...

  7. AWS Data Analytics Fundamentals 官方课程笔记 - Variety, Veracity, Value

    Variety structured data applications include Amazon RDS, Amazon Aurora, MySQL, MariaDB, PostgreSQL, ...

  8. 使用 nuxi info 查看 Nuxt 项目详细信息

    title: 使用 nuxi info 查看 Nuxt 项目详细信息 date: 2024/9/5 updated: 2024/9/5 author: cmdragon excerpt: 摘要:文章介 ...

  9. CoST: 时间序列预测中分离季节趋势特征的对比学习《CoST: CONTRASTIVE LEARNING OF DISENTANGLED SEASONAL-TREND REPRESENTATIONS FOR TIME SERIES FORECASTING》(时序预测、表征学习、对比学习、因果关系、分离趋势季节特征)

    2022/6/18 11:32,简单记录一下随笔(因为不写点东西,根本注意力不集中,看5分钟可能要摸鱼10分钟,还是要写点,突然发现,草稿箱里最早的一篇没写完的博客是去年的7月2日,救命啊,我拖了一年 ...

  10. Angular 18+ 高级教程 – Component 组件 の Control Flow

    前言 Control Flow 是 Angular v17 版本后推出的新模板语法,用来取代 NgIf.NgForOf.NgSwitch 这 3 个 Structure Directive. Stru ...