屏幕是由一个一个显示单元组成的.
1 每个显示单元都是物理世界真实存在的;
2 把一个显示单元的大小称为一个'物理像素';
3 一般咱们所说的 '分辨率', 就是指一块屏幕显示单元的个数, 好比750*1334
, 表示这块屏幕由 750*1334
个显示单元组成javascript
像素是计算机系统里面的单位, 一般状况下, 咱们让一个像素对应一个显示单元. 因此有时候, 咱们说屏幕高 667px, 实际上就是说, 屏幕的的高有 667个显示单元的高度之和. html
随着技术的进步, 显示单元能够作的愈来愈小, 好比之前是 10mm*10mm
的一个显示单元, 如今咱们能够作到 5mm*5mm
一个显示单元.
为何追求显示单元的小? 由于越小图像越精细. java
可是: 显示单元的变小, 意味着屏幕的分辨率变大。浏览器
这里就牵涉到了一些事情:布局
假设屏幕的大小不变, 可是分辨率从 A, 变成 2A (也就是显示单元缩小了一半)
而且: 一个像素对应一个显示单元, 这个规则始终不变code
此时, 你原来宽度为 100px 的一个元素, 在这个 2A 屏幕上渲染出来, 你会明显的发现:
在视觉上: 这个 100px 明显比以前小了, 和以前的 50px 的时候同样大小. htm
那怎么办啊, 这样显示确定是不能够的, 因此咱们要对这个状况作处理:ip
1 咱们规定, 大小为 n*n 的显示单元, 是标准的显示单元, 标准意味着它合乎咱们长久的判断: 100px 在物理世界大概有多大. 开发
2 咱们要知道当前屏幕的显示单元, 和标准显示单元之间的大小比例,好比说当前屏幕的显示单元的大小是标准的一半仍是 三分之一. rem
经过 devicePixelRatio 属性来获
咱们能够认为:
devicePixelRatio 标记是: 标准显示单元/当前设备的显示单元
创建在上面的基础上面, 你就能够动态的调整元素的大小, 好比说某个元素 x 的宽度是 100px;
在 devicePixelRatio = 1 的设备上面宽度是 100px
在 devicePixelRatio = 2 的设备上面宽度就要是 200px;
ok, 那么咱们来搞.
根据不一样的 devicePixelRatio 来调整元素的样式.
var box = document.querySelector('.box'); var height = parseInt(getComputedStyle(box).height); var width = parseInt(getComputedStyle(box).width); box.style.height = height * parseInt(window.devicePixelRatio) + 'px'; box.style.width = width * parseInt(window.devicePixelRatio) + 'px';
这仅仅是一个元素的两个属性, 1000个元素, 每一个元素 5 个属性, 就可让你哭掉了.
因此这种处理方式确定是不能够的.
而后咱们发现了 rem 单位.
它的简单解释:
当你给某个元素A 设置了 height:2rem 的时候 它会找到根节点(html) 的 font-size 值, 好比是 16px 而后拿 16 * 2 = 32px 做为元素A 的最终 height.
这个就能够利用了
1 让元素使用 rem 做单位
2 而后控制根元素的 font-size 值, 在不一样的 devicePixelRatio 下面的时候, 呈现不一样的值
好比你能够设置:
devicePixelRatio = 1, font-size(root) = 100px; devicePixelRatio = 2, font-size(root) = 200px;
元素在这个时候, 就会自动响应大小的变化.
好, 开始搞:
var fontSize = 100 * parseInt(window.devicePixelRatio) + 'px'; document.documentElement.style.fontSize = fontSize;
嗯, 结果仍是不错的, 在不一样的分辨率下面, 咱们也能实现页面相同了.
实际上, 上面的讨论, 已经解决了咱们的问题:
在相同物理尺寸下的设备, 如何在分辨率不一样的状况下, 让一个 100px 的元素, 它对应的物理世界的
大小, 始终相同?
如今更近一步, 上面的讨论, 固定了一个变量: 屏幕尺寸, 如今放开这个变量, 固定屏幕的分辨率这个变量.
这个问题就变成适配问题了:
场景描述:
好比你的一个页面原本是以 375宽度为基础作出来的, 那么在设备的宽度变成 320px 的时候,
你的页面就会出现问题: 挤压, 变形, 错乱, 或者超出隐藏, 超出滚动等等操做.
怎么办啊?
但愿的是在 320 也能正常显示: 让页面上的全部元素都缩小一些, 也就ok了. 好比一个元素
在 375 设备上面显示这么大, 在 320 上面显示成这么大不就好了.
那么如何缩小?
rem;
你想下, 只要在屏幕的宽度变小的时候, 让根元素的 font-size 跟着变小, 那么全部使用 rem 做为单位的
元素, 是否是也跟着变小, 目标就达成了.
那么怎么让 font-size(root) 随着屏幕的宽度变小而变小啊.
选一对基准值, 好比: 375px/100px; 表示屏幕宽度为 375的时候, font-size(root) 为 100;
每次计算一下就好, 好比发现屏幕的当前宽度为 320, 那么算不出来此时的 font-size(root) 吗??
算出来不会设置根元素的 font-size 吗?
好吧, 上面说的暂时都不要试, 先提一个事情.
全部的上面的讨论, 实际上都创建在:
当你屏幕的分辨率是 100100 的时候, 你就拥有一份 100100 大小的容器, 用来呈现你的网页.
好比说, 你的 iPhone7 的分辨率是 6671334, 那么你就拥有一份 6671334 大小的容器来放你的网页
惋惜并非这样的.
从 iPhone 发布前夕提及:
开发人员发现, 本来为 pc 开发的网页 在 iPhone 上面显示不全, 这部分能够经过滚动条来解决. 可是使用 百分比布局的页面就坑爹了, 本来在 pc 端浏览器上拥有 的 20% 在 iPhone 上面就一点点了, 布局彻底乱了, 坑啊. 为了解决这个问题, 开发人员提出了一个的新的玩意: 'layout viewport'
我该怎么解释这个玩意呢.
============== // 这个是你的百分比页面所基于的宽度 === // 这个是你屏幕的宽度
这样一来, 页面确定会错乱. 因此提出的 layout viewport 把模型变成这样:
============== // 这个是你的百分比页面所基于的宽度 ============= // layout viewport 的宽度 === // 这个是你屏幕的宽度
你的页面会被放到 layout viewport 这个容器上面, 而后再将 layout viewport 缩小到
和屏幕宽度同样的大小.
而且容许用户放大页面,经过滚动条滑动来浏览器所有页面.
在最初的时候, 这种方式的确解决了 pc 端页面在手机上浏览的问题, 可是随着移动端的兴起,
大量的针对移动端的页面被制做出来, 也就是模型变成这样:
=== // 针对移动端作的页面 ============ // layout viewport === // 屏幕的宽度
这样很明显就出现问题了: 你的页面先放到 layout viewport 上面, 而后又缩小到和屏幕宽度一致
最终显示出来的, 就是你的页面明显被缩小了.
因此咱们要解决这个问题, 要把 layout viewport 的大小, 变成和屏幕的宽度一致.
这里假设屏幕的显示单元始终是标准的显示单元大小。
怎么让 layout viewport 变成和屏幕的宽度一致呢?
经过 meta name="viewport" 标签.
解释一下:
meta name="viewport" 有一个 content 属性, 它里面有几个值, 能够用来对 layout viewport
作处理. content 有以下几个字段:
initial-scale: 这个值会影响最终 layout viewport 的宽度, 计算公式应该是这样:
屏幕的分辨率/(devicePixelRatio*initial-scale) = 最终的 layout viewport 的宽度.
屏幕的分辨率咱们能够拿到, devicePixelRatio 也能够拿到.
好比 iPhone7, 屏幕分辨率是 750*1334, devicePixelRatio=2, 当你设置 initial-scale=1 的时候
layout viewport 的最终宽度就是 375;
这里有一个点, 我说一下;
咱们可让 layout viewport 的宽度是任意值, 经过对 initial-scale 的设置.
那咱们要设置它为多少呢?
能够设置成 375, 这个宽度, 是以标准显示单元为单位算出来的宽度
也能够设置成 750, 这样的话, 你的 1px 就完整对应这个设备的 1 个显示单元.
咱们选择后者, 由于这个牵涉到 1px border 的实现.
若是设置成这个, 那么你的 initial-scale 始终只要设置成 1/devicePixelRatio 便可,
由于 devicePixelRatio * 1/devicePixelRatio = 1;
还有其余的两个相关属性:
maximum-scale: 最大能放大多少
minimum-scale: 最小能放大多少
但愿不能缩放, 由于咱们的页面不须要缩放就能正常显示, 缩放了反而显示不正确。
最终统筹一下:
咱们要作的事情
1 让 layout viewport 变成和屏幕分辨率一致的宽度
2 根据设备宽度和 devicePixelRatio 来指明根元素的 font-size 值
这些操做以后, 你就能够实现最终的代码了.