【面试题】前端 移动端自适应?

news2024/9/29 18:41:22

移动端 h5 开发中有一个绕不开的话题:移动端自适应方案。移动端的设备尺寸不尽相同,要把 UI 设计图较好地展示在移动端上,需要让 h5 页面能自适应设备尺寸。接下来将对移动端自适应的相关概念、方案和其他一些常见问题做个介绍。

概念简介

大厂面试题分享 面试题库

前后端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库


设备像素、设备独立像素和CSS像素

设备像素(物理像素)

1 个设备像素就代表 1 个真实的像素点,是设备能控制显示的最小单位。iphone6 的设备像素 750 * 1334,也就是说 iphone6 屏幕上有 750 * 1334 个像素点。

设备独立像素(逻辑像素)

与设备无关的逻辑像素,代表可以通过程序控制使用的虚拟像素,是一个总体概念。iphone6 的设备独立像素 375 * 667,正好是设备像素的一半,所以 1 个设备独立像素就用 4 个设备像素显示。所以苹果的 retina 高清屏的画质就更加锐利,没有颗粒感,显示效果出众。

CSS 像素

CSS 中的长度单位,在 CSS 中使用的 px 都是指 CSS 像素。默认情况下 1 css 像素 = 1 设备独立像素。

当页面缩放比不为 1 时,CSS 像素和设备独立像素不再对应。比如当页面放大 200%,则 1 个 CSS 像素等于 4 个设备独立像素。

设备像素比

设备像素比 (DevicePixelRatio) 指的是设备物理像素和逻辑像素的比例 。比如 iPhone6 的 DPR 是2。

设备像素比 = 物理像素 / 逻辑像素。可通过 window.devicePixelRatio 获取,CSS 媒体查询代码如下

@media (-webkit-min-device-pixel-ratio: 3), (min-device-pixel-ratio: 3) {
   ...
}
复制代码

布局视口、视觉视口、理想视口

布局视窗(Layout Viewport)

一般移动设备的浏览器都默认设置了一个布局视口,并且该视口最常见的分辨率为 980px。

由于 980px 的宽度大于大部分手机屏幕的宽度,为了将页面显示完全,只能对原来的页面进行缩放,如果不进行缩放,那么就需要左右拖动来浏览。(大部分浏览器默认采用缩放方式)

视觉视窗(Visual Viewport)

它指的是浏览器的可视区域,也就是我们在移动端设备上能够看到的区域。默认与当前浏览器窗口大小相等,当用户对浏览器进行缩放时,不会改变布局视口的大小,但会改变视觉窗口的大小。

理想视口(Ideal Viewport) 理想中的视口。这个概念最早由苹果提出,其他浏览器厂商陆续跟进,目的是解决在布局视窗下页面元素过小的问题,显示在理想视口中的页面具有最理想的宽度,用户无需进行缩放。所以理想视窗就相当于把布局视窗修改成一个理想的大小,这个大小和物理视窗基本相等。

Viewport Meta

我们可以使用 viewport meta 标签来进行布局视窗的设置,常见的配置如下:

<metaname="viewport"content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />复制代码

viewport meta 各个属性介绍:

  • width:设置 layout viewport 的宽度

  • initial-scale:设置页面与 layout viewport 之间的初始放大系数

  • minimum-scale:设置最小放大系数(用户可以虽小的最小程度)

  • maxmum-sacle:最大放大系数(用户可以放大的最大程度,比如 300%)

  • height:设置 layout viewport 的高度。应该设置布局视图的高度。它在任何地方都不受支持。(一般不会规定高度)

  • user-scalable:设置为 no,意味着阻止用户进行缩放操作。最好不要使用。

自适应方案


响应式布局

使用媒体查询,百分比布局,flex 布局等方式来让页面自适应,Bootstrap 就是使用响应式布局完成适配移动端的。

如上图可以看到,Bootstrap 使用了 @media 来控制不同视窗下的展示。

@mediaonly screen and (min-width: 375px) {
  .logo { width : 62.5px; }
}

@mediaonly screen and (min-width: 360px) {
  .logo { width : 60px; }
}

@mediaonly screen and (min-width: 320px) {
  .logo { width : 53.3333px; }
}
复制代码

rem 方案

rem(font size of the root element)是 CSS3 新增的一个相对单位,是指相对于根元素的字体大小的单位。这个方案阿里有个对应的库 lib-flexible,我们将介绍个他的原理和最终效果。

因为 rem 是相对于根元素字大小的单位,我们在编写标准尺寸的 h5 页面时可以使用 rem 作为单位,最后根据设备大小动态设置根元素大小,这样即可实现自适应。

举个例子:

  1. 比如设计稿是 750 * 1334 尺寸的,根元素设定一个基础大小 100px,页面完成后如果是展示在 828 * 1562 机型上,计算出对应的根元素大小为 110.4 px。此时页面内使用 rem 单元的元素对应的 px 也会按比例增大,就实现了自适应。

  1. 接下来我们要按照设计稿写各个布局宽高大小,只需要把 px 转换成 rem,比如 50px 就对应 0.5rem(根元素为100px)。这边可以使用 postcss-pxtorem 插件或者 less 定义函数都可以。

来看下 lib-flexible 经典版本核心部分:

var doc = window.document;
var docEl = doc.documentElement;
functionrefreshRem(){
    var width = docEl.getBoundingClientRect().width; // 获取html宽度// ...var rem = width / 10; // 这边 10 的计算:750 ÷ 75 = 10,也就是基础大小是 75px,上边例子中是 100px
    docEl.style.fontSize = rem + 'px';
    flexible.rem = win.rem = rem;
}

// 页面出现或者大小变化时重新设置
win.addEventListener('resize', function() {
    clearTimeout(tid);
    tid = setTimeout(refreshRem, 300);
}, false);
win.addEventListener('pageshow', function(e) {
    if (e.persisted) {
        clearTimeout(tid);
        tid = setTimeout(refreshRem, 300);
    }
}, false);
复制代码

还有一部分是根据 window.devicePixelRatio 设置 meta 的 scale(注意2.0版本不会设置),比如在 iphone6 下 scale 会设置成 0.5,此时 1px 的效果如下:

iphone6 下 scale 为 1 时,1px 的效果如下:

可以看到 scale 为 0.5 的情况下,线更细。

如果设置 scale 保持都为 1,根据上边自适应方案,编写的 1px 代码最终在 iphone6 中渲染的是 0.5px,但是部分设备版本不支持 0.5px,可能会解释成 0,这时就要单独处理 1px 问题。

小结:目前个人项目中使用较多的是只动态设置根元素大小,meta 设置为 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />,1px 的问题看情况单独处理。

vw、vh 方案

lib-flexible 官方已经不推荐使用 rem 方案了,推荐使用 vw、vh 方案。

由于viewport单位得到众多浏览器的兼容,lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport来替代此方。

vw、vh、vmin、vmax 是一种视窗单位,也是相对单位。它相对的不是父节点或者页面的根节点。而是由视窗(Viewport)大小来决定的,单位 1,代表类似于 1%。

  • vw:视窗宽度的百分比(1vw 代表视窗的宽度为 1%)

  • vh:视窗高度的百分比

  • vmin:当前 vw 和 vh 中较小的一个值

  • vmax:当前 vw 和 vh 中较大的一个值

举个例子,看下 vw、vh 方案是怎么实现自适应的:

1、设计稿是 750 * 1334 尺寸的,页面布局宽高大小都按设计稿写,到时类似使用 less 或者 postcss-px-to-viewport 插件转换成 vw。比如一个元素宽度为 75px, 到时会自动转换成 10vw,在页面尺寸为 828 * 1562 下,这个元素对应的宽度为 82.8px,实现了自适应。

可以看到对比 rem 方案,这边省去了设置根元素大小,更加简洁。

postcss-px-to-viewport 插件的一些配置:

module.exports = {
  plugins: {
    'postcss-px-to-viewport': {
         unitToConvert: "px", // 要转化的单位       viewportWidth: 750, // UI设计稿的宽度       unitPrecision: 6, // 转换后的精度,即小数点位数       propList: ["*"], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换     viewportUnit: "vw", // 指定需要转换成的视窗单位,默认vw       fontViewportUnit: "vw", // 指定字体需要转换成的视窗单位,默认vw      selectorBlackList: ["wrap"], // 指定不转换为视窗单位的类名,       minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换       mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false      replace: true, // 是否转换后直接更换属性值       exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配       
    }
  }
}
复制代码

vw、vh 的兼容性好,基本所有的现代浏览器都支持。

其他问题


1px 问题

自从 2010 年 iPhone4 推出了 Retina 屏开始,移动设备屏幕的像素密度越来越高,于是便有了 2 倍屏、3 倍屏的概念。在 iPhone6 的设备像素比 dpr = 2 下,一个 CSS 像素等于两个物理像素,实际效果就会比 750 * 1334 设计稿的宽。

1px 不行,我们可以写成 0.5px 么? 在 PC 端浏览器的最小识别像素为 1px。在手机端,不同手机浏览器对小数点像素的处理效果就更千奇百怪了,显示成 0、0.5px、1px 都是有可能的。所以 1px 问题还是需要单独处理。

下面介绍几个常用的解决方案:

viewport + rem

这个上述 rem 适配方案中有提到。在 devicePixelRatio = 2 时,输出 viewport:<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no"> 此时 1px 就和 750 x 1334 设计稿中的 1px 效果一致。

伪类 + transform 实现

原理是利用 :before 或者 :after 模拟 border ,并 transform 的 scale 缩小一半

.scale-1px {
  position: relative;
  border:none;
}

// 一条 border.scale-1px:after {
  content: '';
  position: absolute;
  bottom: 0;
  background: #000;
  width: 100%;
  height: 1px;
  transform: scaleY(0.5);
  transform-origin: 00;
}

// 四条 border.scale-1px:after {
    content: '';
    width: 200%;
    height: 200%;
    position: absolute;
    top: 0;
    left: 0;
    border: 1px solid #bfbfbf;
    border-radius: 4px;
    transform: scale(0.5,0.5);
}
复制代码

除了以上两种,还有使用边框图片(border-image)、背景图(background-image),阴影(box-shadow) 这些去实现 1px。

多倍图

在多倍屏的情形下,一般设计会出 2x 和 3x 的图片,在对应的机型下使用对应的图片。这边可以是 less 或 sass 配合媒体查询去实现。

.bg-image(@url) {
  background-image: url("@{url}@2x.png");
  background-size: 100%;
  background-repeat: no-repeat;
  @media (-webkit-min-device-pixel-ratio: 3), (min-device-pixel-ratio: 3) {
    background-image: url("@{url}@3x.png");
  }
}

// 使用
.className {
    .bg-image('~@/assets/images/advisor/bg_tag')
}
复制代码

总结


移动端适配方案目前已经比较成熟了,无论使用 rem 还是 vw 方案都是可以的。个人推荐使用 vw 方案,在处理下 1px 问题。

大厂面试题分享 面试题库

前后端面试题库 (面试必备) 推荐:★★★★★

地址:前端面试题库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/353321.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是 Web3?解读未来的去中心化网络:The Decentralized Internet of the Future Explained

目录 互联网的演化 什么是 Web 1.0? 什么是 Web 2.0? Web 2.0 变现与安全性 什么是 Web 3.0? 原生支付 创立公司的新方式 Web3 中的身份 如果你读到这篇文章,那么你已经是当代互联网世界的一员了。我们现在使用的网络和10年前大不相同。所以,互联网是怎么演化的,…

Centos7 安装 Mysql 8.0.32,详细完整教程(好文章!!)

mysql5.7的安装方式参考之前的文章&#xff1a; centos7 安装 Mysql 5.7.27&#xff0c;详细完整教程&#xff08;好文章&#xff01;&#xff01;&#xff09;_HD243608836的博客-CSDN博客 一、检查mysql版本冲突 先检查是否已经存在mysql&#xff0c;若存在卸载&#xff0…

大数据第一轮复习笔记(2)

Spark ./spark-submit --class com.kgc.myspark01.WordCount --master yarn --deploy-mode cluster /opt/myspark01-1.0-SNAPSHOT.jar 1.Client向YARN的ResourceManager申请启动Application Master。Client中创建SparkContext同时初始化中将创建DAGScheduler和TASKScheduler…

固态继电器的五大优势

固态继电器的优点和五个关键优势&#xff0c;现代电气控制系统因二极管、晶体管和晶闸管等固态器件的发明而得到极大的增强。对于加热器和电机等大负载设备&#xff0c;固态继电器可能比传统的机械继电器具有巨大的优势。 虽然并非适用于所有情况&#xff0c;但它们具有许多吸引…

前端——周总结系列五

JS的Map对象 概述 ES6新增的一种数据结构Map&#xff0c;对操作键值对很友好&#xff0c;键值对集合&#xff0c;提供属性和方法供开发者使用。存有键值对&#xff0c;键可以是任何数据类型&#xff1b;按照原始插入顺序存储&#xff08;FIFO&#xff09;原则&#xff1b;具有…

关于ChatGPT,我们到底在担心什么?

“ChatGPT已对教育产生了巨大冲击” “ChatGPT对程序员造成了哪些影响” “ChatGPT会取代人类的哪些工作&#xff1f;” “谷歌宣布推出类ChatGPT产品Bard” “Bing新版本引入ChatGPT” …… 显然&#xff0c;在这段时间内&#xff0c;ChatGPT这个词已经触发了“全民焦虑”。 …

低代码平台调研

一、什么是低代码 首先&#xff0c;我们来看一下低代码的概念。在维基百科上&#xff0c;低代码是这样定义的&#xff0c;它的全称叫做低代码开发平台&#xff0c;它为开发者提供了一种创建应用软件的开发环境&#xff0c;可以通过图形化界面和参数配置的方式来代替传统的纯手…

协方差以及PCA

概念&#xff1a;协方差&#xff08;Covariance&#xff09;在概率论和统计学中用于衡量两个变量的总体误差。而方差是协方差的一种特殊情况&#xff0c;即当两个变量是相同的情况。协方差就是衡量两个变量相关性的变量。当协方差为正时&#xff0c;两个变量呈正相关关系&#…

我用vue开发了一个动态网站--百宝阁 万字长文(spa电商,首页没有做动态,搜索页是动态)

一、前言 学习前端已有大半年了&#xff0c;虽然其中备考软件设计师考试花了两个月&#xff0c;但我还是收获颇丰&#xff0c;从最开始的html,到css&#xff0c;js,在到es6&#xff0c;promise&#xff0c;ajax,node.js、vue、webpack我已经有较为靠谱的编码习惯&#xff0c;亲…

Vue实战第4章:主页设计之中部内容设计

前言 本篇在讲什么 接上篇文章&#xff0c;我们制作了一个自定义的网页导航栏&#xff0c;本篇文章我们简单制作一个内容页 仅介绍简单的应用&#xff0c;仅供参考 本篇适合什么 适合初学Vue的小白 适合想要自己搭建网站的新手 适合没有接触过vue-router的前端程序 本篇…

Vue常用指令及声明周期

文章目录知识点前端开发环境配置v-text && v-htmlv-if、v-else && v-showv-forv-onv-modelv-bind、v-cloak、v-pre&&v-once全局 API 是什么Vue.directive 自定义组件Vue.directive 是什么自定义组件回调函数参数自定义组件的生命周期Vue.set 全局操作为…

【Kafka】一.认识Kafka

kafka是一个分布式消息队列。由 Scala 开发的高性能跨语言分布式消息队列&#xff0c;单机吞吐量可以到达 10w 级&#xff0c;消息延迟在 ms 级。具有高性能、持久化、多副本备份、横向扩展能力。 生产者往队列里写消息&#xff0c;消费者从队列里取消息进行业务逻辑。 一般在…

Unity对接接口丨简单教学丨UnityWebRequest

新手制作接口对接前言使用过程Postman测试第一次测试第二次测试第三次测试第四次测试第五次测试第六次测试总结前言 提示&#xff1a;大体介绍今日功能介绍 介绍大概UnityWebRequest对接接口方式,博主也是作为刚开始对接口的使用&#xff0c;相当详细。 使用过程 这里为内容…

你知道IP属地是怎么来的?

在互联网高速发展的时代&#xff0c;登录网络使用网络的过程当中&#xff0c;会存在非常独特的IP属地&#xff0c;这个独特的概念就是在互联网不断发展过程当中&#xff0c;对于大家来说非常熟悉而又陌生的一个必要设备&#xff0c;在使用各种电子设备上网的时候&#xff0c;都…

Flutter For Web实践

1 什么是Flutter Flutter是Google开源的一套UI工具包&#xff0c;帮助开发者通过一套代码库高效构建多平台精美应用&#xff0c;支持移动APP、web、桌面和嵌入式平台。Flutter和其他的跨平台解决方案的实现方式上有比较大的差异。 我们以React Native&#xff08;下文简称RN&…

kubernetes教程 --组件详细介绍

组件详细介绍 NameSpace 在 Kubernetes 中&#xff0c;名字空间&#xff08;Namespace&#xff09; 提供一种机制&#xff0c;将同一集群中的资源划分为相互隔离的组。 同一名字空间内的资源名称要唯一&#xff0c;但跨名字空间时没有这个要求。 名字空间作用域仅针对带有名字…

STM32单片机初学8-SPI flash(W25Q128)数据读写

当使用单片机进行项目开发&#xff0c;涉及大量数据需要储存时&#xff08;例如使用了屏幕作为显示设备&#xff0c;常常需要存储图片、动画等数据&#xff09;&#xff0c;单靠单片机内部的Flash往往是不够用的。 如STM32F103系列&#xff0c;内部Flash最多只能达到512KByte&a…

git安装与学习1(CSDN_0010_202201014)

目录 1. Git下载 2. git安装 3. 生成并添加SSH公钥 3.1 生成公钥 3.2 添加公钥 4. 代码备份 4.1 创建远程仓库 4.2 创建本地仓库 1. Git下载 Git下载官网&#xff1a;Githttps://git-scm.com/ 详细的下载教程见&#xff1a; https://blog.csdn.net/weixin_47638941/ar…

CHAPTER 5 自动发现、自动注册、分布式监控、SNMP监控

自动发现与自动注册5.1 自动发现与自动注册5.1.1 简介5.1.2 两种模式5.2 自动发现--被动模式5.3 自动注册--主动模式5.4 分布式监控5.4.1 介绍5.4.2 配置zabbix proxy5.5 SNMP监控5.5.1 使用范围5.5.2 安装snmp程序5.5.3 配置snmp程序5.5.4 测试snmp5.5.5 在web界面进行配置5.1…

LeetCode 203. 移除链表元素

原题链接 难度&#xff1a;easy\color{Green}{easy}easy 题目描述 给你一个链表的头节点 headheadhead 和一个整数 valvalval &#xff0c;请你删除链表中所有满足 Node.valvalNode.val valNode.valval 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&a…