从原理到方案,一步步讲解web移动端实现自适应等比缩放
前言
在移动端做自适应,我们常用的有媒体查询,rem ,em,宽度百分比这几种方案。但是都各有其缺点。
首先拿媒体查询来说,在某一个宽度区间内只能使用一种样式,为了适应不同屏幕要,css的代码量就会增多,并且后期页面如果有改动,会变得越来越不易维护。em得根据父元素的字体大小来计算宽高,有很大局限性。用百分比来设置宽度局限性也大,首先是得计算每个元素占父元素的宽度,而且只能设置宽度的百分比,而高度则很难通过百分比来设置。所以最后的希望寄托在了rem上。
rem与px
在讲rem实现方案之前,我们还是按照国际惯例,讲一下rem与px之间的关系。rem是指相对于根元素的字体大小的单位。这句话怎么理解呢?请看下面的公式:
元素的rem值 = 元素的px值 / 根节点字体大小 ,我们举栗子说明一下。
如果我们设置了根元素的字体大小为13px,那么一个宽300px,高350px的元素对应的rem就是宽23.076923rem,高26.923076rem。
代码如下:
html{
font-size: 13px;
}
div{
width: 23.076923rem; // 23.076923rem = 300px / 13px
height: 26.923076rem;// 26.923076rem = 350px / 13px
}
可以通过查看器对上面的公式进行验证,如图:

可以看出,浏览器根据rem值自动计算得到div的宽高分别为300px,350px。由此我们可以把根节点字体大小作为自变量,元素宽高作为因变量(注意:此处的宽高指的是浏览器通过换算得到的元素px值,而不是rem值)。当我们通过JavaScript动态改变根节点字体大小时,浏览器就会重新计算元素的宽高,也就可以实现了动态缩放。但是怎么把缩放跟屏幕宽度联系起来呢?
回答上述问题之前我们得知道,任何的缩放都必须有一个参考点,才能称为缩放,这是我们平时很容易忽略的一点。所以接下来我们以iphone6的设计稿为参考点,选择iphone6是因为现在大多数的UI出图都是iphone6的尺寸,我们写好css代码后,浏览器就可以在此基础上计算元素px值,从而达到缩放的效果。
同样通过例子来说明:UI图标注div宽300px, 高350px, 字体大小20px。
实现
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1,
minimum-scale=1, width=device-width, height=device-height"/>
<title>Title</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div>
hello 大家
</div>
</body>
<script src="./src/index.js"></script>
</html>
index.css
div{
font-size: 0.533333rem; // 0.533333rem = 20px / 37.5px
width: 8rem; // 8rem = 300px / 37.5px
height: 9.333333rem; // 9.333333rem = 350px / 37.5px
margin: 0 auto;
background-color: lightskyblue;
}
注意此处并没有设置根节的font-size为37.5px。但是计算rem时却使用了它,因为37.5px即为iphone6屏幕的十分之一,就是为了把iphone6作为参考基准,并且这样元素的宽高与屏幕的宽度之间就有了一个比例关系。当通过js通过改变font-size的值,并且保证这个值始终与屏幕宽度有一个比例关系时,浏览器根据公式重新计算元素的宽高就和屏幕宽度也就有了一个比例关系。当屏幕变宽,元素放大,当屏幕变窄元素缩小。
index.js
var htmlWidth = document.documentElement.clientWidth || document.body.clientWidth //获取屏幕宽度
var htmlDom = document.getElementsByTagName('html')[0] //获取html
htmlDom.style.fontSize = htmlWidth / 10 + 'px'; //设置html字体大小为屏幕的十分之一 //监听窗口大小改变
window.addEventListener('resize', () => {
var htmlWidth = document.documentElement.clientWidth || document.body.clientWidth
var htmlDom = document.getElementsByTagName('html')[0]
htmlDom.style.fontSize = htmlWidth / 10 + 'px';
})

这样基本上就已经可以实现自适应了
但是还有一个重要的问题没解决。我们不能每一个元素的rem值都像上面那样挨个手动计算,这样效率太低。
下面介绍两种解决方案:
第一种:利用scss定义函数实现自动转换
新建index2.scss文件
@function px2rem($px){
$rem:37.5px;
@return ($px / $rem) + rem;
}
div{
font-size: px2rem(20px);
width: px2rem(300px);
height: px2rem(350px);
margin: 0 auto;
background-color: lightskyblue;
}
然后看看IDE自动帮我们编译后的文件index2.css, 和index.css文件一模一样
div{
font-size: 0.533333rem;
width: 8rem;
height: 9.333333rem;
margin: 0 auto;
background-color: lightskyblue;
}
第二种:借助webpack,px2rem-loader实现
先下载各种loader
npm install style-loader css-loader px2rem-loader --save-dev
配置webpack
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [{
loader: "css-loader",
}, {
loader: 'px2rem-loader?remUnit=37.5&remPrecision=6'
}],
})
}
index3.css
div{
font-size: 20px;
width: 300px;
height: 350px;
margin: 0 auto;
background-color: lightskyblue;
}
通过webpack编译过后的index.css3文件还是和index.css文件一样。这样就直接可以按照ui图来写代码,不用任何计算。提高了效率
从原理到方案,一步步讲解web移动端实现自适应等比缩放的更多相关文章
- web移动端适配方案
web移动端常用解决方案: 一.通过js+rem,这里有一个解决方案(http://imochen.github.io/hotcss/) 1.1.rem兼容性(https://caniuse.com) ...
- 空间变换网络(STN)原理+2D图像空间变换+齐次坐标系讲解
空间变换网络(STN)原理+2D图像空间变换+齐次坐标系讲解 2018年11月14日 17:05:41 Rosemary_tu 阅读数 1295更多 分类专栏: 计算机视觉 版权声明:本文为博主原 ...
- 关于如何提高Web服务端并发效率的异步编程技术
最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...
- web移动端性能调优及16ms优化
本文只是一个索引,收集了网络上大部分关于调试及优化方面的文章,从中挑选了一些比较好的文章分享给大家. 移动端性能不及桌面浏览器性能的10分之1,特别是在android设备良莠不齐的情况下,性能显得尤为 ...
- 如何提高Web服务端并发效率的异步编程技术
作为一名web工程师都希望自己做的web应用能被越来越多的人使用,如果我们所做的web应用随着用户的增多而宕机了,那么越来越多的人就会变得越来越少了,为了让我们的web应用能有更多人使用,我们就得提升 ...
- 【转载】Web移动端Fixed布局的解决方案
特别声明:本文转载于EFE的<Web移动端Fixed布局的解决方案>.如需转载,烦请注明原文出处:http://efe.baidu.com/blog/mobile-fixed-layout ...
- iOS 【终极方案】精准获取webView内容高度,自适应高度
前言:是这样的,刚写完上一篇文章还没缓过神来,上一篇文章我还提到了,想和大家聊聊原生+H5如何无缝连接的故事.结果我朋友就给我发了两篇他的作品.他的做法也都有独到之处.好的文章都是这样,让你每次看都能 ...
- IOS开发系列之阿堂教程:玩转IPhone客户端和Web服务端交互(客户端)实践
说到ios的应用开发,我们不能不提到web server服务端,如果没有服务端的支持,ios应用开发就没有多大意义了,因为从事过手机开发的朋友都知道(Android也一样),大量复杂业务的处理和数据库 ...
- web服务端的架构演变
此文已由作者肖凡授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 最近Lofter项目碰到很多性能上的问题,特别是数据库相关的,每次推送后,告警就会第一时间到来.这些问题随着产 ...
随机推荐
- Nginx简单的负载均衡(一)
Nginx是一个高性能的http和反向代理服务器,官方测试nginx能够支支撑5万并发链接,并且cpu.内存等资源消耗却非常低,运行非常稳定. 1.应用场景 1.http服务器.Nginx是一个htt ...
- 基于90nm CMOS技术的功能齐全的64Mb DDR3 STT-MRAM
自旋转矩磁阻随机存取存储器(ST-MRAM)有望成为一种快速,高密度的非易失性存储器,可以增强各种应用程序的性能,特别是在用作数据存储中的非易失性缓冲器时设备和系统.为此,everspin开发了基于9 ...
- day36_tomcat丶servlet入门
web相关概念回顾 软件架构 常见的软件结构有下面2种 Client/Server 客户端/服务器端 简称C/S 特点:在用户本地有一个客户端程序,在远程有一个服务器端程序 如:QQ,迅雷...等等 ...
- 吴裕雄--天生自然 R语言开发学习:集成开发环境\工具RStudio的安装与配置
- 【笔记】机器学习 - 李宏毅 - 7 - Deep Learning
深度学习发展历史: 感知机和逻辑回归很像,只是没有\(sigmoid\)激活函数. 深度学习训练的三个步骤: Step1:神经网络(Neural network) Step2:模型评估(Goodnes ...
- Linux系统的启动原理
Linux系统的启动原理 RHEL的启动原理BIOS自检-MBR-启动GRUB-加载内核-systemd的init进程 systemd的初始化进程加载需要的服务,挂载文件系统/etc/fstabsys ...
- Reg文件操作
注册表REG脚本文件测试 1.新建主键 例如,想在主键[HKEY_CURRENT_USER\Software]下新建一个名叫“新建主键名称”的主键. 可以打开记事本,写入如下内容: Windows R ...
- sqlserver中判断是数字(会自动将.3识别为0.3)
SQL Server 检测是不是数字型的数据(两种方法) 检测是不是数字型的数据, 两种方法 1. ISNUMERIC ( expression ) 2. PATINDEX ( '%pattern%' ...
- 论文阅读笔记(八)【IEEEAccess2019】:High-Resolution and Low-Resolution Video Person Re-Identification: A Benchmark
Introduction (1)Motivation: 监控视频中的行人,有的比较清晰,有的因为距离较远非常模糊. 在高低分辨率方面的行人重识别缺乏数据集和研究. (2)Contribution: ① ...
- python3中的参数*args
python的传参是如何实现的 # 将未拆包的数据进行传参 def run(a,*args): #第一个参数传给了a print(a) # args是一个元组,里面是2和3两个参数 print(a ...