web移动端布局的那些事儿

2023-11-19

原文地址:github.com/HuJiaoHJ/bl…

web移动端布局范畴很广,其中比较基础的几个话题:

  • 移动端适配
  • 1px border
  • 基础布局

本文主要分享这三个话题

一、移动端适配

提起移动端适配,大家想到的肯定是remflexible.js,本文要分享的方案是 vw + rem

对移动端适配不熟悉的同学,可以看看:

vw 是什么?

vw 是基于视图(Viewport)的长度单位,而与Viewport相关四个单位有:

  • vw:Viewport's Width 简写,1vw 等于 window.innerWidth 的 1%
  • vh:Viewport's Height 简写,1vh 等于 window.innerHeight 的 1%
  • vmin:当前 vw 和 vh 中较小值
  • vmax:当前 vw 和 vh 中较大值

常规的 rem 的适配方案(包括flexible),其实就是通过 js 动态计算,模拟 vw 的效果,过去使用这种方案主要原因是 vw 存在一定的兼容问题,不过对于现在而言,vw 也基本能满足对兼容性的要求

可以看到,Android 4.4 以上及 IOS 8.0 以上均已支持,所以现在我们可以直接使用 vw 来做移动端适配啦

vw + rem 方案
1、设置 html font-size 为 10vw
html {
    font-size: 10vw;
}
复制代码
2、以750UI图为例,在 css 中,直接使用UI图上的长度值,单位设置为 px
.head {
    width: 750px;
}
复制代码
3、引入 postcss-pxtorem 插件,配置如下:
require('postcss-pxtorem')({
    rootValue: 75,
    unitPrecision: 5,
    propList: ['*'],
    selectorBlackList: [],
    replace: true,
    mediaQuery: false,
    minPixelValue: 0
})
复制代码

以上,就可以使用了 vw + rem 方案实现了移动端适配

4、引入 viewport-units-polyfill 解决兼容问题

为了保证在低版本的机型也能正常显示页面,可以引入 viewport-units-polyfill 来处理 vw 的兼容问题。

viewport-units-polyfill 其实是 viewport-units-buggyfill 的简化版。

简单介绍下 viewport-units-buggyfill 的实现思路:通过引入一段js,对于存在兼容问题的版本,遍历页面中所有的css,找到用到Viewport单位的css,将Viewport单位计算为 px 单位,并将新的css规则插到head或body中。

viewport-units-polyfill 则是在 viewport-units-buggyfill 基础上做了些修改,主要是把大量的遍历工作去掉,只针对 html font-size 做兼容处理(此适配方案只在 html font-size 中使用到vw)。去掉遍历工作,大大优化了性能。

用法:直接将此 js 脚本放在页面的 head 中即可

二、1px border

网上对 1px border 问题的解决方案很多,可以看看:再谈Retina下1px的解决方案

本文分享的方案则是在使用 vw + rem 的适配方案基础上,使用视图缩放(Viewport scale)来解决 1px border 问题

实现
(function () {
    var dpr = window.devicePixelRatio;
    var scale = 1 / dpr;

    var metaEl = document.querySelector('meta[name="viewport"]') || document.createElement('meta');
    metaEl.setAttribute('name', 'viewport');
    metaEl.setAttribute('content', 'width=device-width, initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no, viewport-fit=cover');

    if (document.documentElement.firstElementChild) {
        document.documentElement.firstElementChild.appendChild(metaEl);
    } else {
        var wrap = document.createElement('div');
        wrap.appendChild(metaEl);
        document.write(wrap.innerHTML);
    }
})();
复制代码

思路很简单,就是讲视图缩放(Viewport scale)设置为 1/dpr(设备像素比),从而解决 1px border 的问题

注意:此脚本是简单版,经过对各种品牌、机型进行测试之后发现,此方案基本表现良好,只有对于魅族几款手机,会存在border过细的问题。原因主要是魅族的手机 dpr 是3,但是屏幕真实分辨率并不高(我个人的理解,并未得到数据上的证实,感兴趣的小伙伴可以去验证),从而视图缩放过多,导致border过细,解决方式则是通过hack的方式(暂时没有想到比较好的,有其他方式的小伙伴欢迎评论交流~)

(function () {
    // 1px
    var dpr = window.devicePixelRatio;
    var isIPhone = window.navigator.appVersion.match(/iphone/gi);
    var UA = window.navigator.userAgent;
    // 对 meizu 某型号进行hack,主要原因是 dpr为3,但是手机屏幕分辨率不够,会出现 1px border 过细的问题,这种问题主要出现在部分魅族手机上
    var hacks = ['m1 note'];
    var flag = false;
    hacks.forEach(function (item) {
        if (UA.indexOf(item) >= 0) {
            flag = true;
            return;
        }
    });
    if (!isIPhone && flag) {
        dpr = dpr >= 2 ? 2 : dpr;
    }
    var scale = 1 / dpr;
    var metaEl = document.querySelector('meta[name="viewport"]') || document.createElement('meta');
    metaEl.setAttribute('name', 'viewport');
    metaEl.setAttribute('content', 'width=device-width, initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no, viewport-fit=cover');

    if (document.documentElement.firstElementChild) {
        document.documentElement.firstElementChild.appendChild(metaEl);
    } else {
        var wrap = document.createElement('div');
        wrap.appendChild(metaEl);
        document.write(wrap.innerHTML);
    }
})();
复制代码

将上面的脚本放在页面head中,在开发 1px border 时,可以直接如下:

.border {
    border-bottom: 1PX solid #eee;
}
复制代码

注意:如果使用了 postcss-pxtorem 类似插件,需要注意不能将此 1px 单位转换成 rem,我使用的方法是不需要转换的 px 使用大写 PX,这样 postcss-pxtorem 就不会转换

三、基础布局

基础布局其实涵盖很多方面,如:

  • 页面整体布局
  • 文案与icon
    • 各种居中对齐(垂直、水平)
    • 文案与icon对齐(icon应该使用iconfont而不是图片)
  • z-index 分层
1、页面整体布局

H5页面比较常见的布局是页面分为三部分:head、body、foot,其中head、foot会有吸顶、吸底的效果,常规的使用 fixed布局 会存在些问题,推荐将页面整体使用flex布局,将head、foot固定,body可滚动,如下:

<div id="page">
    <div id="hd">
        <!-- head -->
    </div>
    <div id="bd">
        <!-- body -->
    </div>
    <div id="ft">
        <!-- foot -->
    </div>
</div>
复制代码
#page {
    display: flex;
    flex-direction: column;
    position: relative;
    height: 100%;
    overflow: hidden;
}
#hd {
    z-index: 999;
}
#bd {
    flex-grow: 1;
    overflow-y: scroll;
    -webkit-overflow-scrolling: touch;
    &::-webkit-scrollbar {
        display: none;
    }
}
复制代码
2、文案和icon
使用iconfont

www.iconfont.cn/

注意:iconfont不支持多色icon,所以多色icon可以考虑使用svg或者img

垂直水平居中

实现方案很多:css-tricks.com/centering-c…

文案与icon对齐
<div class="box">
    <span>文案与icon垂直居中,水平对齐</span>
    <span class="icon-span">
        <i class="icons">&#xe625;</i>
    </span>
</div>
复制代码
.box {
    height: 92px;
    font-size: 32px;
    line-height: 1;
    padding: 0 20px;
    display: flex;
    align-items: center;
    .icon-span {
        font-size: 24px;
        line-height: 1;
        .icons {
            color: red;
            margin-left: 8px;
        }
    }
}
复制代码
3、z-index 分层

规范 z-index 的使用,防止因滥用导致在页面展示问题,分层使用:

$z-layers: ( 
    'below': -1,
    'default': 1,
    'content': (
        'base': 100
    ),
    'fixed': 990,
    'mask': 1000,
    'modal': 1020,
    'toast': 1040
);
复制代码

为了方便使用,使用以下 scss 方法:

$z-layers: ( 
    'below': -1,
    'default': 1,
    'content': (
        'base': 100
    ),
    'fixed': 990,
    'mask': 1000,
    'modal': 1020,
    'toast': 1040
);
@function map-has-nested-keys($map, $keys...) {
    @each $key in $keys {
        @if not map-has-key($map, $key) {
            @return false;
        }
        $map: map-get($map, $key);
    }
    @return true;
}

@function map-deep-get($map, $keys...) {
    @each $key in $keys {
        $map: map-get($map, $key);
    }
    @return $map;
}

@function z($layers...) {
    @if not map-has-nested-keys($z-layers, $layers...) {
        @warn "No layer found for `#{inspect($layers...)}` in $z-layers map. Property omitted.";
    }
    @return map-deep-get($z-layers, $layers...);
}
复制代码

具体使用如下:

.head {
    z-index: z('fixed');
}
复制代码

以上讲的布局,可以去 DEMO页看看,二维码:

代码:github.com/HuJiaoHJ/h5…

以上说的方案,我在现在几款主流的手机上都进行了测试,基本表现良好

写在最后

本文分享的方案都是我在平时工作中用到的,希望能对有需要的小伙伴有帮助~~~

喜欢我的文章小伙伴可以去 我的个人博客 点star ⭐️

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

web移动端布局的那些事儿 的相关文章

随机推荐

  • UITextFeild Test

    import
  • selenium的使用

    selenium的使用 0 使用selenium import time from selenium webdriver import Chrome from selenium webdriver common by import By 1
  • mos管的rc吸收电路计算_RCD吸收电路

    一 首先对MOS管的VD进行分段 输入的直流电压VDC 次级反射初级的VOR 主MOS管VD余量VDS RCD吸收有效电压VRCD1 二 对于以上主MOS管VD的几部分进行计算 输入的直流电压VDC 在计算VDC时 是依最高输入电压值为准
  • 大型网站架构不得不考虑的10个问题

    这里的大型网站架构只包括高互动性高交互性的数据型大型网站 基于大家众所周知的原因 我们就不谈新闻类和一些依靠HTML静态化就可以实现的架构了 我们以高负载高数据交换高数据流动性的网站为例 比如海内 开心网等类似的web2 0系列架构 我们这
  • Visual Studio Code 的安装教程和配置C语言环境(详解版)

    最近想装一个VS Code 来写C C 程序 但是看了网上的很多教程发现并不是那么的好 大部分都尝试失败了 摸索了很久找到了一个比较可靠的方法 目录 一 Visual Studio Code 的安装教程 二 接下来就是C语言的环境配置 三
  • (OD)基站维护工程师

    目录 题目描述 输入描述 输出描述 代码 题目描述 小王是一名基站维护工程师 负责某区域的基站维护 某地方有n 个基站 1
  • Rust swap

    文章目录 fn swap lt a gt a a mut String b a mut String let tmp a a b b tmp let mut a aaa to string let mut b bbb to string s
  • 浅解cocos2d-x中的CCSprite绘制原理

    cocos2d x版本为2 0 4 此画图调用的是opengl es 2 0版本 支持三角形画图 故必须有一个顶点数组 此定义定义在CCSprite h中 ccV3F C4B T2F Quad m sQuad 而这个顶点数组的定义为 4 c
  • Altium designer Silkscreen Over Component Pads

    在画pcb的时候 执行设计规则检查的时候总会出现Silkscreen Over Component Pads这个问题 该问题的意思是丝印层的文字和元件焊盘重合或者挨着很近 解决办法1 修改规则 在design rule中选择Silkscre
  • django解决使用DateTimeField添加、修改记录时不动态更新时间的问题

    解决方法 定义model时 若想动态显示最后的修改时间 使用 from django db import models from datetime import datetime models DateTimeField default d
  • 码云协同开发

    一 协同开发 为每一开发者创建一个分支 各自都在各自的分支上写代码 互不影响 完成后再合并dev分支 方式1 创建项目合作者 方式2 创建项目合作者
  • IP组播 —— IP组播的概念和地址

    一 IP数据报的三种传输方式 二 IP组播地址的范围及特点 三 硬件组播
  • SpringBoot找不到主类

    用idea把一个单独的springboot项目打开可以正确执行 可我把整个运维项目都放在一个目录用idea打开 idea识别不到主类 查看edit configurations里面的 main class也指定到了对应的applicatio
  • C#初始化数组的三种方式

    C 声明数组并初始化 有三种方式 对于一维数组 using System using System Data using System Configuration using System Web using System Web Secu
  • jenkins创建html文件夹失败,jenkins html发布者:目录存在,但未能复制到

    难道有人有不同的答案吗 Jenkins安装在Ubuntu 12 04下的tomcat下 我已经配置了使用CVS存储库进行构建 当我尝试进行新构建时 由于以下错误而失败 INFO INFO BUILD SUCCESS INFO INFO To
  • [实习]git ci/cd概念,创建流程以及常见字段含义

    1 基本概念 1 1 CI CD CI Continuous Integration 为持续集成 即在代码构建过程中持续地进行代码的集成 构建 以及自动化测试等 有了 CI 工具 我们可以在代码提交的过程中通过单元测试等尽早地发现引入的错误
  • 【安全脚本】模拟勒索病毒

    0x00 前置 1 将电脑上的重要文件加密 将文件以二进制的方式进行加密处理 导致加密过后的文件 要打开必须要解密 要解密必须要解密程序 2 传播 系统or程序漏洞 人为疏忽 后门或木马程序 3 解决 交钱 破解 数据备份 0x01 pyt
  • 华为机试题103-Redraiment的走法

    描述 Redraiment是走梅花桩的高手 Redraiment可以选择任意一个起点 从前到后 但只能从低处往高处的桩子走 他希望走的步数最多 你能替Redraiment研究他最多走的步数吗 数据范围 每组数据长度满足1 n 200 数据大
  • linux内核中的设计模式

    创建型 Object Pool Object Pool模式可以提升性能 尤其是在对象的分配 初始化成本高 使用频率高 但使用时间短的情况下 对象池可以设置对象池的大小和回收时间缓存预分配的对象 NT和Linux都有简单的预分配缓存对象的机制
  • web移动端布局的那些事儿

    原文地址 github com HuJiaoHJ bl web移动端布局范畴很广 其中比较基础的几个话题 移动端适配 1px border 基础布局 本文主要分享这三个话题 一 移动端适配 提起移动端适配 大家想到的肯定是rem flexi