移动端适配:自适应布局应该怎样实现?

1,557 阅读4分钟

什么是自适应

简单来说,自适应就是保持比例一致
比如在宽度为300的设计稿中,有一行字的字体是10px的,设计师希望的是在400px宽度的手机中同比例放大,看到的字体应该是400➗300✖️10=13.3px

配置一个px-to-viewport的postcss插件,在css中正常写px,最后生成的文件中会被转为vw。

搭建项目

用webpack(4.43)+原生js搭建一个可以实现自适应的demo。

初始化项目

git init
npm init -y

安装webpack必要的loader、plugin

npm install style-loader css-loader postcss-loader postcss-px-to-viewport -D
npm install webpack webpack-cli html-webpack-plugin -D

配置打包命令:

// package.json
  "scripts": {
    "bundle": "webpack"
  },

webpack不推荐全局安装,因为如果和本地安装版本不同可能会导致差异。
这里在script中配置脚本的作用是如果直接在terminal中输入webpck命令只会在全局中寻找webpack-cli执行的脚本,我们没有安装会导致报错command not found: webpack
而在script中配置的命令会在本地寻找cli

PS:如果不配置可以使用npx webpack命令

webpack配置文件

// webpack.config.js
const path = require('path')
const HtmlPlugin = require('html-webpack-plugin')
module.exports = {
  mode: "development",
  entry: {
    entry1: './src/index.js',
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader''css-loader','postcss-loader']
      }
    ]
  },
  plugins: [
    new HtmlPlugin({
      template: './src/index.html'
    })
  ]
}

postcss配置文件

module.exports = {
  plugins: [
    require('postcss-px-to-viewport')({
      viewportWidth: 375, // (Number) The width of the viewport.
      viewportHeight667// (Number) The height of the viewport.
      unitPrecision3// (Number) The decimal numbers to allow the REM units to grow to.
      viewportUnit'vw'// (String) Expected units.
      selectorBlackList: ['.ignore'], // (Array) The selectors to ignore and leave as px.
      minPixelValue1// (Number) Set the minimum pixel value to replace.
      mediaQuery: false, // (Boolean) Allow px to be converted in media queries.
    }),
  ]
}

这里用到了px转vw的插件,设置自适应的基准
通常来说设计稿是按375的宽度定稿(iphone6)

selectorBlackList会将该类名中的px不转化为vw

模版文件

// index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id='root'></div>
  
<script src="entry1.js"></script></body>
</html>

webpack打包入口

// index.js
import './index.css'
const root = document.getElementById('root')
const div = document.createElement('div')
div.innerHTML = '自适应文字'
div.className = 'custom'
root.append(div)
const span = document.createElement('span')
span.innerHTML = '非自适应文字'
span.className = 'ignore'
root.append(span)
const span2 = document.createElement('span')
span2.innerHTML = '非自适应文字'
span2.style = {'font-size':'10px'}
root.append(span2)

css文件

.custom{
  font-size16px;
}
.ignore {
  font-size16px
}

custom中的px会被转化,ignore中不转变

执行npm run bundle,查看打包出来的结果

在iphone6中,文字大小看上去一模一样,但检查元素的样式会发现,一个是用vw表示,一个还是px

换到更大屏,差异就显现出来了,用vw表示的字体和屏幕保持着相同的比例(为33px左右,用0.04267✖️768px),而使用px的字体就会在大屏上看起来很小(其实还是16px)

这个px转vw的插件是postcss-loader中的一个plugin,而loader是在加载css文件时去起作用的,所以写在js中的内联css不会被识别到,依然是px