移动web开发

lishihuan大约 17 分钟

移动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.htmlopen in new window

什么是媒体查询

媒体查询(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;
}

使用场景:

  1. 引入资源:针对不同媒体使用不同的 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用于电脑屏幕,平板电脑,智能手机等。
print用于打印机和打印预览
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 适配方案技术使用(市场主流)

    1. [less+rem+媒体查询](#3.2 rem实际开发适配方案1)
    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 字体大小

案例:苏宁首页

苏宁首页地址 :苏宁首页open in new window

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/106054343open in new window

3.3.1. 说明

lflexible.js+rem

github地址:https://github.com/amfe/lib-flexibleopen in new window

flexible.js

手机淘宝团队出的简洁高效 移动端适配库,我们再也不需要在写不同屏幕的媒体查询,因为里面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.htmlopen in new window

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/115549134open in new window

第一步:新建 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 单位

image-20220916230146554
image-20220916230146554

第三步在index.vue中引用

import "@/plugin/flexible.js"

引用完就可以使用了

image-20220916230320238
image-20220916230320238

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 的实战用法open in new windowiOS 刘海屏适配指南open in new windowCSS env() 兼容性与使用建议open in new window