HTML番外篇(五)-移动端适配

一、媒体查询

1.认识媒体查询

媒体查询是一种提供给开发者针对不同设备需求进行定制化开发的一个接口

你可以根据设备的类型(比如屏幕设备、打印机设备)或者特定的特性(比如屏幕的宽度)来修改你的页面。

媒体查询的使用方式主要有三种:

  • 方式一:通过@media@import使用不同的CSS规则(常用);

  • 方式二:使用media属性为<style><link><source>和其他HTML元素指定特定的媒体类型;

  • 方式三:使用 Window.matchMedia() 和 MediaQueryList.addListener() 方法来测试和监控媒体状态;

比较常用的是通过 @media 来使用不同的CSS规则,目前掌握这个即可;

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>
  <!-- 媒体查询方式二:使用media属性 -->
  <!-- <link rel="stylesheet" media="screen and (max-width: 800px)" href="./css/body_bgc.css"> -->
  <style>
    /* 媒体查询方式一 使用@import */
    /* @import url(./css/body.css) (max-width: 500px); */
  </style>

  <script>
    // 媒体查询方式三:使用matchMedia函数
    var mediaQueryList = window.matchMedia("(max-width: 600px)");
    mediaQueryList.addEventListener("change", function(a, b){
      if (a.matches) {
        document.body.style.backgroundColor = '#ccc';
      } else {
        document.body.style.backgroundColor = 'transparent';
      }
    })

    
  </script>
</head>
<body>
  
</body>
</html>

2.媒体查询 - 媒体类型(Media types)

在使用媒体查询时,你必须指定要使用的媒体类型。

  • 媒体类型是可选的,并且会(隐式地)应用 all 类型。

常见的媒体类型值如下:

  • all:适用于所有设备。
  • print:适用于在打印预览模式下在屏幕上查看的分页材料和文档。
  • screen(掌握):主要用于屏幕。
  • speech:主要用于语音合成器。

被废弃的媒体类型:

  • CSS2.1 和 Media Queries 3 定义了一些额外的媒体类型(tty, tv, projection, handheld, braille, embossed, 以及 aural);
  • 但是他们在Media Queries 4 中已经被废弃,并且不应该被使用;
  • aural类型被替换为具有相似效果的speech。

3.媒体查询 -- 媒体特性(Media features)

媒体特性(Media features)描述了 浏览器输出设备,或是预览环境的具体特征;

  • 通常会将媒体特性描述为一个表达式
  • 每条媒体特性表达式都必须用括号括起来

4.媒体查询 -- 逻辑操作符(logical operators)

媒体查询的表达式最终会获得一个Boolean值,也就是真(true)或者假(false)。

  • 如果结果为真(true),那么就会生效;
  • 如果结果为假(false),那么就不会生效;

如果有多个条件,我们可以通过逻辑操作符联合复杂的媒体查询:

  • and:and 操作符用于将多个媒体查询规则组合成单条媒体查询
  • not:not运算符用于否定媒体查询,如果不满足这个条件则返回true,否则返回false。
  • only:only运算符仅在整个查询匹配时才用于应用样式。
  • , (逗号):逗号用于将多个媒体查询合并为一个规则。

比如下面的媒体查询,表示:屏幕宽度大于500,小于700的时候,body背景颜色为红色;

5.常见的移动端设备

html 复制代码
<!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>
    /* 
      320~375之间 font-size: 15px;
      375~414之间 font-size: 18px;
      414~480之间 font-size: 21px;
      大于480px font-size: 24px
    */
    /* @media (min-width: 320px) and (max-width: 375px) {
      .box { font-size: 15px; }
    }
    @media (min-width: 375px) and (max-width: 414px) {
      .box { font-size: 18px; }
    }
    @media (min-width: 414px) and (max-width: 480px) {
      .box { font-size: 21px; }
    }
    @media (min-width: 480px) {
      .box { font-size: 24px; }
    } */

    /* CSS层叠性 */
    @media (min-width: 320px) {
      .box { font-size: 15px; }
    }
    @media (min-width: 375px) {
      .box { font-size: 18px; }
    }
    @media (min-width: 414px) {
      .box { font-size: 21px; }
    }
    @media (min-width: 480px) {
      .box { font-size: 24px; }
    }

  </style>
</head>
<body>
  
  <div class="box">
    我是box
  </div>

</body>
</html>

二、CSS常见单位详解

1.CSS中的单位

前面编写的CSS中,我们经常会使用px来表示一个长度(大小),比如font-size设置为18px,width设置为100px。

px 是一个长度(length)单位,事实上CSS中还有非常多的长度单位。

整体可以分成两类:

  • 绝对长度单位(Absolute length units);

  • 相对长度单位(Relative length units);

2.CSS中的绝对单位( Absolute length units )

绝对单位:

  • 它们与其他任何东西都没有关系,通常被认为总是相同的大小。
  • 这些值中的大多数在用于打印时比用于屏幕输出时更有用,例如,我们通常不会在屏幕上使用cm。
  • 唯一一个您经常使用的值,就是px (像素)。

3.CSS中的相对单位( Relative length units )

相对长度单位

  • 相对长度单位相对于其他一些东西;
  • 比如父元素的字体大小,或者视图端口的大小;
  • 使用相对单位的好处是,经过一些仔细的规划,您可以使文本或其他元素的大小与页面上的其他内容相对应;

三、深入理解pixel、DPR、PPI

1.pixel是什么

前面我们已经一直在使用px单位了,px是pixel单词的缩写,翻译为像素

那么像素到底是什么呢?

  • 像素是影响显示的基本单位。(比如屏幕上看到的画面、一幅图片);
  • pix是英语单词picture的常用简写,加上英语单词"元素"element,就得到pixel;
  • "像素"表示"画像元素"之意,有时亦被称为pel(picture element);

2.像素的不同分类(一)

100个pixel到底是多少呢?

  • 我们确实可以在屏幕上看到一个大小,但是这个大小代表的真实含义是什么呢?
  • 我们经常说一个电脑的分辨率、手机的分辨率,这个CSS当中的像素又是什么关系呢?

这里我们要深入到不同的像素概念中,来理解CSS中的pixel到底代表什么含义。

像素单位常见的有三种像素名称:

  • 设备像素(也称之为物理像素);
  • 设备独立像素(也称之为逻辑像素);
  • CSS像素

3.物理像素和逻辑像素

设备像素,也叫物理像素。

  • 设备像素指的是显示器上的真实像素,每个像素的大小是屏幕固有的属性,屏幕出厂以后就不会改变了;
  • 我们在购买显示器或者手机的时候,提到的设备分辨率就是设备像素的大小;
  • 比如iPhone X的分辨率 1125x2436,指的就是设备像素

设备独立像素,也叫逻辑像素。

  • 如果面向开发者我们使用设备像素显示一个100px的宽度,那么在不同屏幕上显示效果会是不同的;
  • 开发者针对不同的屏幕很难进行较好的适配,编写程序必须了解用户的分辨率来进行开发;
  • 所以在设备像素之上,操作系统为开发者进行抽象,提供了逻辑像素的概念
  • 比如你购买了一台显示器,在操作系统上是以1920x1080设置的显示分辨率,那么无论你购买的是2k、4k的显示器,对于开发者来说,都是 1920x1080的大小。

CSS像素

  • CSS中我们经常使用的单位也是 pixel,它在默认情况下等同于设备独立像素(也就是逻辑像素)
  • 毕竟逻辑像素才是面向我们开发者

我们可以通过 JavaScript 中的screen.widthscreen.height获取到电脑的逻辑分辨率:

4.DPR、PPI

DPR:device pixel ratio

  • 2010年,iPhone4问世,不仅仅带来了移动互联网,还带来了Retina屏幕;
  • Retina屏幕翻译为视网膜显示屏,可以为用户带来更好的显示;
  • 在Retina屏幕中,一个逻辑像素在长度上对应两个物理像素 ,这个比例称之为设备像素比(device pixel ratio);
  • 我们可以通过window.devicePixelRatio获取到当前屏幕上的DPR值;

PPI(了解):每英寸像素(英语:Pixels Per Inch,缩写:PPI)

  • 通常用来表示一个打印图像或者显示器上像素的密度;
  • 前面我们提过1英寸=2.54厘米,在工业领域被广泛应用;

五、浏览器视口Viewport

1.什么是移动端适配?

移动互联网的快速发展,让人们已经越来越习惯于使用手机来完成大部分日常的事务。

  • 前端我们已经学习了大量HTML、CSS的前端开发知识,并且也进行了项目实战;
  • 这些知识也同样适用于移动端开发,但是如果想让一个页面真正适配于移动端,我们最好多了解一些移动端的知识;

移动端开发目前主要包括三类:

  • 原生App开发(iOS、Android、RN、uniapp、Flutter等)
  • 小程序开发(原生小程序、uniapp、Taro等)
  • Web页面(移动端的Web页面,可以使用浏览器或者webview浏览)

因为目前移动端设备较多,所以我们需要对其进行一些适配。

这里有两个概念:

  • 自适应:根据不同的设备屏幕大小来自动调整尺寸、大小;
  • 响应式:会随着屏幕的实时变动而自动调整,是一种自适应;

2.认识视口viewport

在前面我们已经简单了解过视口的概念了:

  • 在一个浏览器中,我们可以看到的区域就是视口(viewport);
  • 我们说过 fixed 就是相对于视口来进行定位的;
  • 在PC端的页面中,我们是不需要对视口进行区分,因为我们的布局视口视觉视口是同一个;

但是在移动端,不太一样,你布局的视口和你可见的视口是不太一样的。

  • 这是因为移动端的网页窗口往往比较小,我们可能会希望一个大的网页在移动端可以完整的显示;
  • 所以在默认情况下,移动端的布局视口是大于视觉视口的

所以在移动端,我们可以将视口划分为三种情况:

  • 布局视口(layout viewport)
  • 视觉视口(visual layout)
  • 理想视口(ideal layout)

这些概念的区分,事实上来自ppk,他也是对前端贡献比较大的一个人(特别是在移动端浏览器)

3.布局视口和视觉视口

3.1布局视口(layout viewport)

默认情况下,一个在PC端的网页在移动端会如何显示呢?

  • 第一,它会按照宽度为980px来布局一个页面的盒子和内容
  • 第二,为了显示可以完整的显示在页面中,对整个页面进行缩小

我们相对于980px布局的这个视口,称之为布局视口(layout viewport);

  • 布局视口的默认宽度是980px

3.2视觉视口(visual viewport)

  • 如果默认情况下,我们按照980px显示内容,那么右侧有一部分区域 就会无法显示,所以手机端浏览器会默认对页面进行缩放以显示到用户的可见区域中
  • 那么显示在可见区域的这个视口,就是视觉视口(visual viewport)

在Chrome上按shift+鼠标左键可以进行缩放。

4.理想视口(ideal viewport)

如果所有的网页都按照980px在移动端布局,那么最终页面都会被缩放显示。

  • 事实上这种方式是不利于我们进行移动的开发的,我们希望的是设置100px,那么显示的就是100px;
  • 如何做到这一点呢?通过设置理想视口(ideal viewport);

理想视口(ideal viewport):

  • 默认情况下的layout viewport并不适合我们进行布局;
  • 我们可以对 layout viewport 进行宽度和缩放的设置,以满足正常在一个移动端窗口的布局;
  • 这个时候可以设置meta中的viewport

六、移动端适配

1.移动端适配方案

移动端的屏幕尺寸通常是非常繁多的,很多时候我们希望在不同的屏幕尺寸上显示不同的大小;

  • 比如我们设置一个100x100的盒子
    • 在375px的屏幕上显示是100 x 100;
    • 在320px的屏幕上显示是90+ x 90+;
    • 在414px的屏幕上显示是100+ x 100+;
  • 其他尺寸也是类似,比如padding、margin、border、left,甚至是font-size等等;

这个时候,我们可能可以想到一些方案来处理尺寸:

  • 方案一:百分比设置
    • 因为不同属性的百分比值,相对的可能是不同参照物,所以百分比往往很难统一
    • 所以百分比在移动端适配中使用是非常少的;
  • 方案二:rem单位+动态html的font-size
  • 方案三:vw单位
  • 方案四:flex的弹性布局

2.适配方案 -- rem+动态html的font-size

rem单位是相对于html元素的font-size来设置的,那么如果我们需要在不同的屏幕下有不同的尺寸,可以动态的修改html的 font-size 尺寸。

比如如下案例:

  • 1.设置一个盒子的宽度是 2rem;
  • 2.设置不同的屏幕上html的font-size不同;

这样在开发中,我们只需要考虑两个问题:

  • 问题一:针对不同的屏幕,设置html不同的font-size;
  • 问题二:将原来要设置的尺寸,转化成rem单位;

2.1 rem的font-size尺寸

方案一:媒体查询

  • 可以通过媒体查询来设置不同尺寸范围内的屏幕html的font-size尺寸;
  • 缺点:
    • 1.我们需要针对不同的屏幕编写大量的媒体查询;
    • 2.如果动态改变尺寸,不会实时的进行更新

方案二:编写js代码

  • 如果希望实时改变屏幕尺寸时,font-size也可以实时更改,可以通过js代码;
  • 方法:
    • 1.根据html的宽度计算出font-size的大小,并且设置到html上;
    • 2.监听页面的实时改变,并且重新设置font-size的大小到html上;
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>
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    .box {
      width: 6.25rem;
      height: 6.25rem;
      background-color: #ccc;
    }
  </style>
</head>
<body>
  <div class="box">吃饭睡觉阿斗都</div>

  <script>
    var htmlEl = document.documentElement;
    function setRemUnit() {
      var htmlFontSize = htmlEl.clientWidth / 46.875;
      htmlEl.style.fontSize = htmlFontSize + "px";
      console.log(htmlFontSize);
    }
    setRemUnit();
    window.addEventListener("resize", function () {
      setRemUnit();
    })
  </script>
</body>
</html>

方案三:lib-flexible 库

  • 事实上,lib-flexible库做的事情是相同的,你也可以直接引入它;

2.2 rem的单位换算

方案一:手动换算

  • 比如有一个在375px屏幕上,100px宽度和高度的盒子;
  • 我们需要将100px转成对应的rem值;
  • 100/37.5=2.6667,其他也是相同的方法计算即可;

方案二:less/scss函数

方案三:postcss-pxtorem(后续学习)

  • 目前在前端的工程化开发中,我们可以借助于webpack的工具来完成自动的转化;

方案四:VSCode插件

  • px to rem 的插件,在编写时自动转化;

3.适配方案 - vw

在flexible GitHub上已经有写过这样的一句话:

由于viewport单位得到众多浏览器的兼容,lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport来替代此方。

所以它更推荐使用viewport的两个单位vw、vh

vw的兼容性如何呢?

4.vw 和 rem 的对比

rem事实上是作为一种过渡的方案,它利用的也是vw的思想。

  • 前面不管是我们自己编写的js,还是flexible的源码;
  • 都是将1rem等同于设计稿的1/10,在利用1rem计算相对于整个屏幕的尺寸大小;
  • 那么我们来思考,1vw不是刚好等于屏幕的1/100吗?
  • 而且相对于rem还更加有优势;

vw相比于rem的优势:

  • 优势一:不需要去计算html的font-size大小,也不需要给html设置这样一个font-size;
  • 优势二:不会因为设置html的font-size大小,而必须给body再设置一个font-size,防止继承;
  • 优势三:因为不依赖font-size的尺寸,所以不用担心某些原因html的font-size尺寸被篡改,页面尺寸混乱;
  • 优势四:vw相比于rem更加语义化,1vw刚才是1/100的viewport的大小;
  • 优势五:可以具备rem之前所有的优点;

vw 我们只面临一个问题,将尺寸换算成vw的单位即可;

所以,目前相比于rem,更加推荐大家使用 vw(但是理解rem依然很重要)

5.vw的单位换算

方案一:手动换算

  • 比如有一个在375px屏幕上,100px宽度和高度的盒子;

  • 我们需要将100px转成对应的vw值;

  • 100/3.75=26.667,其他也是相同的方法计算即可;

方案二:less/scss函数

方案三:postcss-px-to-viewport-8-plugin(后续学习)

  • 和rem一样,在前端的工程化开发中,我们可以借助于webpack的工具来完成自动的转化;

方案四:VSCode插件

  • px to vw 的插件,在编写时自动转化;
相关推荐
gnip43 分钟前
链式调用和延迟执行
前端·javascript
SoaringHeart1 小时前
Flutter组件封装:页面点击事件拦截
前端·flutter
杨天天.1 小时前
小程序原生实现音频播放器,下一首上一首切换,拖动进度条等功能
前端·javascript·小程序·音视频
Dragon Wu1 小时前
React state在setInterval里未获取最新值的问题
前端·javascript·react.js·前端框架
Jinuss1 小时前
Vue3源码reactivity响应式篇之watch实现
前端·vue3
YU大宗师1 小时前
React面试题
前端·javascript·react.js
木兮xg1 小时前
react基础篇
前端·react.js·前端框架
ssshooter2 小时前
你知道怎么用 pnpm 临时给某个库打补丁吗?
前端·面试·npm
IT利刃出鞘2 小时前
HTML--最简的二级菜单页面
前端·html
yume_sibai2 小时前
HTML HTML基础(4)
前端·html