吃透移动端 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圆角边框和边界图片效果实例
Jul 01 HTML / CSS
html+css3实现的登录界面
Dec 09 HTML / CSS
HTML5边玩边学(3)像素和颜色
Sep 21 HTML / CSS
css3 transform 3d 使用css3创建动态3d立方体(html5实践)
Jan 06 HTML / CSS
HTML5 script元素async、defer异步加载使用介绍
Aug 23 HTML / CSS
html5 viewport使用方法示例详解
Dec 02 HTML / CSS
HTML5 Canvas中绘制矩形实例
Jan 01 HTML / CSS
HTML5 canvas基本绘图之填充样式实现
Jun 27 HTML / CSS
详解HTML5之pushstate、popstate操作history,无刷新改变当前url
Mar 15 HTML / CSS
Canvas引入跨域的图片导致toDataURL()报错的问题的解决
Sep 19 HTML / CSS
用canvas显示验证码的实现
Apr 10 HTML / CSS
浅谈css实现背景颜色半透明的两种方法
Dec 06 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
生成sessionid和随机密码的例子
2006/10/09 PHP
php注销代码(session注销)
2012/05/31 PHP
PHP中的事务使用实例
2015/05/26 PHP
Yii2基于Ajax自动获取表单数据的方法
2016/08/10 PHP
如何修改yii2.0自带的user表为其它的表
2017/08/01 PHP
PHP基于DateTime类解决Unix时间戳与日期互转问题【针对1970年前及2038年后时间戳】
2018/06/13 PHP
IE 缓存策略的BUG的解决方法
2007/07/21 Javascript
JavaScript DOM 学习第七章 表单的扩展
2010/02/19 Javascript
原生Js实现元素渐隐/渐现(原理为修改元素的css透明度)
2013/06/24 Javascript
开发插件的两个方法jquery.fn.extend与jquery.extend
2013/11/21 Javascript
JS 排序输出实现table行号自增前端动态生成的tr
2014/08/13 Javascript
JavaScript显示表单内元素数量的方法
2015/04/02 Javascript
Angular.js回顾ng-app和ng-model使用技巧
2016/04/26 Javascript
Bootstrap3 input输入框插入glyphicon图标的方法
2016/05/16 Javascript
Javascript将数字转化成为货币格式字符串
2016/06/22 Javascript
如何解决手机浏览器页面点击不跳转浏览器双击放大网页
2016/07/01 Javascript
基于JS实现视频上传显示进度条
2020/05/12 Javascript
Python运行报错UnicodeDecodeError的解决方法
2016/06/07 Python
详解python上传文件和字符到PHP服务器
2017/11/24 Python
Django项目中实现使用qq第三方登录功能
2019/08/13 Python
利用 Flask 动态展示 Pyecharts 图表数据方法小结
2019/09/04 Python
Python爬虫图片懒加载技术 selenium和PhantomJS解析
2019/09/18 Python
tf.concat中axis的含义与使用详解
2020/02/07 Python
加拿大最大的箱包及旅游配件零售商:Bentley Leathers
2017/07/19 全球购物
应聘护士自荐信
2013/10/21 职场文书
领导失职检讨书
2014/02/24 职场文书
《鸟的天堂》教学反思
2014/02/27 职场文书
《美丽的黄昏》教学反思
2014/02/28 职场文书
演讲稿祖国在我心中
2014/05/04 职场文书
2015年光棍节活动总结
2015/03/24 职场文书
2016反腐倡廉警示教育心得体会
2016/01/13 职场文书
创业项目(超低成本创业项目)
2019/08/16 职场文书
OpenCV-Python实现轮廓拟合
2021/06/08 Python
浅谈Python从全局与局部变量到装饰器的相关知识
2021/06/21 Python
Java练习之潜艇小游戏的实现
2022/03/16 Java/Android
PostgreSQL出现死锁该如何解决
2022/05/30 PostgreSQL