移动web开发
移动web开发
流式布局和flex布局,针对的是宽度,
1. 移动web开发之rem布局
1.1 em 介绍
说明:
em相对于父元素 的字体大小来说的 ,此时div的字体 为 12px ====> 1em
此时,子元素宽度、高度为10em 则表示 120px
1.2 rem基础
rem (root em)是一个相对单位,类似于em,em是父元素字体大小。不同的是rem的基准是相对于html元素的字体大小。
比如,根元素(html)设置font-size=12px; 非根元素设置width:2rem; 则换成px表示就是24px。
/* 根html 为 12px */
html {
font-size: 12px;
}
/* 此时 div 的字体大小就是 24px */
div {
font-size: 2rem;
}
rem的优势:
父元素文字大小可能不一致, 但是整个页面只有一个html,可以很好来控制整个页面的元素大小。
可以通过修改html里面的文字大小来改变页面中元素的大小可以整体控制
1.3vw和vh基础
视口单位( Viewport units )
视口单位中的“视口”,桌面端指的是浏览器的可视区域;移动端指的就是Viewport中的Layout Viewport, “视区”所指为浏览器内部的可视区域大小,即window.innerWidth/window.innerHeight大小,不包含任务栏标题栏以及底部工具栏的浏览器区域大小。。
1.vw:1vw等于视口宽度的1%。
2.vh:1vh等于视口高度的1%。
3.vmin:选取vw和vh中最小的那个。
4.vmax:选取vw和vh中最大的那个。
2.媒体查询
媒体查询 + rem 实现元素动态大小变化
媒体查询书写规则
注意: 为了防止混乱,媒体查询我们要按照从小到大或者从大到小的顺序来写,但是我们最喜欢的还是从小到大来写,这样代码更简洁
参考:https://www.runoob.com/cssref/css3-pr-mediaquery.html
什么是媒体查询
媒体查询(Media Query)是CSS3新语法。
- 使用 @media查询,可以针对不同的媒体类型定义不同的样式
- @media 可以针对不同的屏幕尺寸设置不同的样式
- 当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面
- 目前针对很多苹果手机、Android手机,平板等设备都用得到多媒体查询
媒体查询语法规范
- 用 @media开头 注意@符号
- mediatype 媒体类型(all :用于所有设备、screen:用于电脑屏幕,平板电脑,智能手机等、print:用于打印机和打印预览)
- 关键字 and not only
- media feature 媒体特性必须有小括号包含
@media mediatype and|not|only (media feature) {
CSS-Code;
}
使用场景:
- 引入资源:针对不同媒体使用不同的 stylesheet
<!-- 宽度大于 900px 的屏幕使用该样式 -->
<link rel="stylesheet" media="screen and (min-width: 900px)" href="widescreen.css">
<!-- 宽度小于或等于 600px 的屏幕使用该样式 -->
<link rel="stylesheet" media="screen and (max-width: 600px)" href="smallscreen.css">
....
2.直接写在style
@media only screen and (min-width: 600px) { /* >= 600px*/
/* For tablets: */
.col-m-12 {width: 8.33%;}
.col-m-2 {width: 16.66%;}
}
@media only screen and (min-width: 768px) {
/* For desktop: */
.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
}
@media screen and (min-device-width: 1440px) and (max-device-width: 1680px){
.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
}
媒体类型
| 值 | 描述 |
|---|---|
| all | 用于所有设备 |
| screen | 用于电脑屏幕,平板电脑,智能手机等。 |
| 用于打印机和打印预览 | |
| speech | 应用于屏幕阅读器等发声设备 |
媒体功能
主要了解 width,max--width,min-width 都是包含等于号的
| 值 | 描述 |
|---|---|
| aspect-ratio | 定义输出设备中的页面可见区域宽度与高度的比率 |
| color | 定义输出设备每一组彩色原件的个数。如果不是彩色设备,则值等于0 |
| color-index | 定义在输出设备的彩色查询表中的条目数。如果没有使用彩色查询表,则值等于0 |
| device-aspect-ratio | 定义输出设备的屏幕可见宽度与高度的比率。 |
| device-height | 定义输出设备的屏幕可见高度。 |
| device-width | 定义输出设备的屏幕可见宽度。 |
| grid | 用来查询输出设备是否使用栅格或点阵。 |
| height | 定义输出设备中的页面可见区域高度。 |
| max-aspect-ratio | 定义输出设备的屏幕可见宽度与高度的最大比率。 |
| max-color | 定义输出设备每一组彩色原件的最大个数。 |
| max-color-index | 定义在输出设备的彩色查询表中的最大条目数。 |
| max-device-aspect-ratio | 定义输出设备的屏幕可见宽度与高度的最大比率。 |
| max-device-height | 定义输出设备的屏幕可见的最大高度。 |
| max-device-width | 定义输出设备的屏幕最大可见宽度。 |
| max-height | 定义输出设备中的页面最大可见区域高度。 |
| max-monochrome | 定义在一个单色框架缓冲区中每像素包含的最大单色原件个数。 |
| max-resolution | 定义设备的最大分辨率。 |
| max-width | 定义输出设备中的页面最大可见区域宽度。 |
| min-aspect-ratio | 定义输出设备中的页面可见区域宽度与高度的最小比率。 |
| min-color | 定义输出设备每一组彩色原件的最小个数。 |
| min-color-index | 定义在输出设备的彩色查询表中的最小条目数。 |
| min-device-aspect-ratio | 定义输出设备的屏幕可见宽度与高度的最小比率。 |
| min-device-width | 定义输出设备的屏幕最小可见宽度。 |
| min-device-height | 定义输出设备的屏幕的最小可见高度。 |
| min-height | 定义输出设备中的页面最小可见区域高度。 |
| min-monochrome | 定义在一个单色框架缓冲区中每像素包含的最小单色原件个数 |
| min-resolution | 定义设备的最小分辨率。 |
| min-width | 定义输出设备中的页面最小可见区域宽度。 |
| monochrome | 定义在一个单色框架缓冲区中每像素包含的单色原件个数。如果不是单色设备,则值等于0 |
| orientation | 定义输出设备中的页面可见区域高度是否大于或等于宽度。 |
| resolution | 定义设备的分辨率。如:96dpi, 300dpi, 118dpcm |
| scan | 定义电视类设备的扫描工序。 |
| width | 定义输出设备中的页面可见区域宽度。 |
3. rem适配方案
1.让一些不能等比自适应的元素,达到当设备尺寸发生改变的时候,等比例适配当前设备。
2.使用媒体查询根据不同设备按比例设置html的字体大小,然后页面元素使用rem做尺寸单位,当html字体大小变化元素尺寸也会发生变化,从而达到等比缩放的适配。
3.1 rem 适配方案技术使用(市场主流)
- [less+rem+媒体查询](#3.2 rem实际开发适配方案1)
- [flexible.js+rem](#3.3 rem实际开发适配方案2)
总结: 两种方案现在都存在。方案2 更简单
3.2 方案一: less+rem+媒体查询
屏幕尺寸/划分的份数 作为 跟字体大小
思路
①假设设计稿是750px
②假设我们把整个屏幕划分为15等份(划分标准不一可以是20份也可以是10等份)
③每一份作为html字体大小,这里就是50px
④那么在320px设备的时候,字体大小为320/15就是 21.33px
⑤页面元素的rem值 = 页面元素值(px) / html font-size 字体大小
一个100 x 100像素的页面元素在
750屏幕下, 就是 100/ 50 转换为rem 是 2rem*2rem 比例是1比1
320屏幕下, html字体大小为21.33 则 2rem= 42.66px 此时宽和高都是 42.66 ,宽和高的比例还是 1比1
也就是说,用我们页面元素的大小除以不同的 html字体大小会发现他们比例还是相同的
元素大小取值方法:
①屏幕宽度/划分的份数就是 htmlfont-size 的大小
②最后的公式:页面元素的rem值 = 页面元素值(px) / (屏幕宽度 / 划分的份数)
③或者:页面元素的rem值 = 页面元素值(px) / html font-size 字体大小
案例:苏宁首页
苏宁首页地址 :苏宁首页
1.技术选型
方案:我们采取单独制作移动页面方案
技术:布局采取rem适配布局(less + rem + 媒体查询)
设计图: 本设计图采用 750px 设计尺寸
2.搭建文件结构
├──css
│ ├─common.less
│ └─index.less
├─images 图片
│
├─index.html 主页
3.设置视口标签以及引入初始化样式
设置理想视口,使得DOM宽度(layout viewport)与屏幕宽度(visual viewport)一样大,DOM文档主宽度即为屏幕宽度,1个CSS像素(1px)由多少设备像素显示由具体设备而不同;
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
<link rel="stylesheet" href="css/normalize.css">
4.设置公共common.less文件
- 新建common.less 设置好最常见的屏幕尺寸,利用媒体查询设置不同的html字体大小,因为除了首页其他页面也需要
- 我们关心的尺寸有 320px、360px、375px、384px、400px、414px、424px、480px、540px、720px、750px
- 划分的份数我们定为 15等份
- 因为我们pc端也可以打开我们苏宁移动端首页,我们默认html字体大小为 50px,注意这句话写到最上面
// 设置常见的屏幕尺寸 修改里面的html文字大小
// 一定要写到最上面
html {
font-size: 50px;
}
// 我们此次定义的划分的份数 为 15
@no: 15;
// 320
@media screen and (min-width: 320px) {
html {
font-size: 320px / @no;
}
}
// 360
@media screen and (min-width: 360px) {
html {
font-size: 360px / @no;
}
}
// 375 iphone 678
@media screen and (min-width: 375px) {
html {
font-size: 375px / @no;
}
}
// 384
@media screen and (min-width: 384px) {
html {
font-size: 384px / @no;
}
}
// 400
@media screen and (min-width: 400px) {
html {
font-size: 400px / @no;
}
}
// 414
@media screen and (min-width: 414px) {
html {
font-size: 414px / @no;
}
}
// 424
@media screen and (min-width: 424px) {
html {
font-size: 424px / @no;
}
}
// 480
@media screen and (min-width: 480px) {
html {
font-size: 480px / @no;
}
}
// 540
@media screen and (min-width: 540px) {
html {
font-size: 540px / @no;
}
}
// 720
@media screen and (min-width: 720px) {
html {
font-size: 720px / @no;
}
}
// 750
@media screen and (min-width: 750px) {
html {
font-size: 750px / @no;
}
}
5.根据设计稿的尺寸计算 页面元素尺寸
页面元素的rem值 = 页面元素值(px) / html font-size 字体大小
也可以通过 插件计算 [px 转换rem插件](#px 转换rem插件)
import和link 的区分
在index.less 通过 @import "common"; 意思是讲common.less 导入到index.less 文件种
link 是把一个 样式文件引入到HTML页面中
3.3 rem实际开发适配方案2
首先拉取依赖lib-flexible 和 postcss-px2rem 一对,或者lib-flexible 和 postcss-pxtorem 一对,两种配置的依赖是不一样的,要注意。npm拉包默认就给你加到运行依赖里去了,拉开发依赖包时再加上-D。lib-flexible是运行依赖后面那个postcss-px2rem、postcss-pxtorem是开发依赖 https://blog.csdn.net/qq_42031498/article/details/106054343
3.3.1. 说明
lflexible.js+rem
github地址:https://github.com/amfe/lib-flexible
手机淘宝团队出的简洁高效 移动端适配库,我们再也不需要在写不同屏幕的媒体查询,因为里面js做了处理(对比上面的不需要写 媒体查询,交由lflexible.js处理)
它的原理是把当前设备划分为10等份,但是不同设备下,比例还是一致的。我们要做的,就是确定好我们当前设备的html 文字大小就可以了
比如当前设计稿是 750px, 那么我们只需要把 html 文字大小设置为 75px (750px / 10) 就可以
里面页面元素rem值: 页面元素的px 值 / 75 剩余的,让flexible.js来去算
总结:
因为flexible是默认将屏幕分为10等分
但是当屏幕大于750的时候希望不要再去重置html字体了,所以要自己通过媒体查询设置一下,并且要把权重提到最高
插件: px 转换rem 需要设置根字体大小,才能正常使用 [px 转换rem插件](#px 转换rem插件)
VSCode: cssrem (cssrem中css自动转化为rem是参照默认插件的16转换的)
idea: px2rem
3.3.2. 案例:苏宁首页
- 默认设计稿的尺寸是 750px
- lflexible.js 默认是讲 页面10等份,所以 每份是 75
- 开发默认就是以750px 为尺寸,所以 元素的rem值= 页面元素的px值 / 75
1. 搭建文件结构和 视口标签引入初始化样式(同上)
2. 引入 flexible.js
<script src='js/flexible.js'> </script>
<head>
<meta charset="UTF-8">
<!-- 引入视口标签 -->
<meta name="viewport" content="width=device-width, user-scalable=no,initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- 初始化样式,主要是去掉一些不要的样式,如 设置html默认padding和margin -->
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/index.css">
<!-- 引入我们的flexible.js 文件 -->
<script src="js/flexible.js"></script>
<title>flexible_rem 适配</title>
</head>
3. 编写index.css
主要是设置 当屏幕大于750的时候希望不要再去重置html字体了,所以要自己通过媒体查询设置一下,并且要把权重提到最高
/* 如果我们的屏幕超过了 750px 那么我们就按照 750设计稿来走 不会让我们页面超过750px */
@media screen and (min-width: 750px) { html { font-size: 75px!important; } }
/**
width:10rem说明:
开发不用管当前设备尺寸,默认就以是750px,默认是10等份 每份是 75,所以 rem= 设计稿px值 / 75
10rem === > 750/75
*/
body {
min-width: 320px;/* 默认最小尺寸是 320px 最大是 750px */
max-width: 750px;
/* flexible 给我们划分了 10 等份 */
width: 10rem;
margin: 0 auto;
line-height: 1.5;
font-family: Arial, Helvetica;
background: #f2f2f2;
}
/* 如果我们的屏幕超过了 750px 那么我们就按照 750设计稿来走 不会让我们页面超过750px */
@media screen and (min-width: 750px) {
html {
font-size: 75px!important;
}
}
3.3 vue 通过 lflexible.js 实现rem 适配
https://www.cnblogs.com/dreamcc/p/10681358.html
npm i -S amfe-flexible
导包
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<script src="./node_modules/amfe-flexible/index.js"></script>
vscode编辑器安装插件easy-scss
3.4 案例-自定义js 计算html 根字体大小(针对PC 端)
PC端:按照1920px来划分的,因为分为24等份,故每份为80,故需在cssren的设置中需要将root font size改为80
https://blog.csdn.net/u011200562/article/details/115549134
第一步:新建 flexible.js文件
(function flexible(window, document) {
var docEl = document.documentElement;
var dpr = window.devicePixelRatio || 1;
// adjust body font size
function setBodyFontSize() {
if (document.body) {
document.body.style.fontSize = 12 * dpr + "px";
} else {
document.addEventListener("DOMContentLoaded", setBodyFontSize);
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit() {
var rem = docEl.clientWidth / 24;
docEl.style.fontSize = rem + "px";
}
setRemUnit();
// reset rem unit on page resize
window.addEventListener("resize", setRemUnit);
window.addEventListener("pageshow", function(e) {
if (e.persisted) {
setRemUnit();
}
});
// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement("body");
var testElement = document.createElement("div");
testElement.style.border = ".5px solid transparent";
fakeBody.appendChild(testElement);
docEl.appendChild(fakeBody);
if (testElement.offsetHeight === 1) {
docEl.classList.add("hairlines");
}
docEl.removeChild(fakeBody);
}
})(window, document);
第二步:去vscode下载一个cssrem插件,并修改设置
下载插件后设置 根字体大小,后面在输入设计搞的px 数值,插件会自动将其转换为rem 单位

第三步在index.vue中引用
import "@/plugin/flexible.js"
引用完就可以使用了

4. 百分比适配
使用 百分比% 定义 宽度,高度 用px固定,根据可视区域实时尺寸进行调整,尽可能适应各种分辨率,通常使用max-width/min-width控制尺寸范围过大或者过小。下表是子元素不同属性设置百分比的依据
移动端异常处理
1.打包失败
03/11 08:52:00: Launching 'app' on Physical Device.
Installation did not succeed.
The application could not be installed: INSTALL_FAILED_TEST_ONLY
List of apks:
[0] 'D:\svn\yunjian\YJYDXJ\YJYDXJ_APP\igw-cordova-app\platforms\android\app\build\outputs\apk\debug\app-debug.apk'
Installation failed due to: 'null'
Retry
gradle.properties 文件夹下添加
android.injected.testOnly=false
2. 安卓低版本不支持
Android 4.x 的 WebView 很多都不支持
- 不支持 ES6 【let、const等不支持】
- ?.
- backdrop-filter
针对这些,可以通过adb连接,然后利用hbulider 运行到手机或者模拟器中,通过控制台看错误
3. IOS 虚拟键盘导致的容器异常
目前由于虚拟键盘会导致,页面出异常:整体上移、整体下移
通过修改原生代码,添加如下代码,实现 容器的重构
// 假设 self.webView 是你已有的 WKWebView 实例(或通过 tag 找到)
__weak typeof(self) weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillHideNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification * _Nonnull note) {
// 延迟执行,确保键盘动画完全结束
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
// 确保 webView 存在
if ([strongSelf.webView isKindOfClass:[WKWebView class]]) {
WKWebView *webView = strongSelf.webView;
[webView setNeedsLayout];
[webView layoutIfNeeded];
[webView.scrollView setContentOffset:CGPointZero animated:NO];
}
});
}];
其他
iOS 的“安全区域”(Safe Area)是指屏幕中不会被系统 UI 遮挡的可视区域。它是从 iPhone X 开始引入的,为了解决刘海屏、圆角屏、底部 Home Indicator 等系统 UI 元素遮挡页面内容的问题。
✅ 一、什么是 Safe Area?
iPhone X 及以后的设备不再是传统的矩形屏幕,而是:
- 顶部有刘海(状态栏、摄像头)
- 底部有 Home 指示条(白条)
- 四个角是圆角
所以,页面内容如果贴边写,就可能被遮挡。 Apple 定义了一个 “安全区域 Safe Area”,让你在这个区域里布局,不会被系统元素遮挡。
📐 二、Safe Area 示例图解:
╔══════════════════════════════════╗
║ 刘海 + 状态栏(系统) ← safe-area-inset-top
║ ┌────────────────────────────┐
║ │ 页面内容区域 │ ← Safe Area
║ └────────────────────────────┘
║ Home 指示条(系统) ← safe-area-inset-bottom
╚══════════════════════════════════╝
✅ 三、怎么在 H5 / CSS 中适配 Safe Area?
1. ✅ 在 viewport 中开启安全区域适配
<meta name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover">
📌 viewport-fit=cover 表示允许内容绘制到整个屏幕,包括刘海和 Home 指示条区域。
2. ✅ 使用 CSS 的 env() 函数获取安全区边距
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
这几个变量系统会自动设置:
| 变量 | 含义 | 一般值 |
|---|---|---|
env(safe-area-inset-top) | 刘海高度 | 44px(iPhone X) |
env(safe-area-inset-bottom) | Home 指示条高度 | 34px |
env(safe-area-inset-left/right) | 横屏时的边距 | 0~21px |
📦 四、常见使用场景
✅ 导航栏不被刘海遮挡
.navbar {
padding-top: env(safe-area-inset-top);
height: calc(44px + env(safe-area-inset-top));
}
✅ 底部按钮不被 Home 白条遮挡
.footer {
padding-bottom: env(safe-area-inset-bottom);
}
📱 五、适配 iOS Safe Area 的最佳实践(总结)
| 步骤 | 必须做吗 | 示例 |
|---|---|---|
viewport-fit=cover | ✅ 必须 | <meta name="viewport" content="... viewport-fit=cover"> |
使用 env(safe-area-inset-*) | ✅ 必须 | padding-top: env(safe-area-inset-top) |
使用 calc() 合并固定高度 | ✅ 推荐 | height: calc(44px + env(...)) |
| 兼容安卓 | ✅ 会自动忽略 env()(无副作用) |
🔍 小提示:安卓没这个概念怎么办?
安卓系统没有 safe-area 的说法,但:
- Android WebView 不支持
env()的会忽略它,不报错; - 所以你可以放心在 CSS 中使用
env(),它是 渐进增强(progressive enhancement);
✅ 最终推荐结构(HTML + CSS)
<meta name="viewport"
content="width=device-width, initial-scale=1.0, viewport-fit=cover">
html, body {
margin: 0;
padding: 0;
height: 100%;
}
#app {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
min-height: 100vh;
box-sizing: border-box;
}
是否需要我为你当前页面结构生成一份完整的“iOS 安全区适配模板”,包括导航栏 + 页面内容 + 底部按钮的 Safe Area 支持? 你也可以看看这些:viewport-fit 和 Safe Area 的实战用法、iOS 刘海屏适配指南、CSS env() 兼容性与使用建议。