Rem布局的原理解析

article/2025/9/16 22:26:16

Rem布局的原理解析

tobAlier关注

22017.10.25 11:27:32字数 2,630阅读 12,367

什么是Rem

rem和em很容易混淆,其实两个都是css的单位,并且也都是相对单位,现有的em,css3才引入的rem,在介绍rem之前,我们先来了解下em:

em作为font-size的单位时,其代表父元素的字体大小,em作为其他属性单位时,代表自身字体大小——MDN

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元素的字体大小,就可以让子元素实际大小发生变化

/* 作用于根元素,相对于原始大小(16px),所以html的font-size为32px*/
html{font-size:2rem}
/* 作用于非根元素,相对于根元素字体大小,所以为64px */
p{font-size:2rem}

如果让html元素字体的大小,恒等于屏幕宽度的1/100,那1rem和1x就等价了

html{fons-size:width/100}
p{width:50rem}
/* 50rem = 50x = 屏幕宽度的50% */

如何让html字体大小一直等于屏幕宽度的百分之一呢? 可以通过js来设置,一般需要在页面dom ready、resize和屏幕旋转中设置

document.documentElement.style.fontSize=document.documentElement.clientWidth/100+'px';
UE图宽度UE图中元素宽度
640px100px
480px75px
320px50px

那么如何把UE图中的获取的像素单位的值,转换为已rem为单位的值呢?公式是元素宽度 / UE图宽度 * 100,让我们举个例子,假设UE图尺寸是640px,UE图中的一个元素宽度是100px,根据公式100/640*100 = 15.625
p{width:15.625rem}
下面来验证下上面的计算是否正确,下面的表格是UE图等比缩放下,元素的宽度

UE图宽度UE图中元素宽度
640px100px
480px75px
320px50px
页面宽度html字体大小p元素宽度
640px640/100 = 6.4px15.625*6.4=100px
480px480/100=4.8px15.625*4.8=75px
320px320/100=3.2px15.625*3.2=50px

下面的表格是通过我们的元素在不同屏幕宽度下的计算值

页面宽度html字体大小p元素宽度
640px640/100 = 6.4px15.625*6.4=100px
480px480/100=4.8px15.625*4.8=75px
320px320/100=3.2px15.625*3.2=50px

可以发现,UE图宽度和屏幕宽度相同时,两边得出的元素宽度是一致的
上面的计算过程有些繁琐,可以通过预处理的function来简化过程,下面是sass的例子,less类似

$ue-width:640;/* ue图的宽度 */
@functionpx2rem($px){@return#{$px/$ue-width*100}rem;}
p{width:px2rem(100);}

上面的代码编译完的结果如下

p{width:15.625rem}

其实有了postcss后,这个过程应该放到postcss中,源代码如下

p{width:100px2rem}

postcss会对px2rem这个单位进行处理,处理后的结果如下,感兴趣的话来写一个px2rem的postcss插件吧

p{width:15.625rem}

比Rem更好的方案
上面提到想让页面元素随着页面宽度变化,需要一个新的单位x,x等于屏幕宽度的百分之一,css3带来了rem的同时,也带来了vw和vh
vw —— 视口宽度的 1/100;vh —— 视口高度的 1/100 —— MDN
聪明的你也许一经发现,这不就是单位x吗,没错根据定义可以发现1vw=1x,有了vw我们完全可以绕过rem这个中介了,下面两种方案是等价的,可以看到vw比rem更简单,毕竟rem是为了实现vw么

/* rem方案 */
html{fons-size:width/100}
p{width:15.625rem}
/* vw方案 */
p{width:15.625vw}
vw还可以和rem方案结合,这样计算html字体大小就不需要用js了
html{fons-size:1vw}
/* 1vw = width / 100 */
p{width:15.625rem}
兼容性Ios安卓
rem4.1+2.1+
vw6.1+4.4+

虽然vw各种优点,但是vw也有缺点,首先vw的兼容性不如rem好,使用之前要看下

兼容性Ios安卓
rem4.1+2.1+
vw6.1+4.4+

另外,在使用弹性布局时,一般会限制最大宽度,比如在pc端查看我们的页面,此时vw就无法力不从心了,因为除了width有max-width,其他单位都没有,而rem可以通过控制html根元素的font-size最大值,而轻松解决这个问题

Rem不是银弹
rem是弹性布局的一种实现方式,弹性布局可以算作响应式布局的一种,但响应式布局不是弹性布局,弹性布局强调等比缩放,100%还原;响应式布局强调不同屏幕要有不同的显示,比如媒体查询

用户选择大屏幕有两个几个出发点,有些人想要更大的字体,更大的图片,比如老花眼的我;有些人想要更多的内容,并不想要更大的图标;有些人想要个镜子。。。——颜海镜

我认为一般内容型的网站,都不太适合使用rem,因为大屏用户可以自己选择是要更大字体,还是要更多内容,一旦使用了rem,就剥夺了用户的自由,比如百度知道,百度经验都没有使用rem布局;一些偏向app类的,图标类的,图片类的,比如淘宝,活动页面,比较适合使用rem,因为调大字体时并不能调大图标的大小,rem可以做到100%的还原度,但同事rem的制作成本也更大,同时使用rem还有一些问题,下面我们一一列举下:
首先是字体的问题,字体大小并不能使用rem,字体的大小和字体宽度,并不成线性关系,所以字体大小不能使用rem;由于设置了根元素字体的大小,会影响所有没有设置字体大小的元素,因为字体大小是会继承的,难道要每个元素都显示设置字体大小???
我们可以在body上做字体修正,比如把body字体大小设置为16px,但如果用户自己设置了更大的字体,此时用户的设置将失效,比如合理的方式是,将其设置为用户的默认字体大小

html{fons-size:width/100}
body{font-size:16px}

那字体的大小如何实现响应式呢?可以通过修改body字体的大小来实现,同时所有设置字体大小的地方都是用em单位,对就是em,因为只有em才能实现,同步变化,我早就说过em就是为字体而生的'

@mediascreenand(min-width:320px){body{font-size:16px}}
@mediascreenand(min-width:481px)and(max-width:640px){body{font-size:18px}}
@mediascreenand(min-width:641px){body{font-size:20px}}p{font-size:1.2em}pa{font-size:1.2em}

第二,如果用户在PC端浏览,页面过宽怎么办?一般我们都会设置一个最大宽度,大于这个宽度的话页面居中,两边留白

varclientWidth=document.documentElement.clientWidth;
clientWidth=clientWidth<780clientWidth:780;
document.documentElement.style.fontSize=clientWidth/100+'px';

设置body的宽度为100rem,并水平居中

body{margin:auto;width:100rem}

第三,如果用户禁用了js怎么破?其实这种用户真不多了,要不放弃吧。。。
首先可以添加noscript标签提示用户
开启JavaScript,获得更好的体验
给html添加一个320时的默认字体大小,保证页面可以显示
html {fons-size: 3.2px}
如果你想要更好的体验,不如添加媒体查询吧'

@mediascreenand(min-width:320px){html{font-size:3.2px}}
@mediascreenand(min-width:481px)and(max-width:640px){html{font-size:4.8px}}
@mediascreenand(min-width:641px){html{font-size:6.4px}}

rem不是银弹,这个世上也没有银弹,每个方案都有其优点,也有其缺点,学会做出选择和妥协
Rem布局方案
通过上面可以得出最好的弹性布局方案是,rem+js方案,同时还要解决noscript问题,解决字体问题,解决屏幕过宽问题,但是上面的方案还有个问题,就是分成100份的话,假设屏幕宽度320,此时html大小是3.2px,但浏览器支持最小字体大小是12px,怎么办?那就分成10份呗,只要把上面的100都换成10就好了
下面给一个完整的例子,css的计算没有使用预处理器,这个很简单
html代码如下

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><title>rem布局</title>
</head>
<body><noscript>开启JavaScript,获得更好的体验</noscript><div class="p1">宽度为屏幕宽度的50%,字体大小1.2em<div class="s1">字体大小1.2.em</div></div><div class="p2">宽度为屏幕宽度的40%,字体大小默认<div class="s2">字体大小1.2em</div></div>
</body>
</html>

rem布局开启JavaScript,获得更好的体验宽度为屏幕宽度的50%,字体大小1.2em字体大小1.2.em宽度为屏幕宽度的40%,字体大小默认字体大小1.2em
css代码如下

html {font-size: 32px; /* 320/10 */
}
body {font-size: 16px; /* 修正字体大小 *//* 防止页面过宽 */margin: auto;padding: 0;width: 10rem;/* 防止页面过宽 */outline: 1px dashed green;
}/* js被禁止的回退方案 */
@media screen and (min-width: 320px) {html {font-size: 32px}body {font-size: 16px;}
}
@media screen and (min-width: 481px) and (max-width:640px) {html {font-size: 48px}body {font-size: 18px;}
}
@media screen and (min-width: 641px) {html {font-size: 64px}body {font-size: 20px;}
}noscript {display: block;border: 1px solid #d6e9c6;padding: 3px 5px;background: #dff0d8;color: #3c763d;
}
/* js被禁止的回退方案 */.p1, .p2 {border: 1px solid red;margin: 10px 0;
}.p1 {width: 5rem;height: 5rem;font-size: 1.2em; /* 字体使用em */
}.s1 {font-size: 1.2em; /* 字体使用em */
}.p2 {width: 4rem;height: 4rem;
}
.s2 {font-size: 1.2em /* 字体使用em */
}

js代码如下

var documentElement = document.documentElement;function callback() {var clientWidth = documentElement.clientWidth;// 屏幕宽度大于780,不在放大clientWidth = clientWidth < 780 ? clientWidth : 780;documentElement.style.fontSize = clientWidth / 10 + 'px';
}document.addEventListener('DOMContentLoaded', callback);
window.addEventListener('orientationchange' in window ? 'orientationchange' : 'resize', callback);

页面效果如下,完整的例子在这里

 

相关资料
使用CSS3 REM 和 VW 打造等比例响应式页面的便捷工作流
从网易与淘宝的font-size思考前端设计稿与工作流**
移动web适配之rem**
使用 rem 提供一致的字体大小
原文网址:zhuanlan.zhihu.com/p/30413803

 

 


http://chatgpt.dhexx.cn/article/Qy52dTwU.shtml

相关文章

html5如何利用rem实现自适应布局,使用Rem布局实现自适应

之前写过一篇移动端适配的文章,很长,内容太多,看得容易凌乱,重新写个通熟易懂版的。 为什么要自适应? 比如,对于一个移动端页面,设计师给的视觉稿画布宽 750,视觉稿中的一个黄色区块的尺寸是 702 x 300,并在画板中居中。我们希望在任何一个设备中的呈现比例都与视觉稿…

Rem布局

Rem布局?什么东西???Rem布局又称等比缩放布局,是移动端布局中常用的一种布局方式。Rem布局可以通过两种方式实现,一种通过JavaScript实现;还有一种通过vw实现。在这里小编主要讲述第二种方式。 下面小编先简单的说一下rem布局的优缺点: 优点:在不同的设备下看起来比较…

(精中求精) rem适配布局

1.适配导读&#xff1a; 什么是适配布局&#xff1f;与flex或者流式布局又有什么区别&#xff1f; 所谓的适配布局&#xff0c;是让页面盒子的高度&#xff0c;宽度&#xff0c;内外边距&#xff0c;边框大小&#xff0c;文字的大小&#xff0c;定位的元素位置等能够根据屏幕…

移动端布局(三) rem布局及原理

什么是rem 首先来了解一下什么是em: 作为font-size的单位时,其代表父元素的字体大小,em作为其他属性单位时,代表自身字体大小。 s1、s2、s5、s6的font-size和line-height分别是多少px? <div class"p1"><div class"s1">1</div><di…

安装Mysql

设置密码 检测安装是否成功 切换到安装目录的bin下C:\Program Files\MySQL\MySQL Server 8.0\bin&#xff0c;按住shift&#xff0c;单击鼠标右键&#xff0c;点选在此处代开命令窗口 在命令行中输入mysql -u root -p,之后输入之前设定的密码如果出现如下图所示&#xff0c;…

ODBC + WIN32 API 访问MYSQL 数据库实现简单QQ用户注册和登录

//在IT行业&#xff0c;不懂数据库是不行的&#xff0c;我自己在学校里还没有学过数据库有关的知识&#xff0c;不过由于前些日子写项目的要求&#xff0c;不得不去琢磨&#xff0c;虽然有很多数据库类别&#xff0c;包括微软的 SQL server &#xff0c;access,ORACLE公司的ORA…

QQ交谈、QQ在线状态代码生成…

原文地址&#xff1a;QQ交谈、QQ在线状态代码生成&#xff0c;非QQ商家可以正常生成 作者&#xff1a;HHeOnline 非QQ商家用户&#xff0c;直接在QQ互联可以生成QQ在线状态&#xff0c;也就是QQ交谈的代码。 直接放到对应的代码里就可以正常使用了。 QQ代码生成地址&#xff1a…

qq群关系数据库 mysql_QQ群关系数据库24.52G mdf源文件下载 附上使用教程

HQY 腾讯 7000W QQ群关系数据库泄漏共24.52G。 QQ24.5gb腾讯QQ群关系数据库,不包含密码。只包含个人名字(群备注名字等信息)。 如果想在线查询更多qq群数据信息可以查看: 一、下载完24.5gQQ数据库后,解压文件 下载后不要把文件改名,打开7z,点击其中一个文件,选择合并文件…

MySQL 数据类型

数值类型 MySQL支持所有标准SQL数值数据类型。 这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC)&#xff0c;以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。 关键字INT是INTEGER的同义词&#xff0c;关键字DEC是DECIMAL的同义词。 BIT数据类型保存…

mysql数据库的基本管理

一、数据库的介绍 1.数据库就是个高级的表格软件 2.常见数据库 Mysql Oracle mongodb db2 sqlite sqlserver .......3.Mysql (SUN -----> Oracle)4.mariadb 是数据库服务器 数据库中的常用名词 字段 :表格中的表头 表 :表格 库 :存放表格的目录…

mysql数据库

文章目录 一、Windows1.1 修改mysql的data文件夹存放位置&#xff1a;1.2 修改mysql密码1.3 设置Mysql允许其他电脑访问1.4 重新手动安装 二、mysql 时间查询三.解锁四.Linux4.1 下载安装4.2 配置4.3 卸载 三、Bug 一、Windows 1.1 修改mysql的data文件夹存放位置&#xff1a;…

MySQL使用与练习01

MySQL数据库概述 用来存储数据和管理数据,最终形成类似于表格的样子,有行有列(字段) 分类: 关系型数据库 和 非关系型数据库 关系型数据库&#xff0c; Oracle、MySQL、SQLServer、Access非关系型数据库&#xff0c; MongoDB、Redis、Solr、ElasticSearch、Hive、HBase 数据…

MySQL项目3总结创建与维护

登录MySQL mysql -u root -p密码 查看所有数据库 show databases; 创建数据库 CREATE DATABASE 数据库名; 修改数据库默认字符集 alter database 数据库名default character set 新字符集; 查看hao数据库创建信息&#xff1b; show create database 表名\g; 删除数据库 …

关于mysql的表情包_mysql表情包 - mysql微信表情包 - mysqlQQ表情包 - 发表情 fabiaoqing.com...

MySQ从删库到跑路_删库_MySQ表情 TFBOYS 三人击掌 - TFBOYS 三人有着独特的击掌方式_tfboys_明星表情_tfboys_明星表情表情 走,带你试衣服去(UNIQLO)_uniqlo_衣服表情 内裤不试完,谁都别想走!(UNIQLO)_不试_uniqlo_内裤表情 qqloveddme_qqloveddme表情 QQLOVE DDME(qq爱)_qq…

二叉树的最大深度

题目 思路 二叉树大多用递归来实现&#xff0c;本题如果知道左子树的深度和右子树的深度&#xff0c;那么整个二叉树的深度就为max&#xff08;左子树&#xff0c;右子树&#xff09; 1&#xff1b;该方法也叫做深度优先搜索 代码 package hot_100;public class MaxDepth {…

c语言二叉树结点 深度,求二叉树的深度、总结点数和叶子结点数

二叉树的二叉链表的存储结构: typedef char TElemType; typedef struct BiTNode {TElemType data;//数据元素 BiTNode * lchild;//指向左孩子 BiTNode * rchild;//指向右孩子 }BiTNode,* BiTree; 一、二叉树的深度 如果二叉树为空,结点的深度为0; 如果二叉树只…

二叉树的深度和高度

二叉树的深度和高度的定义是不一样的&#xff0c;并且是相反的。深度是从上往下数的&#xff0c;高度是从下往上数的&#xff0c;即深度是从根节点到该节点的距离&#xff0c;高度是该节点到叶子节点的距离。当然树的高度和深度是相等的。 根节点的深度和高度为0&#xff0c;所…

求二叉树的深度

题目 写一个算法求一棵二叉树的深度&#xff0c;二叉树以二叉链表为存储结构 求二叉树深度的函数 //求二叉树深度 int getDepth(BTNode *T) {int LD,RD;//左右子树的深度if(TNULL){return 0;//设定空树的深度为0}else{//采用后根遍历LDgetDepth(T->lchild);//求左子树的深度…

二叉树的深度遍历

一、深度优先遍历 对于一棵二叉树&#xff0c;深度优先搜索&#xff08;Depth First Search&#xff09;是沿着树的深度遍历树的节点&#xff0c;尽可能深的搜索树的分支。 二、二叉树的深度遍历的三种方法 这三种方法常被用于访问树的节点&#xff0c;它们之间的不同在于访问每…

正则匹配中文数字

正则匹配中文数字 运营导入小说时遇到小麻烦&#xff0c;想要在章节目录前面加一些符号&#xff0c;word等工具搜半天没搜到&#xff0c;就想着用正则匹配试一下&#xff0c; 于是用notepad试了一下&#xff0c;正则匹配中文数字章节。 表达式为&#xff1a;(第[\u4e00-\u9f…