REM适配方案
1. 前言
设计师交付给前端开发一张宽度为750px的视觉稿,设计稿上元素的尺寸、颜色、位置等已做过标注,要求工程师工在适配不同屏幕尺寸的设备时采用等比缩放的方案。
2. 原理
在使用单位控制页面元素大小时,可以使用固定单位px,也可以使用相对单位rem。2rem 等于html标签font-size的2倍。基于这个原理,对于需要适配屏幕等比缩放的元素可以选用rem作为单位,对于不需要等比缩放的元素依旧使用px作为单位。只要调整html标签的font-size,就能让所有使用rem单位的元素跟随着发生变化,而使用px单位的元素不受影响。问题的关键在于如何根据屏幕尺寸跳转html标签的font-size。
举个实际的例子。设计师交付的设计稿宽度是750px,设计稿上一个div的标注尺寸是375px(宽度是设计稿宽度的一半)。我们可以
设置html的font-size 为 100*屏幕宽度/设计稿宽度
在写CSS时设置 div 的宽度是 3.75rem (计算时用设计稿标注值除以100),边框宽度为1px
假设用户在逻辑像素宽度是375px的设备上打开页面,则html的font-size是100*375/750 = 50px,div的宽度是3.75rem ,即187.5px 正好是屏幕宽度的一半。
假设用户在逻辑像素宽度是428px的设备上打开页面,则html的font-size是100*428/750 = 57.07px,div的宽度是3.75rem ,即214px 正好是屏幕宽度的一半。
为什么要用100来乘以屏幕宽度/设计稿宽度?其实100只是随便选取的一个值,我们也可以随便其他任意值比如50。如果选100,设计稿中某个元素标注的尺寸是375px,我们可以很快速的计算出3.75rem。如果html的font-size 设置为 50*屏幕宽度/设计稿宽度,那么div的宽度就应该是7.5rem了。换算起来就没那么直观了。
3. 适配代码
rem 适配代码只要 script 里面的
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> <script> const WIDTH = 750//如果是尺寸的设计稿在这里修改 const setView = () => { //设置html标签的fontSize document.documentElement.style.fontSize = (100*screen.width/WIDTH) + 'px' } window.onorientationchange = setView setView() </script> <style> div { width: 3.75rem;/* 需要随屏幕等比缩放,使用rem单位,比如设计稿中标注的32px这里写成0.32rem */ border: 1px solid #ccc;/*不需要缩放的部分用px*/ } </style> </head> <body> <div>内容</div> </body> </html>
如果想要在 vue 里引入可以仿照上面的写在 html 页面中,也可以新建一个 js 页面,写入适配代码,在 main.js 中全局引入,也可以局部引入,但是如果页面过多则不推荐局部引入
- 在 vue 中引入代码:
import './rem'
4. 总结
动态Rem方案既能实现页面级整体缩放,又能个性化控制某些元素不缩放。
vw适配方案
1. 原理
vw是相对单位,1vw表示屏幕宽度的1%。基于此,我们可以把所有需要适配屏幕大小等比缩放的元素都使用vw做为单位。不需要缩放的元素使用px做单位。
举个例子。设计师交付的设计稿宽度是750px,设计稿上一个标题的fontSize标注尺寸是32px。(32/750)*100% = 4.27% ,换句话说这个标题的字号占屏幕宽度的占比是4.27%,不管任何屏幕都是如此。4.27% 即 4.27vw。
对于任何需要等比缩放的元素,在写CSS设置样式时直接换算成vw即可,尺寸 = 100vw*设计稿标注大小/设计稿宽度。
2. 适配代码
假设设计稿尺寸是750px,页面有一个按钮,按钮文字标注大小28px,按钮高度标注为48px,宽度为120px,边框为1px不缩放。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> .button { width: 16vw;/* 100vw*120/750 */ font-size: 3.73vw;/* 100vw*28/750 */ line-height: 6.4vw;/* 100vw*48/750 */ border: 1px solid #000;/*不需要缩放的部分用px*/ text-align: center; } </style> </head> <body> <div class="button">按钮</div> </body> </html>
在写样式时会发现,虽然不用写JS做适配,但标注尺寸换算为vw又麻烦又不直观。
我们可以在CSS里使用calc来换算换,只不过需要注意新语法的兼容性。
:root { --ratio: calc(100vw/750); } .button { font-size: calc(100vw*28/750);/* 可以直接用calc */ line-height: calc(100vw*48/750); width: calc(120*var(--ratio));/* 也可以用calc配合var使用,IE不支持var */ border: 1px solid #000;/*不需要缩放的部分用px*/ text-align: center; }
在正式的项目里,我们也可以用SCSS,把换算交给预处理器
@function px2vw($px) { @return $px * 100vw / 750; } .button { width: px2vw(120); font-size: px2vw(28); line-height: px2vw(48); border: 1px solid #000; text-align: center; }
3. 适配方案对比
- 动态REM方案
- 适配原理稍复杂
- 需要使用JS
- 设计稿标注的px换算到CSS的rem计算简单
- 方案灵活技能实现整体缩放又能实现局部不缩放
- vw方案
- 适配原理简单
- 不需要JS即可适配
- 设计稿标注的px换算到CSS的vw计算复杂
- 方案灵活技能实现整体缩放又能实现局部不缩放
1px问题
1. 简述
有几种方法能实现0.5px边框:
直接设置 border-width: 0.5px;使用方便,但兼容性很差,不推荐使用。
用阴影代替边框,设置阴影box-shadow: 0 0 0 .5px #000; 使用方便,能正常展示圆角,兼容性一般。
给容器设置伪元素,设置绝对定位,高度为1px,背景图为线性渐变,一半有颜色,一半透明。视觉上宽度只有0.5px。这种方法适合设置一条边框,没法展示圆角。
给容器内设置伪元素,设置绝对定位,宽、高是200%,边框是1px,然后使用transform: scale(0.5) 让伪元素缩小原来的一半,这时候伪元素的边框和容器的边缘重合,视觉上宽度只有0.5px。这种方法兼容性最好,4个边框都能一次性设置,能正常展示圆角,推荐使用。
2. 代码测试
做移动端开发的时候,如果边框直接设置 1px的宽度,可能视觉上还是太粗无法满足设计师的要求。下面是实现0.5px边框的几种方案。推荐方案4,复杂度中等,扩展性良好,兼容性好。
<div class="box box1"> 1px 边框,作为对比 </div> <div class="box box2"> 方案1: 直接设置0.5px边框</div> <div class="box box3"> 方案2: 设置0.5px阴影扩散半径 </div> <div class="box box4"> 方案3: 使用背景渐变实现1px背景的一半</div> <div class="box box5"> 方案4: 伪元素2倍尺寸1px边框scale缩小一半</div> <style> .box { width: 200px; height: 50px; border-radius: 10px; margin-top: 10px; } .box1 { border: 1px solid #000; } .box2 { border: 0.5px solid #000; } .box3 { box-shadow: 0px 0px 0px 0.5px #000; } .box4 { position: relative; } .box4::after { content: ""; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px; background-image: linear-gradient(0deg, #000 50%, transparent 50%); } .box5 { position: relative; } .box5::after { position: absolute; bottom: 0; z-index: -1; width: 200%; height: 200%; content: ""; display: block; border: 1px solid #000; border-radius: 10px; transform: scale(0.5); transform-origin: left bottom; } </style>
总结:
以上就是 HTML 中移动端的适配方案,不懂得也可以在评论区里问我,以后会持续发布一些新的功能,敬请关注。