吃透移动端 Html5 响应式布局


Posted in HTML / CSS onDecember 16, 2019

最近写第三个移动端 H5 的项目了,准备记录下自己在 H5 项目中的一些实践探索。移动端 H5 与 PC 端开发最大的区别之一,大概就是 响应式布局 问题。

那么下面我们来聊聊移动端响应式布局,了解他的来龙去脉,对现有的最佳解决方案探索。

问题

全文将围绕下面几个问题进行论述和展开:

写移动端H5 相关页面,相比 PC 端有哪些值得注意的点?

关于H5 响应式布局有哪些解决方案?

什么是 rem?如何在项目中完美使用它?

vh/vw 是最佳解决方案吗?它有什么优势和缺陷 大型开源库里面常用解决方案是什么?

怎样快速搭建一套移动端布局解决方案?

由来

概念

什么是 H5 技术?

H5 这个命名本身是一个很不讨巧的命名,咋一眼看上去认为 HTML5,或者第 5 级标题的标签,对一些造成一些不小的误解。

比如:我的一个某后端同事,谈论到 H5 很简单,HTML 之前我也学过一些,以后要是你请假,我来帮你写。

我是一脸蒙蔽,H5 === HTML?

再看看,搜索引擎中H5是什么?(引用来自谷歌词条第一页)

吃透移动端 Html5 响应式布局

如此看来,将 H5 视作 HTML 的大有人在,而 H5 这个概念只在中国特有,所以对外国人来说他们也认为是 HTML, 所以,对于外国人和非这个领域的人来说,他们存在一样的误解。

目前的 H5 算是一个比较大的概念了,我认为的 H5 技术是 一系列移动端 web 前端技术的集合 大致用一个韦恩图表示如下

吃透移动端 Html5 响应式布局

我们这里只谈 web 前端中 H5 技术,H5 技术本身是用于 移动端的 web 网页 。由于App本身有个 “ webview ” 的容器,在容器里可以运行 web 前端相关代码,由此 H5 和原生 App 结合又衍生出来了 Hybrid App 技术

Hybrid App 技术大致原理

吃透移动端 Html5 响应式布局

这是我给公司同事普及 H5 知识绘制的图像。

移动端 web 和 PC web 的区别

PC 端我们是怎么布局的呢? 一般采用两种方案,一种是 min-width 限制最小的宽度,浏览器宽度小于 min-width 就直接滚动。另外一种呢,就是留白。设置页面一个基础宽度,超出的部分留白。

但是这两种解决方案在移动端可行吗?

移动端手机的宽度,大多不一致,而且没办法进行窗口的缩放。让移动端产生滚动,体验更加糟糕,更别说和原生 app 性能相比较,基本页面展示体验就很差了。

那么留白呢? 更不可行了,手机设备本身宽度就小,再留白就基本看不了什么了。

所以为了让这种 web 能够像原生 app 一样的体验,就出现了 H5 技术。进一步衍生了 Hybird , 虽然比不上 app 性能,但是在 热更新 上占有绝对优势,有着原生无法替代的地方。

下面我们来就来实践下 H5 最基本的技术之一 移动端响应式布局

实践

解决方案一:rem + pxToRem 概念

css 中用于计量的单位有两种,一种是 绝对单位 ,另一种是 相对单位

绝对单位

吃透移动端 Html5 响应式布局 

对于绝对单位,一般来说常用的也就 px, 其他的可能打印需要用到

相对单位

吃透移动端 Html5 响应式布局 

对于相对单位来说, emrem 属于一对, vwvh属于一对。

前一对相对于 字体大小 ,区别在于 rem 相对于 根字体 ,对于我们控制整体的大小相对容易些,所以我们可以使用它来控制整个页面的缩放。

后一对,相对于视窗的大小,这个将在下一个节中发挥主要作用。

原理

  • 监听屏幕视窗的宽度,通过一定比例换算赋值给 htmlfont-size 。此时,根字体大小就会随屏幕宽度而变化。
  • px 转换成 rem , 常规方案有两种,一种是利用 sass / less 中的自定义函数 pxToRem ,写 px 时,利用 pxToRem 函数转换成 rem 。另外一种是直接写 px ,编译过程利用插件全部转成 rem 。这样 dom 中元素的大小,就会随屏幕宽度变化而变化了。

 实现

动态更新根字体大小

const MAX_FONT_SIZE = 420

// 定义最大的屏幕宽度
document.addEventListener('DOMContentLoaded', () => {
  const html = document.querySelector('html')
  let fontSize = window.innerWidth / 10
  fontSize = fontSize > MAX_FONT_SIZE ? MAX_FONT_SIZE : fontSize
  html.style.fontSize = fontSize + 'px'
})

pxrem

pxToRem 方案一

$rootFontSize: 375 / 10;
// 定义 px 转化为 rem 的函数
@function px2rem ($px) {
    @return $px / $rootFontSize + rem;
}

.demo {
    width: px2rem(100);
    height: px2rem(100);
}

pxToRem 方案二

vue-cli3 中配置 装 postcss-pxtorem 插件就可以了,其他平台大致差不多

const autoprefixer = require('autoprefixer')
const pxtorem = require('postcss-pxtorem')
module.exports = { 
  // ...
  css: {
    sourceMap: true,
    loaderOptions: {
      postcss: {
        plugins: [
          autoprefixer(),
          pxtorem({
            rootValue: 37.5,
            propList: ['*']
          })
        ]
      }
    }
  }
}

解决方案二:vh + vw

原理

vw 相对于视窗宽度的单位,随宽度变化而变化。由此看来,方案一其实是方案二的一种 Hack, 通过使用监听实现了方案二的效果

实现

与 rem 类似做法,直接使用postcss-px-to-viewport 插件进行配置, 配置方式也是和 postcss-pxtorem 大同小异

我们看看插件的原理是不是也是一样的

function createPxReplace(opts, viewportUnit, viewportSize) {
  return function (m, $1) {
    if (!$1) return m;
    var pixels = parseFloat($1);
    if (pixels <= opts.minPixelValue) return m;
    var parsedVal = toFixed((pixels / viewportSize * 100), opts.unitPrecision);
    return parsedVal === 0 ? '0' : parsedVal + viewportUnit;
  };
}

果然呢,连方法名、变量名、代码逻辑,都一摸一样哈哈哈,谁抄谁,我就不指出来啦 - -

其他解决方案 

                        

  方案 缺陷
1 百分比 高度无法百分比
2 媒体查询 + meta 中 viewport 不同设备宽度不同,缩放比无法完全确定
3 flex 还是无法解决宽度超出问题

上面方案均存在致命缺陷,不推荐使用它完成移动端布局计算。

flex 与 rem 结合使用更佳

兼容性

上述两种方案, 兼容性主要在于 rem,vh,vw 关键词上

吃透移动端 Html5 响应式布局

rem 在移动端表现高达 100%,令人惊叹!

吃透移动端 Html5 响应式布局 

吃透移动端 Html5 响应式布局 

vh vw表现还是比较令人满意,低版本的 safari 情况下会有兼容性问题,但不影响它会成为一种比较好的移动端布局解决方案。

 开源库解决方案

vant 组件库

吃透移动端 Html5 响应式布局

vant 组件库中,默认采用 px 做计量单位,如果需要使用 rem ,直接使用插件完美适配。

对于 vw 方案,vant 也是可以通过插件将 px 转成 vw ,对于 vw 可能会存在一些坑点。

ant-design-mobile 组件库

ant-design-mobile 组件库仍然使用 px 单位

@hd: 1px; // 基本单位

// 字体尺寸
// ---
@font-size-icontext: 10 * @hd;
@font-size-caption-sm: 12 * @hd;
@font-size-base: 14 * @hd;
@font-size-subhead: 15 * @hd;
@font-size-caption: 16 * @hd;
@font-size-heading: 17 * @hd;

// 圆角
// ---
@radius-xs: 2 * @hd;
@radius-sm: 3 * @hd;
@radius-md: 5 * @hd;
@radius-lg: 7 * @hd;
@radius-circle: 50%;

// 边框尺寸
// ---
@border-width-sm: 1PX;
@border-width-md: 1PX;
@border-width-lg: 2 * @hd;

vant 组件一样, 还是由开发者来决定到底用哪一种方案 这种把选择权交给开发者,算是一种开源库的最灵活的做法了 。

总结

通过该文,你大概了解 H5 问题的来龙去脉了吧,也明白了如何解决移动端响应式布局问题,如果这篇文章能解决你的疑问或者工作中问题,不妨 点个赞 收藏下。

由于技术水平有限,文章中如有错误地方,请在评论区指出,感谢!

上一篇文章,解决了 1px 问题 ,这篇文章解决了 响应式布局 问题, 接下我应该会继续研究下, 关于 H5 一些踩坑总结 ,之后应该会去研究下 vue 最新的源码 再进行分享,想持续了解更多,不妨点个 关注 呗。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
详解css3 object-fit属性
Jul 27 HTML / CSS
利用CSS3实现单选框动画特效示例代码
Sep 26 HTML / CSS
Css3新特性应用之视觉效果实例
Dec 12 HTML / CSS
HTML5 使用 sessionStorage 进行页面传值的方法
Jul 02 HTML / CSS
HTML5中的新元素介绍
Oct 17 HTML / CSS
HTML5图片预览实例分享
Jun 04 HTML / CSS
HTML5打开手机扫码功能及优缺点
Nov 27 HTML / CSS
解锁canvas导出图片跨域的N种姿势小结
Jan 24 HTML / CSS
用canvas显示验证码的实现
Apr 10 HTML / CSS
AmazeUI 导航条的实现示例
Aug 14 HTML / CSS
前后端结合实现amazeUI分页效果
Aug 21 HTML / CSS
使用CSS设置滚动条样式
Jan 18 HTML / CSS
HTML文本属性&amp;颜色控制属性的实现
Dec 17 #HTML / CSS
吃透移动端 1px的具体用法
Dec 16 #HTML / CSS
关于html字符串正则判断和匹配的具体使用
Dec 12 #HTML / CSS
处理textarea中的换行和空格
Dec 12 #HTML / CSS
VSCode 自定义html5模板的实现
Dec 05 #HTML / CSS
HTML5 图片悬停放大的实现代码示例
Dec 04 #HTML / CSS
Html5写一个简单的俄罗斯方块小游戏
Dec 03 #HTML / CSS
You might like
一个简单的自动发送邮件系统(一)
2006/10/09 PHP
php笔记之:有规律大文件的读取与写入的分析
2013/04/26 PHP
php 模拟GMAIL,HOTMAIL(MSN),YAHOO,163,126邮箱登录的详细介绍
2013/06/18 PHP
php传值赋值和传地址赋值用法实例分析
2015/06/20 PHP
老生常谈PHP面向对象之命令模式(必看篇)
2017/05/24 PHP
通过jQuery打造支持汉字,拼音,英文快速定位查询的超级select插件
2010/06/18 Javascript
js 获取后台的字段 改变 checkbox的被选中的状态 代码
2013/06/05 Javascript
IE下双击checkbox反应延迟问题的解决方法
2014/03/27 Javascript
javascript判断数组内是否重复的方法
2015/04/21 Javascript
快速理解 JavaScript 中的 LHS 和 RHS 查询的用法
2017/08/24 Javascript
jQuery ajax调用webservice注意事项
2017/10/08 jQuery
原生javascript AJAX 三级联动的实现代码
2018/05/04 Javascript
vue 中使用 watch 出现了如下的报错的原因分析
2019/05/21 Javascript
解决Vue的项目使用Element ui 走马灯无法实现的问题
2020/08/03 Javascript
[04:22]DOTA2大事件之护国神翼
2020/08/14 DOTA
python中使用smtplib和email模块发送邮件实例
2014/04/22 Python
python获取文件版本信息、公司名和产品名的方法
2014/10/05 Python
Python中使用items()方法返回字典元素对的教程
2015/05/21 Python
Python 正则表达式的高级用法
2016/12/04 Python
简单谈谈Python中的几种常见的数据类型
2017/02/10 Python
一篇文章读懂Python赋值与拷贝
2018/04/19 Python
Djang的model创建的字段和参数详解
2019/07/27 Python
Python 实现黑客帝国中的字符雨的示例代码
2020/02/20 Python
python实现从ftp服务器下载文件
2020/03/03 Python
jupyter notebook插入本地图片的实现
2020/04/13 Python
荷兰的时尚市场:To Be Dressed
2019/05/06 全球购物
Lentiamo荷兰:在线订购隐形眼镜、隐形眼镜液和太阳镜
2019/10/25 全球购物
.net面试题
2015/12/22 面试题
laravel使用redis队列实例讲解
2021/03/23 PHP
一夜的工作教学反思
2014/02/08 职场文书
贯彻学习两会心得体会范文
2014/03/17 职场文书
2015年学校团委工作总结
2015/05/26 职场文书
2016年小学圣诞节活动总结
2016/03/31 职场文书
CSS3 制作的图片滚动效果
2021/04/14 HTML / CSS
Python一些基本的图像操作和处理总结
2021/06/23 Python
教你使用Jenkins集成Harbor自动发布镜像
2022/04/03 Servers