自适应

开发移动端网页时,为了适配分辨率不同的机型,需要让网页根据设备自适应布局,所以得设置meta标签:

1
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

如果不设置width=device-width,设备会按默认的视口宽度(通常是较宽的桌面屏幕)渲染网页,导致网页内容在移动设备上显示不良,出现内容被截断或水平滚动的情况

圣杯布局

圣杯布局是一种两边盒子宽度固定,中间盒子自适应的三栏布局,其中,中间栏放在文档流前面,保证先行渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<template>
<div>
<header class="header">
<div>left</div>
<div>center</div>
<div>right</div>
</header>
</div>
</template>

<style lang='less'>
.header {
display: flex;
div {
height: 50px;
line-height: 50px;
color: white;
text-align: center;
}
// 两边固定、中间铺满
div:nth-child(1) {
width: 100px;
background-color: pink;
}
div:nth-child(2) {
flex: 1;
background-color: greenyellow;
}
div:nth-child(3) {
width: 100px;
background-color: cyan;
}
}
</style>

对于小手机而言,这个布局的效果太怪了

相对长度单位

px是固定的绝对长度单位,就像厘米cm一样,不会因为设备屏幕的不同而变化(无法进行自适应)

rem是可变的相对长度单位,根据html的font-size进行缩放,因此可以进行自适应,但需要计算每个屏幕大小所适合的font-size,才能确定布局是否合适

若需计算,可以使用flexible.js库

vw和vh也是相对长度单位,是相对viewport视口的单位,配合meta标签可以直接使用,无需计算:1vw=$1 \over 100$视口宽度;1vh=$1 \over 100$视口高度

百分比%相对于父元素,而vw和vh一定相对于视口

但开发时,根据设计图的px换算vw很麻烦,最好是能自动转换单位,可以用PostCSS编写一个px转vw/vh的插件

PostCSS插件

Vite已经内置了PostCSS,如果没有就自行安装

tsconfig.node.json配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
// 是否允许隐式any
"noImplicitAny": false,
"lib": ["ES2015", "DOM"]
},
"include": ["vite.config.ts", "plugins/**/*"]
}

新建plugins文件夹,编写/plugins/postcss-px-to-vw.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 编写postcss插件
import { Options } from 'element-plus'
import { Plugin } from 'postcss'

interface Options {
viewportWidth?: number
}

// (宽度)默认375,要设置成UI设计稿的宽度
const Options: Options = {
viewportWidth: 375
}

// 需要导出一个函数
export const PostCssPxToVW = (options: Options = Options): Plugin => {
// 组合配置项
const opt = Object.assign({}, Options, options)
// 要求返回一个对象
return {
// 插件名
postcssPlugin: 'postcss-px-to-viewport',
// 获取所有css节点的钩子
// node参数记录了节点的信息
Declaration(node) {
// 筛选px单位的属性值
if(node.value.includes('px')) {
// 一般设计稿都会给出像素值,所以需要px转vw
// 将带px的属性值转为数字(需要考虑小数)
const num = parseFloat(node.value)
// 将px转换为vw并赋值
node.value = `${((num/opt.viewportWidth)*100).toFixed(2)}vw`
console.log(node.prop, node.value)
}
// 也可以自定义一个单位,通过某种运算使其和其他单位具有对照
// 例如,px转vw,但不需要转的时候就写单位px,需要转就写单位yjsp
// if(node.value.includes('yjsp')) {}
}
}
}

在vite.config.js引入postcss插件:

1
2
3
4
5
6
plugins: [...],
css: {
postcss: {
plugins: [PostCssPxToVW()]
}
}

这样一来效果就好多了,布局在各种尺寸都会呈现差不多的效果:

全局样式切换

其实就是所谓的“主题”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<template>
<div>
<header class="header">
<div>left</div>
<div>center</div>
<div>right</div>
</header>
<!-- 一堆用于切换样式的按钮 -->
<div>
<button @click="change(36)">大</button>
<button @click="change(24)">中</button>
<button @click="change(14)">小</button>
</div>
</div>
</template>

<script setup lang='ts'>
// import { useCssVar } from '@vueuse/core'

const change = (num: number)=> {
// 1.可以使用VueUse库,具有切换css变量的方法
// const size = useCssVar('--size')
// size.value = num + 'px'

// 2.或者不用库,使用原生方法
console.log(document.documentElement.style.getPropertyValue('--size'))
document.documentElement.style.setProperty('--size', num + 'px')

// 如果需要记忆用户的样式设定,可以使用localstorage存储
// 用户进入/刷新时,若storage存有样式设定,则更换样式;否则使用默认样式
}

</script>

<style lang='less'>
// 在:root中定义css变量,作用于全局(挂载于html标签)
// 想要动态切换全局字体大小,使用css变量即可
// 只要这个变量的值改变,全局相关的样式都会改变
:root {
--size: 14px
}
.header {
display: flex;
div {
height: 50px;
line-height: 50px;
color: black;
text-align: center;
// 记得使用css变量
font-size: var(--size);
}
// ......省略
}
</style>

当点击任意按钮时,文字的大小就会随之变化

本站的自适应播放器也使用了全局样式切换,打开控制台一探究竟吧(