场景化分析rem布局原理

移动端rem布局

前端很流行的布局方式rem布局,通过设备之间px像素与rem的转换,达到不同屏幕相同视觉效果的布局方式,在了解rem布局之前需要先明白几个概念,设备像素(物理像素)、独立像素、CSS像素。

设备像素(物理像素)

屏幕设备真实的像素点,一张图片就是由一个个像素点构成,屏幕也是有一个个像素点构成,一个iPhone6的设备像素是750*1334,屏幕制造商制作行内标准制定,属于物理范畴,不能修改。

独立像素(逻辑像素)

逻辑像素,操作系统规约定义的一种长度单位。规定一个独立像素等于两个物理像素,那么iPhone6的设备的独立像素是 375 * 667像素,主流操作系统产商按标准规定,属于协议规约范畴。

CSS像素

网页制作中CSS样式语言中定义的长度单位,如今(iPhone4开始)CSS中1px就是1CSS像素等于1独立像素,属于语言协会制定标准。

devicePixelRatio设备像素比

js中也引入了设备devicePixeRito像素比的概念,描述物理像素与独立像素之比(物理像素/独立像素),可以在BOM对象(window)中查看,使用window.devicePixelRatio进行查看。

resolution

媒体查询中的resolution变量就是指window.devicePixelRatio

@media (min-resolution: 2dppx) {
  
}

场景理解

远古时代(iPhone3物理像素:320*480),当时1CSS像素=1物理像素。假设我们就学会了编程且是前端,设计网页是按照iPhone3尺寸来进行设计,为了我们的网页能够占满屏幕,我们在CSS样式中设定width: 320px,当时是刚好占满屏幕。可是苹果公司在iPhone4时推出了Retina 屏幕物理像素变成:640*960,屏幕尺寸没有变化。原本设置的网页在iPhone4中就占一半,巨丑!所以新时代救星来了,独立像素的到来,1CSS=1独立像素=2物理像素,这个时候我们的网页在iPhone3、iPhone4都可以占满屏幕了!因为iPhone4屏幕像素(高清屏幕)看得更加的清楚,同理图片也是如此,像素越多越清晰,但体积越大。

尺寸参考

参考网址链接:https://material.io/resources/devices/,其中dp列为独立像素,px列为物理像素。大家觉得搜集麻烦的话可以去我的资源收录网站:http://n.huasenjio.top/,有很多实用的资源网站!

尺寸参考

rem布局实现

理念

rem是CSS中的一个长度单位,html根元素中的font-size的值就是1rem,例如你在写样式的时候为html标签(:root伪类)设置了font-size: 14px,那么1rem就是14px,当你修改html的font-size值时,rem也会发生变化。一句话概括就是为html标签定义font-size值,在写样式的时候用rem代替px。固定大小的标签尽量使用rem,自由伸缩元素使用百分比布局或者flex布局。

1)js

因为视口viewport的出现,head标签中的<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">,获取屏幕实际的真实物理屏幕像素已经很简单了,根据js查询到当前屏幕的px值,通过js动态修改html标签的font-size值,父元素宽高值设置rem,子元素设置相对于父元素的百分比宽高的理念就能简单实现一个rem布局。

// 立即执行函数
function () {
  const setHtmlFontSize = () => document.documentElement.style.fontSize = document.documentElement.clientWidth / 100
  window.addEventListener('DOMContentLoaded,setHtmlFontSize, false) // 初始的 HTML 文档被完全加载和解析完成调用
  window.addEventListener('orientationchange',setHtmlFontSize, false) // 屏幕横竖转换时候调用
} ()

把屏幕分为100份,每一份就是一个1rem,例如你的手机是iPhone6(375px),那么1rem==37.5px,每一个屏幕都是下100rem就会占满一块屏幕。如果我们拿到的设计稿是750的物理像素的iPhone6设计稿,那么独立像素就是370px,我们通过马克鳗量到一个元素是30px,那么我们设置元素的宽度时就别写width: 30px,正确的姿势应该是width: 30/37.5rem,为了避免麻烦我们建议使用sass(css增强语言),定义一个转换sass方法。

@function px2rem($px) {
  @return $px / 37.5 + rem; // 使用时width: px2rem(30)
}

2)devicePixelRatio

通过document.documentElement.clientWidth获得文档像素再动态修改html标签的font-size的方式,进而给父元素设置CSS宽高距离等使用rem代替px的理念。大屏幕环境下,元素位置宽高不会发生太大改变,而元素内的子元素例如图片文字等则会变化得很小,类似于百分比布局,导致块大内容不佳的问题。出现了新的方案就是利用到js对象devicePixelRatio,查询到当前屏幕的设备像素比,动态设置htmt的font-size值、viewport的mata标签的initial-scale(缩放比例)。设置初始的1rem=30px,devicePixelRatio==2的屏幕下1rem =30*2,而<meta name="viewport">的值始终是initial-scale = 1 / dpr,当initial-scale ==1时是正常显示,显示得相对清楚。

'use strict';

/**
 * 不用自己添加mata的viewport标签
 * @param {Boolean} [normal = false] - 是否正常显示;  
 * @param {Number} [baseFontSize = 100] - 初始字体大小100px;
 * @param {Number} [fontscale = 1] - 字体缩放比例;
 */
const win = window;
export default win.flex = (normal, baseFontSize, fontscale) => {
  const _baseFontSize = baseFontSize || 100;
  const _fontscale = fontscale || 1;

  const doc = win.document; // 获得到文档对象
  const ua = navigator.userAgent; // 获取到客户端信息
  const matches = ua.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i); // 进行匹对
  const UCversion = ua.match(/U3\/((\d+|\.){5,})/i);
  const isUCHd = UCversion && parseInt(UCversion[1].split('.').join(''), 10) >= 80;
  const isIos = navigator.appVersion.match(/(iphone|ipad|ipod)/gi);
  let dpr = win.devicePixelRatio || 1;
  if (!isIos && !(matches && matches[1] > 534) && !isUCHd) {
    // 如果非iOS 非Android4.3以上 非UC内核 dpr设为1 不高清;
    dpr = 1;
  }
  const scale = normal ? 1 : 1 / dpr;

  let metaEl = doc.querySelector('meta[name="viewport"]'); // 样式选择器
  if (!metaEl) {
    metaEl = doc.createElement('meta');
    metaEl.setAttribute('name', 'viewport');
    doc.head.appendChild(metaEl);
  }
	// 设置mata的viewport标签
  metaEl.setAttribute('content', `width=device-width,user-scalable=no,initial-scale=${scale},maximum-scale=${scale},minimum-scale=${scale}`);
  doc.documentElement.style.fontSize = normal ? '50px' : `${_baseFontSize / 2 * dpr * _fontscale}px`;
};

vue项目适配rem布局

rem的原理将物理像素px分为一百份,每一份就是1rem,例如当你的手机是苹果6s,物理像素是375px,那么转化成rem就是37.5px。插件设置html根标签的字体属性font-size变为1rem,通过转换将css中的px转换成对应的rem。当屏幕发生大小缩放的时候,更改html下的font-size的大小,就能实现了其他标签的大小距离也随比例缩放,达到rem自适应布局。

1)安装依赖

npm i lib-flexible postcss-px2rem --save

2)删除index.html中的<meta name=‘viewport’ >视口标签

flexible会为页面根据屏幕自动添加<meta name='viewport' >标签,动态控制initial-scale,maximum-scale,minimum-scale等属性的值,不删除会造成重复追加,导致代码冗余等情况。

3) 入口文件main.js文件中引入依赖

import 'lib-flexible'

4)配置vue.config.js文件

module.exports = {
  devServer: {
    port: 3000,
    open: true
  },
  // rem 的配置
  css: {
    loaderOptions: {
      css: {},
      postcss: {
        plugins: [
          require('postcss-px2rem')({
            // 适配375px屏幕 设计图750中量出来的尺寸要 / 2
            remUnit: 37.5
          })
        ]
      }
    }
  }
}
  • 12
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值