前端开发过程中, 尺寸单位是我们必须用到的, 下面我们对 CSS 中常见的几种尺寸单位 px,em,rem,rpx 进行逐一介绍
在这之前, 需要先对几个概念进行普及介绍
基本概念
(以下概念读起来可能有些晦涩, 如果看不懂也没关系)
像素
它不是自然界的物理长度, 指基本原色素及其灰度的基本编码.
CSS 中的像素只是一个抽象的单位, 在不同的设备或不同的环境中, CSS 中的 1px 所代表的设备物理像素是不同的.
在为桌面浏览器设计的网页中, 我们无需对这个津津计较, 但在移动设备上, 必须弄明白这点.
在早先的移动设备中, 屏幕像素密度都比较低, 如 iphone3, 它的分辨率为 320x480, 在 iphone3 上, 一个 CSS 像素确实是等于一个屏幕物理像素的.
后来随着技术的发展, 移动设备的屏幕像素密度越来越高, 从 iphone4 开始, 苹果公司便推出了所谓的 Retina 屏, 分辨率提高了一倍, 变成 640x960, 但屏幕尺寸却没变化, 这就意味着同样大小的屏幕上, 像素却多了一倍, 这时, 一个 CSS 像素是等于两个物理像素的. 其他品牌的移动设备也是这个道理.
物理像素
它是显示器 (电脑, 手机屏幕) 最小的物理显示单位, 物理像素指的是显示器上最小的点. 物理像素的大小取决于屏幕. 是一个无法改变的属性.
设备独立像素
我上一张图, 你就会理解什么是设备独立像素
就是我们开发过程中使用的 CSS 中的 px
设备像素比(device pixel radio)
设备像素比 = 物理像素 / 设备独立像素, 单位是 dpr!(device pixel radio)
Retina 屏幕
所谓 "Retina" 是一种显示标准, 是把更多的像素点压缩至一块屏幕里, 从而达到更高的分辨率并提高屏幕显示的细腻程度. 也被称为视网膜显示屏 -- 百度百科
因为 Retina 屏幕的出现, 在 pc 端默认情况下, CSS 中的 1px 等于 1 物理像素, 但在移动端 1px 不一定等于 1 物理像素, 比如说 iPhone 的设备独立像素是 375 667, 因为它使用了 Retina 屏幕, 他的 dpr 是 2, 所以 iPhone 6 的物理像素为 7501334
在不同的屏幕上 (普通屏幕 vs retina 屏幕),CSS 中 1px 所呈现的大小(物理尺寸) 是一致的, 不同的是 1px 所对应的物理像素个数是不一致的.
在普通屏幕下, 1px 对应 1 个物理像素(1:1). 在 Retina 屏幕下(dpr=2),1px 对应 2x2 个物理像素(1:4).
你会发现, 在移动端开发中使用了图片(img 标签),2 倍图要比 1 倍图清晰, 就是这个缘故
px
默认情况下像素 px 是相对于屏幕分辨率而言, 比如说我们的屏幕分辨率是 1440 X 900, 说的就是像素 1440px X 900px;
这里会遇到另一种情况
浏览器缩放
缩放是缩放 CSS 像素(缩放比例为 1 时, 一个 CSS 像素等于一个屏幕像素), 就是在屏幕分辨率不变的情况下, 用户对浏览进行了缩放
强调一点, 用户的缩放行为是对浏览器进行的, 缩放的是 CSS 像素, 而非分辨率, 分辨率是屏幕的分辨率, 不论你怎么缩放当前页面, 屏幕分辨率都不会改变
我们知道在移动端可以在一定程度上控制用户的缩放行为, 也可以禁止用户缩放
<meta name="viewport" content="width=device-width,initial-scale=1.0">
content 属性值 :
width: 可视区域的宽度, 值可为数字或关键词 device-width
height: 可视区域的高度, 值可为数字或关键词 device-height
intial-scale: 页面首次被显示是可视区域的缩放级别, 取值 1.0 则页面按实际尺寸显示, 无任何缩放
maximum-scale=1.0, minimum-scale=1.0; 可视区域的缩放级别,
maximum-scale 用户可将页面放大的程序, 1.0 将禁止用户放大到实际尺寸之上.
user-scalable: 是否可对页面进行缩放, no 禁止缩放
但是在 pc 端就麻烦了
- Windows:
- ctrl + +/-
ctrl + 滚轮
浏览器菜单栏
- Mac:
- cammond + +/-
浏览器菜单栏
由于浏览器菜单栏属于系统软件权限, 没发控制, 我们可以通过 JS 控制 ctrl/cammond + +/- 或 Windows 下 ctrl + 滚轮 缩放页面的情况
em
本人在实际开发过程中并没有使用过 em 单位, 但是后面要说的 rem 是基于 em 的, 所以, 对 em 进行简单介绍
em 是相对长度单位. 相对于当前对象内文本的字体尺寸. 如当前对行内文本的字体尺寸未被人为设置, 则相对于浏览器的默认字体尺寸.
em 的值并不是固定的;
em 会继承父级元素的字体大小;
任意浏览器的默认字体高都是 16px. 所有未经调整的浏览器都符合: 1em=16px.body 选择器中声明 Font-size=62.5%<==>1em=10px.
看个栗子吧
- <body>
- <style>
- html {
- font-size: 50px;
- }
- .my-div {
- width: 100%;
- height: 500px;
- margin-top: 50px;
- background-color: gray;
- font-size: 40px;
- }
- .my-div .parent-font {
- font-size: 30px;
- }
- .my-div .parent-font .child-font {
- font-size: 0.5em;
- }
- </style>
- <div class="my-div">
- <p class="parent-font">
我是父级文字
- <span class="child-font">我是子级文字</span>
- </p>
- </div>
- </body>
HTML 代码中,
第一级, HTML 的 font-size: 50px;
第二级, my-div 的 font-size: 40px;
第三级, parent-font 的 font-size:30px;
第四级, child-font 的 font-size: 0.5em;
我们通过浏览器查看, 发现第四级的 fong-size 为 15px;
我们取消第三级 parent-font 的字体大小
我们通过浏览器查看, 发现第四级的 fong-size 为 20px;
当我们取消第三级 font-size 后, 第三级的字体大小为 40px;
所以我们说 em 的字体大小不是固定的, em 的大小取决于父级的字体大小
当父级的字体大小为 20px, 子级的 1em 就是 20px
当父级的字体大小为 30px, 子级的 1em 就是 30px
那么说 font-size 存在着继承父级的特点
我们在第一级 HTML 中设置 font-size, 第二级继承第一级, 第三级继承第二级, 第四级继承第三级, 以此类推
每一级都继承自它的父级, 也就是说每一级的 em 所代表的 px 大小都不是固定的, 因为他们的父级不是同一个, 所以 em 的应用场景并不多.
那么如果是 em 的都继承自同一个地方, 是不是可以解决很多问题呢?
这时候 rem 出现了
rem
rem 是 CSS3 的一个相对单位(root em, 根 em)
使用 rem 为元素设定字体大小时, 仍然是相对大小, 但相对的只是 HTML 根元素
只要 HTML 的 font-size 大小不变, 1rem 所代表的 font-size 大小就不会变, rem 只取决于 HTML 的 font-size
rem 解决了哪些问题
移动设备的宽度是各种各样的, 每个设备的 dpr 也不同, 换句话说就是不同设备每一行的物理像素数不同, 能显示的 CSS 的 px 数也不同,
如果我们写一个 div, 宽度是 375px,375px 在这个屏幕 (iPhone6) 上是刚刚满屏, 因为这个屏幕宽度刚刚是 375px( 设备独立像素),
当我们换另一个宽度是 414px 的设备 (iPhone6Plus) 时, 这个宽度 375px 的 div 就无法铺满这个屏幕, 同样的当换一个 iPhone5(320px), 又会出现滚动条, 安卓机的宽度更是五花八门, 使用 media 媒体查询不靠谱, 因为它不能覆盖所有的机型宽度
我们之前说 rem 的大小是相对于 HTML 的 font-size 的, 如果 HTML 的 font-size 根据不同设备的宽度做动态计算, 问题就会得到解决
我们写页面都是根据 UI 设计稿来做的, 我们假设 UI 设计稿的宽度是 750px(750px 是常规宽度, 当然也可以是 640px 或是其他宽度, 但是整个项目, 宽度必须统一), 唯一不变就是就屏幕宽度, 我们的 HTML 的 font-size(rem)只取决于设备宽度
于是
document.documentElement.style.fontSize = 100 * ( document.documentElement.clientWidth / 750) + 'px'
HTML 的 font-size:document.documentElement.style.fontSize
设备的宽度: document.documentElement.clientWidth
750:UI 设计稿的宽度
为了方便计算我们将 font-size x 100, 方便计算(乘 100 不是必须的, 我接触过一些项目就不是乘以 100, 但是 UI 设计稿中使用了 sketch 做了动态计算, 但我还是建议乘 100, 不然遇到 psd 的设计图就很麻烦了)
对上面的 JS 做些完善
- const fontFun = function () {
- let docEl = document.documentElement
- let resizeEvt = 'orientationchange' in Windows ? 'orientationchange' : 'resize'
- const recalc = function () {
- let clientWidth = docEl.clientWidth
- if (!clientWidth) return
- docEl.style.fontSize = 100 * (clientWidth / 750) + 'px'
- }
- if (!document.addEventListener) return
- Windows.addEventListener(resizeEvt, recalc, false)
- Windows.addEventListener('pageshow', recalc, false)
- document.addEventListener('DOMContentLoaded', recalc, false)
- }
- export {
- fontFun
- }
对以上代码不做过多解释
也可以这样写
- (function(doc, win) {
- var docEl = doc.documentElement,
- resizeEvt = 'orientationchange' in Windows ? 'orientationchange' : 'resize',
- recalc = function() {
- var clientWidth = docEl.clientWidth
- if (!clientWidth) return
- docEl.style.fontSize = 100 * (clientWidth / 750) + 'px'
- }
- if (!doc.addEventListener) return
- win.addEventListener(resizeEvt, recalc, false)
- win.addEventListener('pageshow', recalc, false)
- doc.addEventListener('DOMContentLoaded', recalc, false)
- })(document, Windows)
iPhone5(320px)下 HTML 的 font-size:42.6667px,1rem=42.6667px
iPhone6(375px)下 HTML 的 font-size:50px,1rem=50px
iPhone6Plus(414px)下 HTML 的 font-size:55.2px,1rem=55.2px
rem 是继承自 HTML 的 font-size, 但是小程序中没有 HTML, 那怎么办呢?
rpx
我不基于 HTML 的 font-size 了, 我基于一个别的值就行了, 你也不需要计算这个值, 我给你计算了, 这就是 rpx.
最终的效果就是, 你开发时在 iphon6 的设计稿上量了多少 px, 就写多少 rpx 就行了, 完美适配, perfect!
这里推荐一下我的前端学习交流群: 784783012, 里面都是学习前端的从最基础的 HTML+CSS+JS[炫酷特效, 游戏, 插件封装, 设计模式] 到移动端 HTML5 的项目实战的学习资料都有整理, 送给每一位前端小伙伴. 最新技术, 与企业需求同步. 好友都在里面学习交流, 每天都会有大牛定时讲解前端技术!
点击: 加入 http://u6.gg/eUpjy
来源: http://www.qdfuns.com/article/51769/db9a56392d25110d00ccce1f6e01f5cc.html