关于rem:Rem布局的原理解析

什么是Remrem和em很容易混同,其实两个都是css的单位,并且也都是绝对单位,现有的em,css3才引入的rem,在介绍rem之前,咱们先来理解下em。 em作为font-size的单位时,其代表父元素的字体大小,em作为其余属性单位时,代表本身字体大小——MDN 我在面试时常常问会一道和em无关的题,来看一下面试者对css细节的理解水平,如下,问s1、s2、s5、s6的font-size和line-height别离是多少px,先来想一想,结尾处有答案和解释。<div class="p1"> <div class="s1">1</div> <div class="s2">1</div></div><div class="p2"> <div class="s5">1</div> <div class="s6">1</div></div> .p1 {font-size: 16px; line-height: 32px;}.s1 {font-size: 2em;}.s1 {font-size: 2em; line-height: 2em;} .p2 {font-size: 16px; line-height: 2;}.s5 {font-size: 2em;}.s5 {font-size: 2em; line-height: 2em;} em能够让咱们的页面更灵便,更强壮,比起到处写死的px值,em仿佛更有张力,改变父元素的字体大小,子元素会等比例变动,这一变动仿佛预示了有限可能。有些人提出用em来做弹性布局页面,但其简单的计算让人诟病,甚至有人专门做了个px和em的计算器,不同节点像素值对应的em值,o(╯□╰)o。 em做弹性布局的毛病还在于牵一发而动全身,一旦某个节点的字体大小发生变化,那么其后辈元素都得从新计算,X﹏X。 rem作用于非根元素时,绝对于根元素字体大小;rem作用于根元素字体大小时,绝对于其出初始字体大小——MDN rem取值分为两种状况,设置在根元素时和非根元素时,举个例子:/ 作用于根元素,绝对于原始大小(16px),所以html的font-size为32px/html {font-size: 2rem} / 作用于非根元素,绝对于根元素字体大小,所以为64px /p {font-size: 2rem} rem有rem的长处,em有em的长处,尺有所短,寸有所长,我始终不感觉技术没有什么对错,只有适宜不适宜,有对错的是应用技术的人,卓越与优良的区别就在于是否抉择适合的技术,并让其发挥优势。我始终感觉em就是为字体和行高而生的,有些时候子元素字体就应该绝对于父元素,元素行高就应该绝对于字体大小;而rem的有点在于对立的参考系。Rem布局原理rem布局的实质是什么?这是我问过很多人的一个问题,但失去的答复都差强人意。其实rem布局的实质是等比缩放,个别是基于宽度,试想一下如果UE图可能等比缩放,那该如许美妙啊。假如咱们将屏幕宽度均匀分成100份,每一份的宽度用x示意,x = 屏幕宽度 / 100,如果将x作为单位,x后面的数值就代表屏幕宽度的百分比。p {width: 50x} / 屏幕宽度的50% / 如果想要页面元素随着屏幕宽度等比变动,咱们须要下面的x单位,可怜的是css中并没有这样的单位,侥幸的是在css中有rem,通过rem这个桥梁,能够实现神奇的x通过上面对rem的介绍,能够发现,如果子元素设置rem单位的属性,通过更改html元素的字体大小,就能够让子元素理论大小发生变化html {font-size: 16px}p {width: 2rem} / 32px/ html {font-size: 32px}p {width: 2rem} /64px/ 如果让html元素字体的大小,恒等于屏幕宽度的1/100,那1rem和1x就等价了html {fons-size: width / 100}p {width: 50rem} / 50rem = 50x = 屏幕宽度的50% / ...

July 8, 2022 · 2 min · jiezi

关于rem:响应式rem适配方案

说起挪动端适配,经常会想到rem,在这里写两种rem适配计划: 一、自定义配置在rem.scss文件中定义: /**设计稿的宽:$design_width设计稿的高:$design_height需本人定义**/@function px2rem($px) { @return $px / ($design_width / 10) * 1rem;}@function rem2px($rem) { @return $rem * ($design_width / 10) * 1px;}@function px2vh($px) { @return $px / $design_height * 100vh;}@function px2vw($px) { @return $px / $design_width * 100vw;}应用:引入rem.scss @import "./rem.scss";.table { width:px2rem(300); height: px2rem(180); margin: 0 px2rem(16);}二、flexible.js操作步骤: 1.装置lib-flexible.js npm install lib-flexible --save 2.在我的项目入口文件main.js 中引入lib-flexible import 'lib-flexible/flexible' 3.在VScode中装置cssrem插件 4.批改默认字体的大小 在设置中,搜寻框外面输出 cssroot 会显示用户和工作区,如果效果图是750,那这里就改成75,如果是375这里就改成37.5,要让rem单位换算正确; 5.而后就能够应用了

June 17, 2022 · 1 min · jiezi

关于rem:数据大屏rem适配方案

一般来说,做PC端的页面并不像挪动端那样对分辨率及屏幕大小有的特地强的要求,然而针对数据大屏这种展现型的页面来说,就须要思考适配的计划了,毕竟要尽可能的保障大部分的支流显示器都能失常展现。 市面上大部分的显示器简直都是16:9的尺寸,也就是1920 * 1080的分辨率。 现实中的成果当屏幕的尺寸比例刚好是16:9时,页面能刚好全屏展现,内容占满显示器 当屏幕的尺寸比例小于16:9时,页面高低留白,左右占满并高低居中,显示比例放弃16:9 当屏幕尺寸比例大于16:9时,页面左右留白,高低占满并居中,显示比例放弃16:9 当屏幕大小扭转时,动静计算两头内容的显示比例大小,保障内容始终放弃16:9 解决方案remrem(font size of the root element),是 css3 中新增的一个大小单位,即绝对于根元素 font-size 值的大小。 思路就是动静的计算出页面的fontsize从而扭转rem的大小。 思路首先拿 1920 * 1080 的规范屏幕大小为例。将屏幕分为10份,先计算rem的基准值: 1920 / 10 = 192 ,而后把所有元素的长,宽,地位,字体大小等原来的 px 单位全副转换成 rem, 网页加载后,用 js 去计算以后浏览器的宽度,并设置 html 的 font-size 为 (以后浏览器窗口宽度 / 10),这样的话10rem就刚好等于浏览器窗口的宽度。也就能够保障100%宽度,等比例缩放设计稿的页面了。 两件事: 取得 rem 的基准值。这边默认设置容器宽度为1920 * 1080,而后用1920 / 192 来计算rem的值页面内写一段js代码,动静的计算html根元素的font-size实现站在伟人的肩膀上,咱们不须要去从0到1去实现两个需要。 针对第一点: 首先装置 @njleonzhang/postcss-px-to-rem 这个包npm i @njleonzhang/postcss-px-to-rem -D复制代码新建.postcssrc.js配置文件module.exports = { plugins: { autoprefixer: {},"@njleonzhang/postcss-px-to-rem": { unitToConvert: 'px', // (String) 要转换的单位,默认是px。 widthOfDesignLayout: 1920, // (Number) 设计布局的宽度。对于pc仪表盘,个别是1920. unitPrecision: 3, // (Number) 容许 REM 单位增长到的十进制数字. selectorBlackList: ['.ignore', '.hairlines'], // (Array) 要疏忽并保留为 px 的选择器. minPixelValue: 1, // (Number) 设置要替换的最小像素值. mediaQuery: false // (Boolean) 容许在媒体查问中转换 px.}}}复制代码配置实现后,页面内的px就会被转换成rem了针对第二点: ...

December 8, 2021 · 1 min · jiezi

关于rem:vue使用rem适配

1.开发环境 vue2.电脑系统 windows10专业版3.在应用vue开发挪动端的过程中,咱们会因为兼容性而头疼,上面我来分享分享上面vue应用rem自适配,心愿对你有所帮忙。4.废话不多说,间接上操作: //装置 postcss-pxtoremnpm i postcss-pxtorem -S5.在src目录新建rem文件夹,上面新建rem.js,增加如下代码: //基准大小const baseSize = 37.5// 设置 rem 函数function setRem() { const salepro = document.documentElement.clientWidth / 750 // 以后页面宽度绝对于 750 宽的缩放比例,可依据本人须要批改. // 设置页面根节点字体大小 document.documentElement.style.fontSize = (baseSize * Math.min(salepro, 2)) + 'px'}// 初始化setRem()// 扭转窗口大小时从新设置 remwindow.onresize = function () { setRem()}6.在我的项目根目录新建 .postcssrc.js,增加代码如下: module.exports = { "plugins": { "postcss-pxtorem": { "rootValue": 37.5, "propList": ["*"] } }}留神:我在配置中,比例是1:1,也就是设计图宽是750px,你在css中间接写width:750px;就能够啦,不必进行换算,是不是很棒。7.在main.js中引入 import '@/rem/rem.js'8.在vue模板中应用,css中增加如下代码: <style lang="scss" scoped>.about { width: 750px; height: 100vh; box-sizing: border-box; background-color: blue !important; .kk { width: 350px; height: 350px; background-color: red; }}</style>9.效果图如下:10.本期的分享到了这里就完结啦,心愿对你有所帮忙,让咱们一起致力走向巅峰。 ...

February 5, 2021 · 1 min · jiezi

关于rem:苏宁首页lessrem媒体查询

技术选型计划:采纳独自制作挪动端页面技术选型:rem适配布局(less+ rem+ 媒体查问) 采纳750px设计尺寸 步骤1.搭建相干文件夹构造 2设置视口标签及引进css初始化款式 <!-- 设置视口标签 --> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <!-- 引进css初始化款式 --> <link rel="stylesheet" href="./css/normalize.css">3.新建common.less文件新建commem.less文件,设置好常见的尺寸,利用媒体查问设置不同的html字体大小关怀的尺寸有320px,360px,375px,384px,400px,414px,424px,480px,540px,720px,750px划分的分数设置为15等份pc端设置的html字体为50px(写在最下面)4.新建index.less文件新建index.less文件 指的是首页的款式将方才设置好的common.less文件导入index.less外面。最初把index.css文件引入html文件中@import 'common';

August 4, 2020 · 1 min · jiezi

REM布局原理

1 em、rem、meta标签的基本概念em 是一个布局的长度单位,当前对象内文本的字体大小的相对单位,也就是说相对于当前元素的font-size。 rem 是(根)字体大小相对单位,也就是说跟当前元素的font-size没有关系,而是跟整个body的font-size有关系。 物理像素是硬件的一个实际像素;而逻辑像素是我们在网页设计中使用的像素。它跟物理像素的关系是有一个设备像素比的关系,比如说设备像素比是2,那么就说明一个逻辑像素对应着4个物理像素,它们是一个平方的关系。 meta标签,我们可以指定浏览器的适口,适口就是可以看见的区域。然后它有三个需要了解的概念,分别是: layout viewport 浏览器的默认适口,也就是clientWidth,在PC端如果把浏览器最大化的时候我们可以发现clientWidth与innerWidth是相同的,但是在移动端是不一样的;它是移动设备默认的viewport。 visual viewport 浏览器的可视区域大小,在手机浏览器中的innerWidth是小于clientWidth,在PC端最大化的时候两者是一样的,但是在手机端最大化是两者是不一样的。 ideal viewport 是一个理想化的适口viewport。这个概念更多的取决于具体的需求,比如说在2倍的环境下开发和当前的尺寸下开发那么它的ideal viewport是不一样的。这里面有一个概念叫initial-scale 缩放比例,它是layout viewport相对于ideal viewport 的缩放比例。更准确的说ideal viewport是由layout viewport和initial-scale 缩放比例决定的。 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">上面代码的意思是:name是用来指定适口的,content 具体内容,第一个width宽度等于设备宽度,initial-scale缩放比例是1,最大的缩放比例也是1,然后不允许用户缩放。里面的width和initial-scale都是指定ideal viewport,如果两者都存在,那么取两者之间的较大值。 2 移动端的适配设备屏幕最终目标是设计稿能够等比缩放在设备上。既然我们要设计稿等比缩放在设备上,那么所有的设备都要有一个统一的适口,对我们而言统一的适口就叫做ideal viewport 理想的适口,我们得到这个理想的适口就需要动态的去处理Mate标签: 像素比 - 1 - scale=1像素比 - 2 - scale=2像素比 - 3 - scale=3获取设备的像素比首先获取像素比,根据设备的像素比来指定不同的initial-scale,像素比可能是1,2,3,那么我们在设置的时候就用1除以这个像素比。下面是一个动态处理Mate标签scale的代码: var devicePixelRatio = window.devicePixelRatio;var scale = 1 / devicePixelRatio;var metaElement = document.createElement('meta');metaElement.setAttribute('name', 'viewport'); metaElement.setAttribute( 'content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');document.documentElement.firstElementChild.appendChild(metaElement);处理完理想的ideal viewport接下来就要处理根节点的尺寸(font-size取适口的十分之一)。因为我们使用的rem布局在不同的设备上要有不同的根节点来保证我们得到的比例是一样的。 ...

July 4, 2019 · 1 min · jiezi

第三代移动端布局方案

第三代移动端布局方案大家有没有发现淘宝的H5移动端没有使用任何rem和vw单位,而是和web端项目一样,使用的是px单位。虽然是px但它也很完美的将整个页面渲染了出来。那淘宝的FE是怎么实现的呢?最近在研究关于布局的设计方案,通过学习理解阿里的fusion.design的设计思想并结合手机淘宝H5版的px布局问题。逐渐有了一些想法,这里进行综合整理,也算是抛砖引玉吧。1、rem和vwrem和vw都是为了解决移动端适配问题。rem方案中最成功的就是淘宝的lib-flexible了,它是通过javascript将整个布局分割成10份,从而进行有效布局。不过有计算dpr的问题,在一些dpr比较怪异的手机上会出现脱相的问题。后来又产生了vw布局,使用了vw之后,也再无需通过javascript的帮助进行布局的切分,而是自动的将整个布局切割为等分的100份,也就是1vw = 1%的页面宽度。1.1、 rem的问题在奇葩的dpr设备上表现效果不太好,比如 一些华为的高端机型 用rem布局会出现错乱。设置根字体大小的方式有两种,一种是媒体查询,优点:不需要额外使用js去更改html的字体,缺点:不连续,或者说并能完* 全实现对所有设备的布局规范统一;另一种是js动态更改html字体,优点:连续;缺点:不如直接写媒体查询的体验好;不支持css3 calc的需要大量密集的 @media hack;使用iframe引用也会出现问题;需要解决在ios上的1px边框问题,但是这个在lib-flexible中已经解决:(1px变2px, 又被 initial-scale=0.5 缩小了一半rem需要引入一个lib库html的font-size设置到12px以下还是会按照12px=1rem来计算,这样所有使用了rem单位的尺寸都是错的1.2、vw的问题支持程度不太好,安卓4.4以下都不支持1.3、它们共同的问题都需要计算以达到适配的目的额外引入工具,在编译阶段完成转换UI的回归测试不友好。毕竟设计稿是px,而页面是rem或vm。都是相对单位。rem 的比例是可以通过控制 html 字体大小来控制的,而vw的比例是固定的。无法和web项目共用统一套工程化方案,因为web项目不需要使用rem和vw单位。2、移动端布局的初衷可以轻松搞定任意布局通过设计稿,可以让应用在不同的设备上有完美的体验效果虽然rem和vw可以很好完成它们的初衷,不过同时它们也是有代价的(就是它们存在的问题)。那有没有一种方案可以规避掉以上rem和vw的问题又可以很好的完成初衷哪?2.1、一个新的Units单位(该小节摘自https://fusion.design/design/…)DP为UI设计中的唯一可用单位由于DP在不同设备中的叫法不同,且用于描述字号的单位有所不同(如SP,PT),但其基本计算方法和原则相同且通用,所以在设计过程中,我们考虑到严谨性,统一采用只写数字不带单位的方法书写。选用DP的原因像素密度PPI:指每英寸包含的像素(Px)个数如图同一物理尺寸(肉眼所见尺寸)下,低密度显示器的像素个数明显小于高密度显示器的像素个数,所以像素(PX)在多变的设备和分辨率下不是一个稳定可用的单位与密度无关的像素(DP):设备独立像素如图,DP与PX的对比可见,DP可以自适应屏幕的密度,不管屏幕密度怎么变化,实际显示的物理尺寸相同,DP可以保证物理尺寸的一致性,DP是目前最适合UI设计的单位,同时也是使代码语言相通的尺寸。转换公式当屏幕的PPI为160时,1DP=1PX;例:Iphone4,Iphone5,Iphone6,PPI为326,在这些屏幕之下1DP=2PXDP=(PX160)/PPIPX=DP(PPI/160)切图规则DP是与开发代码共用的语言,但一些需要置入的jpg,png等图片非矢量,依旧采用px作为单位,这个时候我们需要将图片适配到不同PPI的屏幕中去。图示,为一块banner适配到不同分辨率屏幕时的像素值:但实际场景中,无法为各种屏幕做切图适配,我么遵循大图可压缩小,小图不可变大的原则:【Mobile】选择3x图输出,适配于ios和andirod【Web】选择2x的图输出,适配普通屏幕和retina屏幕画布设置规则【Mobile】选择375667作为绘图尺寸【Andriod】 选择360640作为绘图尺寸【Web】使用1440宽作为绘图尺寸3、具体实现主要思路设计稿中统一使用dp作为像素单位,具体规则参考上面的切图规则和画布设计规则rem和vw多多少少存在各种问题,所以统一使用px作为实现单位web和wap可以使用同一套工程方案实现设计稿的dp到真实应用中px的映射关系,并且px会随着设备窗口大小的改变而改变当然,如果稿子是px的也可以手动将px转换为dp。想要实现这个整体方案,核心就在于第4条(实现设计稿的dp到真实应用中px的映射关系),并且这个过程只靠工程化的编译阶段是无法完美解决的,必须和浏览器运行时一起配合工作才能够达成我们的目标。前提业务模块的css不可以抽离为独立的css文件,必须输出在js文件中(style-loader的能力),这样才有改变css内容的基本能力。定义一个尺寸单位dp,标识这是在设计稿上的尺寸(类似于小程序中的rpx)。并不是所有的px都需要做弹性转换的,对于需要做弹性转换的容器的px统一改为dp,否则继续使用px。假设我们根据Mobile设计稿定义一个移动端H5的容器元素:<div class=“box”> <div class=“tip”>this is tip</div></div>.box { /* 这里使用的单位为dp,表示需要根据设备大小进行弹缩 / width: 100dp; height: 150dp; background: red;}.box .tip { / 使用的单位为px,不需要根据设备大小进行弹缩。无论设备怎么变化,该元素的宽高都是10像素。 */ width: 10px; height: 10px; background: blue;}最终,元素.box会根据设备的宽高的改变而改变自身的大小,下方就是.box元素在不同设备下的宽和高:设备宽度高度设计稿100dp150dpiPhone 5/SE85.33px128pxiPhone 6/7/8100px150pxiPhone 6/7/8 Plus110.4px165.60pxiPhone X100px150pxGalaxy S596px144px在实现这个功能必须先提供一个转换dp为px的帮助函数:unitParser。因为接下来的两种方式中都需要这个函数来帮助我们实现最终目的。const allowMiniPixel = () => { let allow = false; if (window.devicePixelRatio && devicePixelRatio >= 2) { let ele = document.createElement(“div”); ele.style.border = “.5px solid transparent”; document.body.appendChild(ele); allow = 1 === ele.offsetHeight; document.body.removeChild(ele); } return allow;}();function unitParser(unit) { let type = void 0 === unit ? “undefined” : getType(unit); if (“number” === type) { unit += “dp” } if (“string” !== type) { return unit; } let regExp = /^([\d.]+)(np|dp)?$/g; return unit.replace(regExp, (chars, count, suffix) => { count = Number(count) switch (suffix) { case “np”: // np不做转换。1np就是1px 100np就是100px break; case “dp”: default: // 注意这里375。说明的上文说了,设计稿是按照iphone 6的375进行设计的。 // deviceWidth为屏幕的宽度。iphone 5/SE为320、iphone 6/7/8为375 count = count / 375 * deviceWidth }; if (!allowMiniPixel && count < 1) { count = 1 } return count + “px”; })}3.2.1、方式一:styled-components + css-in-js + JSXVue:import styled from ‘vue-emotion’import unitParser from ‘./unitParser.js’;const box = styled(‘div’) width: ${unitParser("100dp")}; height: ${unitParser("150dp")}; background: red;const tip = styled(div) width: 10px; height: 10px; background: blue;new Vue({ render() { return ( <box> <tip>this is a tip</tip> </box> ) }})react:import styled from ‘styled-components’;import unitParser from ‘./unitParser.js’;const Box = styled.div width: ${unitParser("100dp")}; height: ${unitParser("150dp")}; background: red;const Tip = styled.div width: 10px; height: 10px; background: red;render( <Box> <Tip>this is a tip</Tip> </Box>)注意:使用此方案需要注意和sass、post-css等工具的结合使用问题,会增加一定的工程复杂度。另外这种方案会产生大量的元素style属性,导致dom复杂度增加。3.2.2、方式二:在浏览器运行时动态计算自定义一个webpack的css-loader,进行unitParser处理。function styleInject(css, ref) { if ( ref === void 0 ) ref = {}; var insertAt = ref.insertAt; if (!css || typeof document === ‘undefined’) { return; } var head = document.head || document.getElementsByTagName(‘head’)[0]; var style = document.createElement(‘style’); style.type = ’text/css’; if (insertAt === ’top’) { if (head.firstChild) { head.insertBefore(style, head.firstChild); } else { head.appendChild(style); } } else { head.appendChild(style); } if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); }}var css = “.box {width: " + unitParser(“100dp”) + “; height: " + unitParser(“150dp”) + “; background: red;} .box .tip {width: 10px; height:10px; background: blue}";styleInject(css);3.2.3、优缺点优点:文章开头所提到的rem和vw都存在众多问题,该方案都可以完美解决。还可以和其他任何单位混合使用,这意味这使用这种方案的同时还可以使用之前的rem和vw方式。缺点:不管使用方式一还是方式二,都会对项目的工程化复杂度增加,不过和目前处理rem以及vm的px2rem以及px2viewport等工具相比,这点复杂度根本不值一提。增加了js bundle文件的体积,减少了css文件的体积。不过没有整体的体积没有增加,仅仅是将部分业务的css内容搬到了js文件里。最后借用了大部分工程化的能力,主要还是用来css in js的能力但是这样有个缺点。就是视窗大小改变的时候会出现布局错乱。不过影响不大,因为真机里是不会出现窗口大小改版的。而且这一套方案完全抹平了web和wap的差异性,在开发层面完全一直。需要缩放就用dp,不需要就用np和px作为单位即可这套方案还是蛮不错的,比rem和vw好很多。确实属于第三代移动端布局方案了 ...

April 12, 2019 · 2 min · jiezi

移动端适配方案 (有demo)

移动端 Web 页面适配方案其中方案 1.3.4.5的demo地址移动端适配方案移动端 Web 页面,即常说的 H5 页面、手机页面、webview 页面等。手机机设备屏幕尺寸不一,做移动端的 Web 页面,需要考虑在安卓/IOS 的各种尺寸设备上的兼容,这里总结的是针对移动端设备的页面,设计与前端实现怎样做能更好地适配不同屏幕宽度的移动设备。适配的目标在不同尺寸的手机设备上,页面“相对性的达到合理的展示(自适应)”或者“保持统一效果的等比缩放(看起来差不多)”。<!– markdown-to-slides index.md -o index.html -s slide.css –>I. 概念的理解要搞懂移动端的适配问题,就要先搞明白像素和视口。像素在移动端给一个元素设置 width:200px 时发生了什么?这里的 px 到底是多长呢?像素是网页布局的基础,但是我们一直在用直觉使用它。iphone6 有 750 的物理像素,但是屏幕宽度像素是 375px???1.设备像素 device pixel设备像素是物理概念,指的是设备中使用的物理像素,任何设备屏幕的物理像素的数量都是固定不变的。比如 iphone6 的分辨率 1334 x 750px ,750px 指的是设备物理像素2.逻辑像素 css pixelcss 像素是 web 编程的概念,指的是 css 样式中使用的逻辑像素css px 是一个相对单位 相对的是设备像素我们网页 css 和小程序用的是逻辑像素eg:iphone6 使用的是 retina 视网膜屏幕2px x 2px 的设备像素代表 1px z 1px 的 css 像素所以设备像素 1334 x 750 css 逻辑像素是 667 x 375那么,我们现在再来说说一个元素 width:200px 以后会怎么样。这个元素跨越了 200 个 CSS 元素,200 个 CSS 元素相当于多少个设备像素取决于两个条件:页面是否缩放屏幕是否为高密度这两方面后面再解释,先梳理一下手机硬件之间的关系,注意这里使用的都是物理像素。以 iPhone5 为例,我们已知的是:1.分辨率 1136pt x 640pt指屏幕上垂直有 1136 个物理像素,水平有 640 个物理像素2.屏幕尺寸 4 英寸注意英寸是长度单位,不是面积单位。4 英寸指的是屏幕对角线的长度。3.屏幕像素密度 326ppi屏幕像素密度(Pibel Per Inch)简称 ppi ,单位是 dpi(dot per inch)。这里指屏幕水平或垂直每英寸有 326 个物理像素。原则上来说,ppi 越高越好,因为图像会更加细腻清晰。ppi 是可以通过 分辨率 和 屏幕尺寸 计算得到的:<img src="./ppi.png"/>这个网站列出了很多设备的分辨率和屏幕尺寸,并且计算了 ppi。这个网站列出了很多设备的分辨率和屏幕尺寸,并且计算了 ppi。视口桌面浏览器中,浏览器窗口就是约束你的 CSS 布局视口(又称初始包含块)。它使所有 CSS 百分比宽度推算的根源,它的作用是 CSS 布局限制了一个最大宽度,视口的宽度和浏览器窗口宽度一致。但是在移动端,情况就很复杂了。布局视口 layout viewport在手机上,视口与移动端浏览器屏幕宽度不再相关联,是完全独立的,这个浏览器厂商定的视口被称为布局视口。布局视口我们是看不见的,只知道网页的最大宽度是 980px ,并且被缩放在了屏幕内。可以这样设置布局视口的宽度:<meta name=“viewport” content=“width=640” />媒体查询与布局视口@media (min-width: 700px) { …;}document.documentElement.clientWidth/Height 返回布局视口的尺寸视觉视口 visual viewport有了 layout viewport,我们还需要一个视口用来承载它,这个视口可以简单的认为是手持设备物理屏幕的可视区域,视觉视口是用户正在看到的网页的区域,大小是屏幕中 CSS 像素的数量。window.innerWidth/Height 返回视觉视口的尺寸很明显,visual viewport 的尺寸不会是一个固定的值,甚至每款设备都可能不同。大致列几种常见设备的 visual viewport 尺寸:iPhone4iPhone5S: 320*480pxiPhone6iPhone6S: 375627pxiPhone6 Plus~iPhone6S Plus: 414736px以 iPhone4S 为例,会在其 320px② 的 visual viewport 上,创建一个宽 980px 的 layout viewport,于是用户可以在 visual viewport 中拖动或者缩放网页,来获得良好的浏览效果;布局视口用来配合 CSS 渲染布局,当我们定义一个容器的宽度为 100%时,这个容器的实际宽度是 980px 而不是 320px,通过这种方式大部分网页就能以缩放的形式正常显示在手机屏幕上了。理想视口(完美视口) ideal viewport布局视口明显对用户是不友好的,完全忽略了手机本身的尺寸。所以苹果引入了理想视口的概念,它是对设备来说最理想的布局视口尺寸。理想视口中的网页用户最理想的宽度,用户进入页面的时候不需要缩放。<meta name=“viewport” content=“width=device-width” />定义理想视口是浏览器的事情,并不能简单地认为是开发者定义的,开发者只能使用。screen.width/height 返回理想视口的尺寸,有严重的兼容性问题—可能返回两种值:理想视口的尺寸(下载浏览器)屏幕的设备像素尺寸(内置浏览器)Screen size tests 和 Understanding viewport 可以测试你的设备的 screen.width 值,同一设备的不同浏览器返回的值可能是不一样的。这一情况主要发生在默认浏览器和下载浏览器(如 UC、Chrome)之间。关于 3 个视口,PPK已经做了非常棒的阐释,你也可以在 StackOverflow 上找到一些对此描述的相互补充,例如:1, 2,有兴趣的童鞋也可以看看缩放缩放是在放大或缩小 CSS 像素,比如一个宽度为 200px 的元素无论放大,还是 200 个 CSS 像素。但是因为这些像素被放大了,所以 CSS 像素也就跨越了更多的设备像素。缩小则相反。缩放与视口缩放会影响视觉视口的尺寸页面被用户放大,视觉视口内 CSS 像素数量减少;被用户缩小,视觉视口内 CSS 像素数量增多就行了。这个道理应该是不难想的。用户缩放不会影响布局视口在下载浏览器中,可以这么算(理想视口与视觉视口的比):zoom level = screen.width / window.innerWidth禁止缩放<meta name=“viewport” content=“user-scalable=no” />设置缩放<meta name=“viewport” content=“initial-scale=2” />使用 initial-scale 有一个副作用:同时也会将布局视口的尺寸设置为缩放后的尺寸。所以 initial-scale=1 与 width=device-width 的效果是一样的。完美视口解决各种浏览器兼容问题的理想视口设置<meta name=“viewport” content=“width=device-width,initial-scale=1” />设备像素比屏幕是否为高密度也会影响设备像素和 CSS 像素的关系。在缩放程度为 100%(这个条件很重要,在后面会说到)时,他们的比例叫做设备像素比(device pixel ratio):dpr = 设备像素 / CSS 像素可以通过 JS 得到: window.devicePixelRatio设备像素比也和视口有关:dpr = 屏幕横向设备像素 / 理想视口的宽viewport 特性NameValuedescriptionwidth正整数或 device-width定义视口的宽度,单位为像素height正整数或 device-height定义视口的高度,单位为像素initial-scale[0.0-10.0]定义初始缩放值minimum-scale[0.0-10.0]定义缩小最小比例,它必须小于或等于 maximum-scale 设置maximum-scale[0.0-10.0]定义放大最大比例,它必须大于或等于 minimum-scale 设置user-scalableyes/no定义是否允许用户手动缩放页面,默认值 yeswidthwidth 被用来定义 layout viewport 的宽度,如果不指定该属性(或者移除 viewport meta 标签),则 layout viewport 宽度为厂商默认值。initial-scale如果想页面默认以某个比例放大或者缩小然后呈现给用户,那么可以通过定义 initial-scale 来完成。<meta name=“viewport” content=“initial-scale=2” />那么用户将会看到 2 倍大小的页面内容。maximum-scale在移动端,你可能会考虑用户浏览不便,然后给予用户放大页面的权利,但同时又希望是在一定范围内的放大,这时就可以使用 maximum-scale 来进行约束。<meta name=“viewport” content=“initial-scale=1,maximum-scale=5” />假设页面的默认缩放值 initial-scale 是 1,那么用户最终能够将页面放大到这个初始页面大小的 5 倍。minimum-scale类似 maximum-scale 的描述,不过 minimum-scale 是用来指定页面缩小比例的。通常情况下,为了有更好地体验,不会定义该属性的值比 1 更小,因为那样页面将变得难以阅读。user-scalable如果你不想页面被放大或者缩小,通过定义 user-scalable 来约束用户是否可以通过手势对页面进行缩放即可。<meta name=“viewport” content=“user-scalable=no” />II. 移动端适配方案1.使用百分比+媒体查询 test.1.html2.使用 flexbox3.使用 rem + viewport test.3.html4.使用 rem test.4.html5.固定布局视口宽度,使用 viewport 进行缩放 test.5.html在 iphone6p 下 test.1.html 和 test.3.html 适配对比<img src="./iphone6p1-3.png"/>rem 是什么相对长度单位,相对于根元素(即 html 元素)font-size 计算值的倍数兼容性<img src="./rem.png"/>浏览器默认为 16px 可能造成 rem 计算上的麻烦和多位小数,所以,我们也可以使用 100px 初始化根元素:<img src="./computed.png" height=“220” width=“650”/>1.使用百分比+媒体查询meida queries 的方式可以说是我早期采用的布局方式,它主要是通过查询设备的宽度来执行不同的 css 代码,最终达到界面的配置。核心语法是:@media screen and (max-width: 600px) { /当屏幕尺寸小于600px时,应用下面的CSS样式/ /你的css代码/}优点media query 可以做到设备像素比的判断,方法简单,成本低,特别是对移动和 PC 维护同一套代码的时候。目前像 Bootstrap 等框- 架使用这种方式布局图片便于修改,只需修改 css 文件调整屏幕宽度的时候不用刷新页面即可响应式展示缺点代码量比较大,维护不方便为了兼顾大屏幕或高清设备,会造成其他设备资源浪费,特别是加载图片资源为了兼顾移动端和 PC 端各自响应式的展示效果,难免会损失各自特有的交互方式2.以天猫首页为代表的 flex 弹性布局[表示怀疑]它的 viewport 是固定的:<meta name=“viewport” content=“width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no”/>高度定死,宽度自适应,元素都采用 px 做单位。随着屏幕宽度变化,页面也会跟着变化,效果就和 PC 页面的流体布局差不多,在哪个宽度需要调整的时候使用响应式布局调调就行(比如网易新闻),这样就实现了『适配』。3.rem + viewport 缩放这也是淘宝使用的方案,根据屏幕宽度设定 rem 值,需要适配的元素都使用 rem 为单位,不需要适配的元素还是使用 px 为单位。实现原理如 iphone6 plus 的 dpr 为 3, 则页面整体放大 3 倍, 1px(css 单位)在 plus 下默认为 3px(物理像素)然后 viewport 设置为 1/3, 这样页面整体缩回原始大小. 从而实现高清。这样整个网页在设备内显示时的页面宽度就会等于设备逻辑像素大小,也就是 device-width。 这个 device-width 的计算公式为:设备的物理分辨率/(devicePixelRatio * scale), 在 scale 为 1 的情况下,device-width = 设备的物理分辨率/devicePixelRatio 。当设计以 iphone6 为标准,出 750px 的设计稿时,此时 dpr=2width = document.documentElement.clientWidth = 375px;rem = 375px / 7.5 = 50px; // font-size = 50pxdpr = 2 时, 1rem = 100px, initial-scale=0.5, 缩放为0.5。4.rem 实现根据不同屏幕动态写入 font-size,以 rem 作为宽度单位,固定布局视口。<meta name=“viewport” content=“width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no”/>以 640px 设计稿和 750px 的视觉稿,网易这样处理的:var width = document.documentElement.clientWidth // 屏幕的布局视口宽度var rem = width / 7.5 // 750px设计稿将布局视口分为7.5份var rem = width / 6.4 // 640px设计稿将布局视口分为6.4份在 750px 设计稿上://在ipone6上:width = document.documentElement.clientWidth = 375px;rem = 375px / 7.5 = 50px; // font-size = 50px//在ipone5上:width = document.documentElement.clientWidth = 320px;rem = 320px / 7.5 = 42.667px; // font-size = 42.667px;百分比适配,没有 1px 适配,有字体大小适配。通过以下代码来控制 rem 基准值(设计稿以 720px 宽度量取实际尺寸)documentElementdevicePixelRatio!(function(d) { var c = d.document var a = c.documentElement var b = d.devicePixelRatio var f function e() { var h = a.getBoundingClientRect().width, g if (b === 1) { h = 720 } if (h > 720) h = 720 //设置基准值的极限值 g = h / 7.2 a.style.fontSize = g + ‘px’ } if (b > 2) { b = 3 } else { if (b > 1) { b = 2 } else { b = 1 } } a.setAttribute(‘data-dpr’, b) d.addEventListener( ‘resize’, function() { clearTimeout(f) f = setTimeout(e, 200) }, false ) e()})(window)5.固定布局视口宽度,使用 viewport 进行缩放如:荔枝 FM、网易应用固定布局视口,宽度设置固定的值,总宽度为 640px,根据屏幕宽度动态生成 viewport。(设计稿应该是 640px 的)<meta name=“viewport” content=“width=640, minimum-scale = 0.5625, maximum-scale = 0.5625, target-densitydpi=device-dpi”/>网页宽度始终为 640px。缩放比例 scale 为:var scale = window.screen.width / 640百分比适配,部分 1px 适配,没有字体适配。微信新增尺寸单位 rpx新增了尺寸单位。在写 CSS 样式时,开发者需要考虑到手机设备的屏幕会有不同的宽度和设备像素比,采用一些技巧来换算一些像素单位。WXSS 在底层支持新的尺寸单位 rpx ,开发者可以免去换算的烦恼,只要交给小程序底层来换算即可,由于换算采用的浮点数运算,所以运算结果会和预期结果有一点点偏差。rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为 750rpx。如在 iPhone6 上,屏幕宽度为 375px,共有 750 个物理像素,则 750rpx = 375px = 750 物理像素,1rpx = 0.5px = 1 物理像素。设备物理像素css 像素rpx->pxpx->rpxiPhone5320px320px1rpx = 0.42px1px = 2.34rpxiPhone6750px375px1rpx = 0.5px1px = 2rpxiPhone6+1080px414px1rpx = 0.552px1px = 1.81rpx建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。III. 响应式和自适应自适应是最早出现的,后面才有了响应式。响应式布局等于流动网格布局,而自适应布局等于使用固定分割点来进行布局。响应式的基本概念是(Responsive design):简而言之,就是一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本。自适应的解释(Adaptive design):自适应布局给了你更多设计的空间,因为你只用考虑几种不同的状态。如果用响应式布局来处理的话,用不同设备(电脑、平板、手机)去访问此页面,最后看到的布局和内容有很大不同。而如果用自适应布局去处理的话,那不管访问设备如何的不同(下图是三台尺寸不一样的手机),最后看到的页面内容和布局基本上还是一样的,就是尺寸略有不同。响应式京东云官网 (栅格系统 + 媒体查询)pro-list-hd hidden-xsMicrosoft (栅格系统 + 媒体查询)col-6 pad-6x华为 (栅格系统 + 媒体查询 )col-sm-4 col-pd-12 col-mb-12自适应携程淘宝实现响应式有哪几种方式?1.使用媒体查询(Media Query) 结合 rem 字体// 如果大于1000px,就用:对应PC端页面@media screen and (min-width: 1000px) { …;}// 如果在小于1000px和大于768px之间: 对应平板端页面@media screen and (max-width: 1000px) and (min-width: 768px) { …;}// 如果小于768px: 对应手机端页面@media screen and (max-width: 768px) { …;}2.使用插件bootstrap栅格化布局,本例利用 bootstarp 的栅格系统<img src="./sgxt.png" /><img src="./sg.png" /><img src="./768.png" height=“170”/><img src="./769.png" height=“170”/><img src="./992.png" height=“170”/>3.使用弹性布局(flex)flexVI. 移动端适配总结1 像素边框高清高清图问题1 像素边框高清在移动端 web 开发中,UI 设计稿中设置边框为 1 像素,前端在开发过程中如果出现 border:1px,测试会发现在某些机型上,1px 会比较粗,即是较经典的移动端 1px 像素问题。项目中引入:border-1px.css,然后通过控制元素的 before 和 after 伪元素,改变 border 大小或颜色。上面说到的淘宝的实现方式即 rem+viewport 缩放来实现。div { width: 1px; height: 100%; display: block; border-left: 1px solid #e5e5e5; -webkit-transform: scale(0.5); transform: scaleX(0.5);}缺点:圆角无法实现,实现 4 条边框比较麻烦,并且只能单独实现,如果嵌套,会对包含的效果产生不想要的效果,所以此方案配合:after 和 before 独立使用较多。box-shadow利用 CSS 对阴影处理的方式实现 0.5px 的效果-webkit-box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5);优点:基本所有场景都能满足,包含圆角的 button,单条,多条线。缺点:颜色不好处理, 黑色 rgba(0,0,0,1) 最深的情况了。有阴影出现,不好用。大量使用 box-shadow 可能会导致性能瓶颈。四条边框实现效果不理想。图片实现使用 background-image 实现 1px 有两种方式: 渐变 linear-gradient 或直接使用图片(base64)。渐变 linear-gradient (50%有颜色,50%透明)单线条div { height: 1px; background-image: -webkit-linear-gradient(top, transparent 50%, #000 50%); background-position: top left; background-repeat: no-repeat; background-size: 100% 1px;}优点: 可以设置单条,多条边框 可以设置颜色缺点: 大量使用渐变可能导致性能瓶颈 代码量大 多背景图片有兼容性问题高清图问题1. 使用 srcset 标签(WebKit 最新特性 srcset 简介)<img src=“http://g.ald.alicdn.com/bao/uploaded/i1/TB1d6QqGpXXXXbKXXXXXXXXXXXX_!!0-item_pic.jpg_160x160q90.jpg" srcset=” http://img01.taobaocdn.com/imgextra/i1/803091114/TB2XhAPaVXXXXXmXXXXXXXXXXXX_!!803091114.jpg 2x, http://gtms04.alicdn.com/tps/i4/TB1wDjWGXXXXXbtXVXX6Cwu2XXX-398-510.jpg_q75.jpg 3x “/>2. 使用 js 自带的 Image 异步加载图片<img id=“img” data-src1x=“xxx@1x.jpg” data-src2x=“xxx@2x.jpg” data-src3x=“xxx@3x.jpg”/>var dpr = window.devicePixelRatioif (dpr > 3) { dpr = 3}var imgSrc = $(’#img’).data(‘src’ + dpr + ‘x’)var img = new Image()img.src = imgSrcimg.onload = function(imgObj) { $(’#img’) .remove() .prepend(imgObj) //替换img对象}3. 背景图片高清解决方法(对于 dpr=2,1 个 css 像素对应 4 个物理像素)对于 dpr=1,物理像素和 css 相同,图片高清。但对于 dpr=2,导致每个像素点实际上有 4 倍的普通像素点,反过来说,一个 CSS 像素点实际分成了四个,这样就造成了颜色只能近似选取,于是,我们看上去就变得模糊了。所以使用 2x 的图片就刚刚好。使用 media 来处理/* 普通显示屏(设备像素比例小于等于1)使用1倍的图 /.css { background-image: url(img_1x.png);}/ 高清显示屏(设备像素比例大于等于2)使用2倍图 /@media only screen and (-webkit-min-device-pixel-ratio: 2) { .css { background-image: url(img_2x.png); }}使用 image-set 来处理https://www.html.cn/book/css/….css { background-image: url(1x.png); /不支持image-set的情况下显示/ background: -webkit-image-set( url(1x.png) 1x, / 支持image-set的浏览器的[普通屏幕]下 / url(2x.png) 2x, / 支持image-set的浏览器的[2倍Retina屏幕] / url(3x.png) 3x / 支持image-set的浏览器的[3倍Retina屏幕] */ );}IV. 总结移动端 Web 页面适配方案移动端适配方案(上)移动前端开发之 viewport 的深入理解深入了解 viewport 和 pxMobileWeb 适配总结移动端适配方案(下)移动端 H5 页面高清多屏适配方案移动前端第一弹:viewport 详解前端移动端适配总结移动前端自适应适配布局解决方案移动端页面适配———多方案解析移动端适配之 REM移动端前端适配方案移动端适配方案一 弹性布局移动端适配方案移动端 1 像素边框问题的解决方案移动端适配问题<center>– End –</center> ...

March 25, 2019 · 5 min · jiezi