移动端适配方案(手机专用的自适应方案)
区分:px em rem vh/vw
首先都是单位
px
在缩放页面时,使用px
作为单位的字体、按钮等的大小不会自适应;em
的值并不是固定的,基于父元素的 font-size ,代表倍数;rem
的值并不是固定的,始终是基于根元素<html>
的`font-size`,也代表倍数。vw/vh
是浏览器视口宽度 / 视口高度(viewport width/viewport height
)的 1/100。在手机端,vw/vh
的值是固定的,因为用户不能在手机上缩放浏览器。100 vw 就是浏览器视口宽度。100 vh 就是浏览器视口高度。
注意:
- chrome 字体 font-size 最小为 12px
- 浏览器的默认字体的
font-size
是 16px,未经字体大小调整的浏览器显示 1em = 16px。 - 元素的 font-size 属性可继承,子元素的 font-size 默认继承 父元素的 font-size。
1em == the font-size of father-element
1 rem
==the font-size of html-element
==100 viewport width
手机端方案的特点
- 所有手机显示的界面内容都是一样的,只是内容大小不同,要求页面内容根据设备宽度可以等比例放大,完美还原设计稿。
- 不同型号的手机,屏幕宽度不同,也就是浏览器视口宽度不同,可以理解为展示网页的窗口大小不同。但是型号定了,移动设备宽度不会改变,而PC端用户可以改变浏览器窗口大小。至少要记20种 手机型号的屏幕宽度。
1rem === 10 vw
百分比布局的缺点
百分比布局是元素 的宽度使用了百分比,但是这样做最大的缺点是 元素的高度未知,元素的宽度和高度没有办法建立关联、配合使用,比如让你做一个 宽高1:1 的图,宽高 1:2 ?百分比布局根本做不了,设置 height: 20%
并不会根据元素的宽度去计算。
引入 REM
引入 REM 方案到布局中,就是为了解决百分比布局中元素宽高无法建立起联系的问题。
移动端适配的目标
要求页面内容根据设备宽度可以等比例放大,所有型号的手机浏览器视口展示的内容完全一样,完美还原设计稿。
移动端适配方案
- 开发时,网页中使用的单位一切以宽度为准,就能完美还原设计稿。
其实 px em rem 都与宽度无关,只有 vw 与 宽度有关,但是 vw 的兼容性不好。退而求其次,想办法建立 视口宽度 和 rem 联系,而 rem 始终以 html 的 font-size 为标准,因此 使用 JS 将 html 的 font-size 设置为 浏览器视口宽度(100 vw),那么 1 rem === 100vw。
- 使用 JS 动态调整 REM 的 心路历程,完整 code
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<script>
var pageWidth = window.innerWidth // window.innerWidth 是浏览器视口宽度
document.write('<style>html{font-size:'+pageWidth+'px;}</style>')
</script>
在上面代码中,因为 html 是根元素,其它元素默认继承了 html 的 font-size 。
注意,因为 直接 1rem === 100vw
,导致在网页开发过程中很多单位都是小数,因此我们可以改成 1rem === 1vw
,如:
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<script>
var pageWidth = window.innerWidth
document.write('<style>html{font-size:'+pageWidth/100 +'px;}</style>')
</script>
但是呢,上面是不对的。因为当浏览器视口宽度较小时,比如很多手机,如 视口宽度只有 320px,百分之一只有3.2px,因此我们用JS 将 html 根元素的 font-size 改成了 3.2px,大错特错,我们忽略了 chrome 浏览器限制元素的 font-size 最小为 12px ,结果就是 用JS 将 html 根元素的 font-size 改成了 3.2px 的操作失败!!!!
取不了百分之一,取十分之一可以吧!最终,1rem === 10 vw
,也就是 html 根元素的 font-size 是 浏览器视口宽度的 1/10。
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<script>
var pageWidth = window.innerWidth
document.write('<style>html{font-size:'+pageWidth/10 +'px;}</style>')
</script>
总结:1rem === 100vw 太大,1 rem === 1vw 太小, 1rem === 10vw 刚好合适。
- rem 方案 实质是使用 rem 单位 模拟 vw 单位, vw 单位其实是最好的,奈何兼容性不好。
- 使用 REM 方案就可以 实现任意宽高比例的 div 。
- REM 做自适应布局 单位使用规则:通常 border 、文字的font-size 太小,就直接使用 px 单位,数字大才使用 rem 单位。
font-size: 16px;
border: 1px solid red;
width: 0.5rem;
第一个完整的 移动端页面
为什么不在 PC 端使用 动态REM 做自适应布局?
- 可以用
首先,PC端也是可以使用 动态REM做自适应布局的,但是还是推荐在移动端使用动态REM 做自适应布局。
- 怎么用
PC端用rem首先要用resize()函数把平常用的remjs包含起来,因为手机屏幕宽度固定,而pc端用户可以改变浏览器窗口大小。PC端用rem做响应式,应该动态监听窗口的resize动作,当窗口的分辨率变化时,动态计算html的font-size大小
(function (doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if(clientWidth>=640){
docEl.style.fontSize = '100px';
}else{
docEl.style.fontSize = 100 * (clientWidth / 640) + 'px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
使用:在html页面开头,引入上面的原生js代码。
代码意思是:如果页面的宽度超过了640px,那么页面中html的font-size恒为100px,否则,页面中html的font-size的大小为: 100 * (当前页面宽度 / 640)
- 为什么不用?
PC端一般不用rem主要是对低版本浏览器的兼容性问题,比如从ie9才开始支持rem,但是只是部分支持。ie11才全部支持。IE7、IE8不支持;IE9、IE10部分支持例如:rem用在伪元素和缩写样式上就不支持
- 若非要用
PC端检查一下是否浏览器是否支持rem,如果不支持的话提示升级浏览器。否则,只能使用兼容的”库”。
- PC页面制作建议
单位建议使用 px、百分比 ,em不建议使用,不好用。
REM 方案的痛点
- 单位转换!因为我们通常收到的设计稿是以 px 为单位的,难道前端开发时候还要手动改成 rem 单位???
- 解决办法:在 style.scss 文件 里使用 px2rem 函数 自动将 px 装换成 rem。
- 安装 scss 是前端一大难点,要 fq。官网安装 sass 方式要逆天。下面是 window 的 命令行安装方式
npm config set registry https://registry.npm.taobao.org/
vi .bashrc
- 在 vim 模式下,输入
export SASS_BINARY_SITE="https://npm.taobao.org/mirrors/node-sass"
- 按下 Esc键,输入
:wq
退出命令行的 vim 模式。 npm i -g node-sass
- 然后等待安装,就能看到
+ node-sass@4.12.0
安装成功提示。 - mkdir scss-demo
- cd scss-demo
- mkdir scss css
- touch scss/style.scss
- touch css/style.css
- 保证你的 index.html 文件里面有用 JS动态修改 html 根元素的 font-size。即写了下面代码
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<script>
var pageWidth = window.innerWidth
document.write('<style>html{font-size:'+pageWidth/10 +'px;}</style>')
</script>
- 打开 style.scss,在 scss 文件里添加```scss
@function px( $px ){
@return $px/$designWidth*10 + rem;
}
$designWidth : 640; // 640 是设计稿的宽度,你要根据设计稿的宽度填写。如果设计师的设计稿宽度不统一,就杀死设计师,换个新的。
.child{ width: px(320); height: px(160); margin: px(40) px(40); border: 1px solid red; float: left; font-size: 1.2em; }
- `node-sass scss/style.scss css/style.css`,使用命令自动编译 scss 文件,得到 css 文件。<br />命令行反应
Rendering Complete, saving .css file… Wrote CSS to G:\frontend\sass-demo\css\style.css
<br />然后打开 style.css 文件就可以看到 px 变成 rem。这时候你就可以开服务器验收 网页的,注意 index.html 要引入 style.css 文件。
- 解释一下上面的代码,更开始还很迷糊,走了点弯路。`$px/$designWidth*10`是指用设计稿上元素的宽度(单位px) / 设计稿的宽度((单位px) * 10 得到 rem 倍数,而 rem 是动态的,rem 具体是多少 px 由设备视口宽度决定,我们需要同时使用 js 动态修改 html 元素 的 font-size。**也就是通过设计稿我们得到一个比例,基数还得由设备决定,这样实现的缩放。**
<a name="ec442b2c"></a>
### SASS 使用
1. 安装 node-sass
2. 建立 sass-demo 项目, 项目下需要有 scss/style.scss 和 css/style.css 两个目录,及 index.html 。
3. 每一次 更改了 style.css 文件都要 手动编译。执行下面这行命令
node-sass scss/style.scss css/style.css ```
为什么你学不好 LESS/SASS/Webpack
- 你不会命令行,你非要用 Windows。 LESS/SASS/Webpack 使用方式都是命令行。
- 你不会英语(有些内容可以看中文翻译)
- 你不会看文档(很重要的能力),你要强制自己去看文档。