目录
一、自适应和响应式
二、为什么要做移动端适配?
三、当前流行的几种适配方案
(1) 方案一:百分比设置(不推荐)
(2) 方案二:rem + 动态设置 font-size
px 与 rem 的单位换算
手动换算
less/scss函数
webpack工具 - postcss-pxtorem
VSCode插件 - px to rem & rpx & vw
实现方案一:媒体查询
实现方案二:编写 js 代码
实现方案三:lib-flexible 库
(3) 方案三:vw / vh - (viewport width)适配方案
px 与 vw 的单位转换
手动换算
less/scss 函数
webpack工具 - postcss-px-to-viewport-8-plugin
vs Code 插件 - px to rem & rpx & vw
(3) 方案四:Flex布局
一、自适应和响应式
- 自适应:根据不同的设备屏幕大小来自动调整尺寸、大小。
自适应布局是一种根据不同的设备屏幕分辨率进行布局的方式,它为不同的屏幕分辨率定义了不同的布局,即创建多个静态布局,每个静态布局对应一个屏幕分辨率范围。当屏幕分辨率发生变化时,页面中元素的位置会变化而大小不会变,从而保持在不同渲染设备下浏览效果的最优化,给用户一致的浏览体验。然而,自适应布局的劣势在于,为了适应不同的设备,同一个页面往往需要开发不同页面,会增加成本,尤其当页面需求发生变化时,会涉及多套代码的改动。
自适应布局的实现通常通过使用媒体查询(Media Queries)技术,根据屏幕宽度等条件应用不同的CSS样式规则。例如,可以通过设置不同的背景颜色来区分屏幕宽度,实现自适应布局的应用方式案例。此外,自适应布局的特点还包括使用百分比、auto等尺寸值,以便元素尺寸能够相对父对象或自动计算,从而实现与浏览器尺寸的关联,达到自适应的效果。
综上所述,自适应布局是一种根据设备屏幕分辨率调整页面布局的技术,通过定义多个静态布局来适应不同的屏幕分辨率范围,同时利用媒体查询和适当的尺寸值来实现布局的自适应性。
- 响应式:会随着屏幕的实时变动而自动调整,是一种更强的自适应。
响应式布局也会用到媒体查询,自适应布局是在不同的屏幕下看到的页面布局是一样的,如果屏幕太小的话,即使对小屏幕进行适配,会发现页面还是过于拥挤,而响应式正式为了解决这个问题,它可以识别屏幕大小,还是根据屏幕大小调整页面的布局。
参考:一文了解,前端网页布局常用的几种方式_前端布局的几种方式-CSDN博客
参考:最全的前端项目中自适应布局和响应式布局解决方案-CSDN博客
二、为什么要做移动端适配?
目前市面上移动端屏幕尺寸非常的繁多,很多时候我们希望一个元素在不同的屏幕上显示不同的大小以此来更好的还原效果图:
- 当我们针对一个手机进行布局设计时,设置了一个 200 * 200 大小的盒子
- 但在不同的设备上,由于逻辑像素不同的问题,会使得这个盒子在更大的视口上显得很小,在更小的视口上显示很大
- 因此,我们需要进行适配让它在不同设备上所占据视口的空间比例是相同的
三、当前流行的几种适配方案
-
方案一:百分比设置(不推荐)
- 因为不同属性的百分比值,相对的可能是不同参照物,所以百分比往往很难统一
- 所以,百分比在移动端适配中使用是非常少的
-
方案二:rem单位+动态html的font-size
-
方案三:vw单位(推荐)
-
方案四:flex的弹性布局
(1) 方案一:百分比设置(不推荐)
百分比布局, 也叫流式布局,这是一种比较老的解决方案,现在基本上都是作为辅助在使用。通过使用百分比来定义元素的宽度,可以实现元素的宽度自适应,而高度固定的效果,适用于需要宽度自适应的场景。
使用百分比布局实现移动端的自适应布局,可以让页面元素随设备屏幕的大小自动适应缩放,从而实现不同设备的自适应。下面是具体的实现步骤:
① 在CSS中,使用百分比作为元素的宽高、边距等属性值。
例如,如果设计稿中某个元素的宽度为375px,那么在样式中应该设置其宽度为100%(相对于父元素),再设置padding、margin等。
.example {
width: 100%; /* 相对于父元素 */
padding: 10% 5%; /* 相对于元素宽度 */
margin: 5% auto; /* 相对于元素宽度 */
box-sizing: border-box; /* 让padding不影响元素实际宽度 */
}
② 在HTML中,设置viewport的宽度为设备宽度,并设置initial-scale为1,表示不缩放。这样,元素的宽度就会根据设备宽度自动缩放。
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
③ 在响应式设计中,可以使用媒体查询来针对不同的设备尺寸设置不同的样式。例如,当设备宽度小于等于768px时,设置某个元素的宽度为80%。
@media (max-width: 768px) {
.example {
width: 80%; /* 相对于父元素 */
}
}
通过以上步骤,就可以使用百分比布局实现移动端的自适应布局了。不同设备的屏幕大小,页面元素都会自动缩放,保证在任何设备上都能有良好的显示效果。同时,可以通过媒体查询针对不同设备尺寸设置不同的样式,进一步优化移动端的显示效果。
(2) 方案二:rem + 动态设置 font-size
rem是目前多数企业在用的解决方案,屏幕宽度不同,网页元素尺寸不同(等比缩放)效果。
rem 单位是相对于 html 元素的 font-size 来设置的,通过在不同屏幕尺寸下,动态的修改 html 元素的 font-size 以此来达到适配效果。
在开发中,我们只需要考虑两个问题:
- 针对不同的屏幕,设置 html 不同的 font-size
- 将原来设置的尺寸,转化成 rem 单位
font-size 的尺寸
屏幕尺寸 | html的font-size | 盒子的设置宽度 | 盒子的最终宽度 |
---|---|---|---|
375px | 37.5px | 1rem | 37.5px |
320px | 32px | 1rem | 32px |
414px | 41.4px | 1rem | 41.4px |
px 与 rem 的单位换算
手动换算
- 根元素 html 的文字大小 = 视口宽度/分成的份数(一般为10份,方便计算)
- rem 值 = 元素的 px 值 / 根元素 html 的文字大小
- 比如有一个在375px屏幕上,100px宽度和高度的盒子
- 我们需要将100px转成对应的rem值
- 100/37.5=2.6667,其他也是相同的方法计算即可
目前rem布局方案中,将网页等分成10份, HTML标签的字号为视口宽度的 1/10
查看设计稿宽度 → 确定参考设备宽度(视口宽度) → 确定基准根字号(1/10视口宽度)
以设计稿为375px为例,1rem = 1html字号大小(基准根字号)=37.5px
手机屏幕大小不同, 如何设置不同的HTML标签字号:例如,使用媒体查询能够检测视口的宽度,然后编写差异化的 CSS 样式。
rem单位小结:rem单位是一种相对单位,相对于HTML标签的字号计算结果,1rem等于HTML标签的字号大小。这种布局方案中,将网页等分成若干份,HTML标签的字号设置为视口宽度的某一比例,如以设计稿宽度为例,1rem等于视口宽度的1/10。通过使用媒体查询检测视口的宽度,可以编写差异化的CSS样式,实现不同屏幕尺寸下的适配。
less/scss函数
.pxToRem(@px) {
result: 1rem * (@px / 37.5);
}
.box {
width: .pxToRem(100)[result];
height: .pxToRem(100)[result];
background-color: orange;
}
p {
font-size: .pxToRem(14)[result];
}
webpack工具 - postcss-pxtorem
- 目前在前端的工程化开发中,我们可以借助于webpack的工具来完成自动的转化
npm install postcss-pxtorem
-
VSCode插件 - px to rem & rpx & vw
一个 px
与 rem
单位互转的 VSCode 插件,且支持WXSS微信小程序。
特性
-
支持智能感知
-
px
->rem
(快捷键:Alt + z
) -
rem
->px
(快捷键:Alt + z
) -
px
->vw
(快捷键:Alt + v, Alt + w
) -
vw
->px
(快捷键:Alt + v, Alt + w
) -
px
->rpx
(微信小程序, 快捷键:Alt + r
) -
rpx
->px
(微信小程序, 快捷键:Alt + r
)
-
-
支持鼠标悬停显示转化过程
-
支持直接打上标记
-
支持选中区域
可以利用VSCODE的Keyboard shortcuts重新定义快捷键。
如何使用
-
在文件内自动转换,例如录入
12px
智能提醒对应转化后rem
值 -
光标至
14px
上,按下Alt + z
对应转化rem
-
通过
F1
面板查找:cssrem
支持语言
html vue css less scss sass stylus tpl(php smarty3) tsx jsx
配置
根目录的 .cssrem
文件优先级最高,其格式如下:
{
"rootFontSize": 18,
"fixedDigits": 3
}
其次,也可以配置全局,点击 VS Code 的 文件 > 首选项 > 设置
,打开设置面板:
名称 | 描述 | 默认值 |
---|---|---|
cssrem.rootFontSize | 基准font-size(单位:px ) | 16 |
cssrem.fixedDigits | 保留小数点最大长度 | 4 |
cssrem.autoRemovePrefixZero | 自动移除0开头的前缀 | true |
cssrem.ingoresViaCommand | 当使用命令行批量转换时,允许忽略部分 px 值不转换成 rem (单位:string[] ),例如:[ "1px", "0.5px" ] | [] |
cssrem.addMark | 是否启用加上标记 | false |
cssrem.hover | 是否启用悬停时显示转换数据, disabled : Disabled, always Anything, onlyMark : Only valid when cssrem.addMark is true | onlyMark |
cssrem.currentLine | 是否当前行尾显示标记,disabled : Disabled, show Show | show |
cssrem.ingores | 忽略文件清单,例如:[ 'demo.less', 'src' ] | string[] |
cssrem.languages | 支持语言清单 [ 'html', 'vue', 'css', 'postcss', 'less', 'scss', 'sass', 'stylus', 'tpl', 'wxss', 'twig', 'javascriptreact', 'typescriptreact', 'javascript', 'typescript' ] ,默认全部包含 | string[] |
cssrem.remHover | 是否启用 rem 悬停 | true |
cssrem.vw | 是否启用vw支持 | false |
cssrem.vwHover | 是否启用 vw 悬停 | true |
cssrem.vwDesign | 规定设计稿宽度(一般等同于浏览器视口宽度) | 750 |
cssrem.wxss | WXSS小程序样式 是否启用WXSS支持 | false |
cssrem.wxssScreenWidth | WXSS小程序样式 规定屏幕宽度,默认 750 ,尺寸单位 | 750 |
cssrem.wxssDeviceWidth | WXSS小程序样式 设备分辨率宽度,官方推荐使用 iPhone6 作为视觉稿的标准 | 375 |
VSCode插件 - cssrem插件信息截图如下:
实现方案一:媒体查询
参考:https://blog.csdn.net/sunyctf/article/details/142652838
思路:通过媒体查询来设置不同尺寸屏幕下 html 的 font-size
缺点:
- 需要针对不同的屏幕编写大量的媒体查询
- 如果动态改变尺寸,不会实时更新,只是一个个区间
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>rem适配</title>
<style>
/* 1. 不同的视口, HTML标签字号不同, 字号是视口宽度的1/10 */
@media screen and (min-width: 320px) {
html {
font-size: 20px;
}
}
@media screen and (min-width:375px) {
html {
font-size: 24px;
}
}
@media screen and (min-width: 414px) {
html {
font-size: 28px;
}
}
@media screen and (min-width: 480px) {
html {
font-size: 32px;
}
}
/* 2. 书写盒子尺寸, 单位rem */
.box {
width: 5rem;
height: 5rem;
background-color: blue;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</head>
</html>
番外:在HTML中,设置viewport的宽度为设备宽度,并设置initial-scale为1,表示不缩放。这样,页面元素的宽度就会根据设备宽度自动缩放。
实现方案二:编写 js 代码
思路:通过监听屏幕尺寸的变化来动态修改 html 元素的 font-size 大小
方法:
- 根据 html 的宽度计算出 font-size 的大小,并设置到 html 上
- 监听页面尺寸的变化,实时修改 font-size 大小
function setRemUnit() {
// 获取所有的 html 元素
const htmlEl = document.documentElement
// 375 -> 16px
// 320px -> 12px
// 我们需要动态更改字体大小,因此需要获取网页的宽度
// 拿到客户端宽度
const htmlWidth = htmlEl.clientWidth
// 将宽度分成10份
const htmlFontSize = htmlWidth / 10
console.log('htmlFontSize', htmlFontSize);
// 将值给到html的font-size
htmlEl.style.fontSize = htmlFontSize + 'px'
}
setRemUnit()
// 给 window 添加监听事件
window.addEventListener('resize', setRemUnit)
实现方案三:lib-flexible 库
lib-flexible 是淘宝团队出品的一个移动端自适应解决方案,通过动态计算 viewport 设置 font-size 实现不同屏幕宽度下的 UI 自适应缩放。
(function flexible (window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
手机设备多,屏幕尺寸不一,视口不仅仅有几个,不可能每次都定义媒体查询。此时可以使用flexible.js,这是手机淘宝团队开发出的一个用来适配移动端的js框架,核心原理就是根据不同的视口宽度给网页中html根节点设置不同的font-size值。
他帮我们把媒体查询写好了 并且给html 设置font-size ,帮我们把屏幕划分成 10份 然后他把每一份的大小给 html的font-size 设置好了 。
使用方法:在代码中引入flexible.js文件即可
(3) 方案三:vw / vh - (viewport width)适配方案
● vw / vh 是相对单位,vw就是视口的宽度 vh就是视口的高度
vw 、 vh 和 百分比的特点(了解):
- vw 永远是以视口的宽度/高度为准。如,在 375px设计稿下, 1vw 永远是 3.75px
- vh 永远是以视口的高度为准。如,在 667px设计稿下, 1vh 永远是 6.67px
- 百分比以父盒子为准。 假如父盒子是 200px,则 1% 是 2px
vw:viewport width 1vw = 1/100的视口宽度
1vw=当前屏幕宽度的1/100,即1%。如果正常稿屏幕宽度为375px,则1vw = 375px*1% = 3.75px
vh:viewport height 1vh = 1/100的视口高度
1vh=当前屏幕高度的1/100,即1%,如果正常稿屏幕的高度是667px ,则1vh = 667px*1%= 6.67px
① vw 单位尺寸
- 确定设计稿对应的vw尺寸 (1/100视口宽度)
查看设计稿宽度 → 确定参考设备宽度 (视口宽度) → 确定vw尺寸 (1/100 视口宽度)
- vw单位的尺寸 = px单位数值 * ( 1/100 视口宽度 )
100vw 相当于整个视口的宽度 innerWidth,1vw 相当于视口宽度的 1%,将 px 转换为 vw 即可完成适配,其实上面的 rem 就是模仿 vw 方案。
例如:设计图 375px 100vw=375px 1vw=3.75px
如果测量的盒子大小是75px 那么就是75/3.75 =20vw
box { width: 75px;height: 75px; }==>转化写法就是 box { width: 20vw;height: 20vw; }
② vh 单位尺寸
- 确定设计稿对应的vh尺寸(1/100视口高度)
查看设计稿宽度 → 确定参考设备高度 (视口高度) → 确定vh尺寸 (1/100 视口高度)
- vh单位的尺寸 = px单位数值 * ( 1/100 视口高度 )
● 问:开发中,vw和vh是否能一起混用?
当然是不可以的。vw和vh不能混用,如果混用会导致盒子变形,所以,我们要么统一使用vw,要么统一使用vh。但是高度比宽度要大,所以,建议使用vw。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 在HTML中,设置viewport的宽度为设备宽度,并设置initial-scale为1,表示不缩放。这样,元素的宽度就会根据设备宽度自动缩放 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box1 {
width: 10vw;
height: 10vw;
background-color: #ccc;
margin: 5vw auto;
}
.box2 {
width: 10vh;
height: 10vh;
background-color: pink;
margin: 5vh auto;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>
vw适配效果,如下:
vh适配效果,如下:
番外:在HTML中,设置viewport的宽度为设备宽度,并设置initial-scale为1,表示不缩放。这样,元素的宽度就会根据设备宽度自动缩放。
小结:vw和vh不能混用的原因是会导致盒子变形。
vw和vh是CSS中的视窗单位,分别代表视口的宽度和高度。由于vw和vh分别基于视口的宽度和高度,如果混用,当视口尺寸变化时,盒子的宽高比会发生变化,从而导致盒子变形。
具体来说,vw和vh单位是相对于视口大小的,这意味着它们会随着视口大小的改变而改变。如果同时使用vw和vh来设置盒子的宽度和高度,当视口尺寸变化时,盒子的宽高比会发生变化,可能导致盒子的形状扭曲。因此,为了保证布局的稳定性和一致性,建议要么统一使用vw,要么统一使用vh。
此外,混用vw和vh还可能导致兼容性问题。虽然现代浏览器普遍支持vw和vh单位,但在一些旧版本的浏览器中可能不支持或支持不完全,这会增加开发和维护的难度。因此,为了避免这些问题,推荐在设置盒子的宽度和高度时保持一致性,使用单一的vw或vh单位。
vw相比于rem的优势:
- 不需要去计算 html 的 font-size 大小,也不需要去给 html 设置 font-size
- 不会因为设置 html 的 font-size 大小,而必须再给 body 设置一个 font-size 防止继承
- 因为不依赖 font-size 的尺寸,所以不用担心某些原因的 html 的 font-size 尺寸被篡改,导致页面尺寸混乱
- vw 更加语义话,1vw 相当于 1/100 viewport 的大小
- rem 事实上作为一种过渡的方案,它利用的也是 vw 的思想
rem目前市场比较常见: 1. 需要不断修改html文字大小。 2. 需要媒体查询media。3. 需要 flexible.js
vw / vh是将来(马上)趋势 :省去各种判断和修改,目前大厂都在趋向使用。
px 与 vw 的单位转换
手动换算
示例:以普通稿375px*667px为例
公式:vw=测量宽度 / 标准稿(375 * 1% = 3.75px) ;vh=测量宽度 / 标准稿(667 * 1% = 6.67px)
示例:若需要转换的测量宽width,高hight都为100px。则转换过后的vw值=(100 / 3.75); vh值=(100 / 6.67);
less/scss 函数
@vwUnit: 3.75;
.pxToVw(@px) {
result: (@px / @vw) * 1vw
}
.box {
width: .pxToVw(100)[result];
height: .pxToVw(100)[result];
}
webpack工具 - postcss-px-to-viewport-8-plugin
- 和rem一样,在前端的工程化开发中,我们可以借助于webpack的工具来完成自动的转化
npm install postcss-px-to-viewport-8-plugin
vs Code 插件 - px to rem & rpx & vw
px to vw 插件,在编写时自动转化:
(3) 方案四:Flex布局
Flex布局 / 弹性布局:是一种浏览器提倡的布局模型 ,布局网页更简单、灵活 ,避免浮动脱标的问题,目前比较流行的一种方式。
基于 Flex 精确灵活控制块级盒子的布局方式,Flex布局非常适合结构化布局。
使用:父元素添加 display: flex;子元素可以自动的挤压或拉伸。
Flex布局是一种更现代且灵活的布局方式,它允许更精确地控制块级盒子的布局,避免了浮动脱标的问题。Flex布局非常适合结构化布局,通过设置 display: flex 在父元素上,子元素可以自动地挤压或拉伸,实现元素的灵活排列和对齐。
主轴的对齐方式:
修改主轴对齐方式属性: justify-content:属性值
侧轴的对齐方式: 使用align-items调节元素在侧轴的对齐方式
改变主轴(X轴)对齐的方向,变成侧轴(Y轴)方向:
主轴默认是水平方向,侧轴默认是垂直方向,可以使用flex-direction属性改变元素排列方向
弹性盒子换行:使用flex-wrap: wrap; 实现弹性盒子多行排列效果
调整换行后的对齐方式 :使用align-content 属性,属性值和justify-content的一样。
参考:CSS align-content 属性
align-content 定义和用法
align-content 属性在弹性容器内的各项没有占用交叉轴上所有可用的空间时对齐容器内的各项(垂直)。
提示:使用 justify-content 属性对齐主轴上的各项(水平)。
注意:容器内必须有多行的项目,该属性才能渲染出效果。
👋🏻 align-content和align-item的区别
align-content 适用于多行,align-item 则是适用于单行。
align-content(单行无效)可以设置上对齐、下对齐、居中、拉伸、平分剩余空间;align-item上对齐、下对齐、居中、拉伸。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.demo {
display: flex;
flex-wrap: wrap;
width: 500px;
height: 500px;
background-color: aqua;
justify-content: space-around;
align-content: space-between;
}
.demo span {
width: 200px;
height: 100px;
background-color: brown;
margin: 15px;
}
</style>
</head>
<body>
<div class="demo">
<span>1</span><span>2</span><span>3</span> <span>4</span><span>5</span><span>6</span>
</div>
</body>
</html>
显示结果,如下图:
总结:移动端适配方案主要包括百分比布局、Flex布局、rem单位、vw/vh等几种解决方案。
此外,移动端适配还需要考虑不同屏幕大小、像素密度等因素。对齐模式和尺寸适应是移动端适配的两个关键要素,其中对齐模式涉及元素与父级图层的对齐关系,而尺寸适应则是元素对上级或下级元素尺寸变化的响应逻辑。像素密度也是一个重要的考虑因素,不同设备的像素密度差异很大,需要在设计和开发过程中加以考虑,以确保跨设备的良好用户体验。
参考资料
—— Vue移动端项目适配方案总结 _烤地瓜的CSDN博客 —— | 移动端适配如何处理
移动端的适配该如何实现_CSDN博客 | 【面试】移动端自适应布局如何实现-CSDN博客
—— H5实现移动端自适应的几种方法 | 一文了解,前端网页布局常用的几种方式 ——
VW、VH适配移动端的解决方案与常见问题 _ 脚本之家
最全的前端项目中自适应布局和响应式布局解决方案-CSDN博客