移动端页面适配方案

本文介绍了移动端web页面的适配方案,包括百分比宽度、rem、动态缩放的rem、vh/vw以及vw+rem。针对1px问题和2倍图3倍图问题提出了解决方案,如使用伪元素、viewport缩放、srcset和sizes属性等,帮助开发者实现跨设备的完美展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

移动端web页面的开发,由于手机屏幕尺寸、分辨率不同,或者需要考虑横竖屏问题,为了使得web页面在不同移动设备上具有相适应的展示效果,需要在开发过程中使用合理的适配方案来解决这个问题。经过整理,常用方案有以下几种

视口相关理解:
获取布局视口的宽度:document.documentElement.clientWidth
获取设备css像素(屏幕尺寸):window.screen.width

<meta name=”viewport” content=”width=device-width, initial-scale=1, maximum-scale=1″>

width:控制 layout viewport 的大小,可以指定的一个值,如 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。

方案一:百分比—固定高度,宽度自适应

这种方案是目前使用较多的方案,也是相对较简单的实现方案:

该方法使用了理想视口:

<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">

垂直方向使用固定的值,水平方向使用弹性布局,元素采用定值、百分比、flex布局等。这种方案相对简单,还原度也非常低。

使用 百分比% 定义 宽度,高度 用px固定,根据可视区域实时尺寸进行调整,尽可能适应各种分辨率,通常使用max-width/min-width控制尺寸范围过大或者过小。下表是子元素不同属性设置百分比的依据

属性设置参考
height/width基于子元素的直接父元素,width相对于父元素的width,height相对于父元素的height
top/bottom 和left/right相对于直接非static定位的父元素的height/width
padding/margin不论是垂直方向或者是水平方向,都相对于直接父亲元素的width,与父元素的height无关
border-radius相对于自身的宽度
方案二:rem—固定布局视口,以rem作为宽度单位,根据不同屏幕动态写入font-size

实例:网易新闻

固定布局视口,设置理想视口

<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">

以640px设计稿和750px的视觉稿,网易这样处理的:DOMContentLoaded后,设置rem

var width = document.documentElement.clientWidth;   // 屏幕的布局视口宽度
var rem = width / 7.5;                              // 750px设计稿与375px的屏幕都将布局视口分为7.5份,
// 如果设计稿是640px
var rem = width / 6.4;                              // 640px设计稿与320px的屏幕都将布局视口分为6.4份

这里width除以的常数值主要是为了得到100,方便根据设计稿计算元素的尺寸。这样不管是750px设计稿还是640px设计稿,1rem 等于设计稿上的100px。故px转换rem时:

rem = px / 100

在750px设计稿上:

//75px 对应 0.75rem, 距离占设计稿的10%;

//在ipone6上:
width = document.documentElement.clientWidth = 375px;
rem = 375px / 7.5 = 50px;
0.75rem = 37.5px;   //(37.5/375=10%;占屏幕10%)
                     
//在ipone5上:
width = document.documentElement.clientWidth = 320px;
rem = 320px / 7.5 = 42.667px;
0.75rem = 32px; //(32/320=10%;占屏幕10%)

故对于设计稿上任何一个尺寸换成rem后,在任何屏下对应的尺寸占屏幕宽度的百分比相同。故这种布局可以百分比还原设计图。

此方案的font-size使用了rem作为单位

在这里插入图片描述
在这里插入图片描述
js代码:

(function (doc,win) {
          var fn = function () {
              var deviceWidth =  doc.documentElement.clientWidth; // 获取的是布局视口宽度
              // 移动设备的横向逻辑像素超过640,可以去访问pc端了。
              if (deviceWidth > 640) { // 保持font-size值不变。
                  deviceWidth = 640;
              }
              doc.documentElement.style.fontSize = deviceWidth / 7.5 + 'px';
          }
          window.addEventListener('orientationchange'in win ? 'orientationchange' : 'resize', fn ,false);
          doc.addEventListener('DOMContentLoaded',fn,false);

 })(document,window)
方案三:rem—动态缩放布局视口,以rem作为宽度单位,动态写入font-size

实例:手机淘宝

以iphone6的设计稿750为例

根据dpr来设置viewport缩放。看看淘宝的:

var devicePixelRatio = window.devicePixelRatio;
var isIPhone = window.navigator.appVersion.match(/iphone/gi);
var dpr,scale;
if (isIPhone) {
  if (devicePixelRatio >=3) {
    dpr = 3;
  } else if (devicePixelRatio >=2) {
    dpr = 2;
  } else {
    dpr = 1;
  }
} else {
  dpr = 1;
}
scale = 1 / dpr;

// 设置meta标签
doc.write("<meta name=viewport content=width=device-width,initial-scale="+scale+",minimum-scale="+scale+",maximum-scale="+scale+",user-scalable=no>");

淘宝只对iphone做了缩放处理,对于android所有dpr=1,scale=1即没有缩放处理。(淘宝的flexible适配方案为什么只对iOS进行dpr判断,对于Android始终认为其dpr为1?

缩放之后,布局视口的宽度 = device-width / scale

将屏幕分为固定的块数7.5,这个数值主要是为了得出容易计算的rem:

var width = document.documentElement.clientWidth;   // 屏幕的布局视口宽度
var rem = width / 7.5;                               // 将布局视口分为7.5份

这样在任何屏幕下,总长度都为7.5rem。1rem对应的值也不固定,与屏幕的布局视口宽度有关。

此方案与方案二相似,只是对iphone做了viewport缩放,能百分比还原设计稿。

在这里插入图片描述
在这里插入图片描述
相对完整代码:

(function (doc,win) {
          var devicePixelRatio = window.devicePixelRatio;
          
          // 只对iphone的视口进行缩放
          var isIPhone = window.navigator.appVersion.match(/iphone/gi);
		  var dpr,scale;
		  if (isIPhone) {
		    if (devicePixelRatio >=3) {
		      dpr = 3;
		    } else if (devicePixelRatio >=2) {
		    dpr = 2;
		    } else {
		      dpr = 1;
		    }
		  } else {
		    dpr = 1;
		  }
		  scale = 1 / dpr;
		  
		  // 设置meta标签
          doc.write("<meta name=viewport content=width=device-width,initial-scale="+scale+",minimum-scale="+scale+",maximum-scale="+scale+",user-scalable=no>");

		  // 动态设置html字体大小
          var fn = function () {
              var deviceWidth =  doc.documentElement.clientWidth; // 获取的是布局视口宽度
              // 移动设备的横向逻辑像素超过640(这时候物理像素大于1280),可以去访问pc端了。
              if (deviceWidth > 1280) { // 保持font-size值不变。
                  deviceWidth = 1280;
              }
              doc.documentElement.style.fontSize = deviceWidth / 7.5 + 'px';
          }
          window.addEventListener('orientationchange'in win ? 'orientationchange' : 'resize', fn ,false);
          doc.addEventListener('DOMContentLoaded',fn,false);

      })(document,window)
方案四:vh/vw

原理
视口是浏览器中用于呈现网页的区域,移动端的视口通常指的是 布局视口

  • vw : 1vw 等于 视口宽度 的 1%
  • vh : 1vh 等于 视口高度 的 1%
  • vmin : 选取 vw 和 vh 中 最小 的那个
  • vmax : 选取 vw 和 vh 中 最大 的那个

使用 css 预处理器把设计稿尺寸转换为 vw 单位,包括 文本,布局高宽,间距 等,使得这些元素能够随视口大小自适应调整。以1080px设计稿为基准,转化的计算表示为

// 以1080px作为设计稿基准
$vw_base: 1080
@function vw($px) {
    @return($px / 1080) * 100vw
}
方案五:vw + rem

原理:通过vw这一动态单位来动态设置rem(根元素html的font-size),从而达到不同设备的设配

此方法使得任何页面在不同分辨率设备,所显示的内容均为一样,相当于等比例缩放。首先我们来看一下vw的兼容
vw兼容性图例
步骤:
(1)设置理想视口
html页面设置meta标签(该标签在做移动端页面时不用说肯定都要加上,如果引用的开源代码可能会自动加上该标签,则不用手动添加)

<meta name = 'viewport' content = 'width = device-width,initial-scale = 1,minimum-scale = 1, maximum-scale = 1, user-scalable = no'/>

(2)设置html元素的font-size属性

html {
	font-size: calc(16 / 3.75 * 1vw);
}

解释一下公式里的参数:
16 : 表示浏览器默认字体大小
3.75 : 目前大多数设计图分别有两个尺寸,640或者750,可能750占大多数,那我们就拿750尺寸作为参照,这样 3.75px(css像素) == 1vw
在这里插入图片描述

以上公式则是将750尺寸设计图下浏览器的rem设置为了16px。公式里的数值可以根据设计稿以及想要设置的rem大小进行改变,同时需注意浏览器对于最小字体的限制。

通过以上公式,就将rem转换为了根据设备变化的动态单位。

(3)现在我们就可以根据rem来进行眼样式的编写。但是在对照设计稿转换成rem时涉及换算比较麻烦,这个时候我们可以考虑css预处理器的函数,以下为scss里面的函数参考

/* 1. 新建px转换为rem方法*/
@function px2rem($px){
	@return $px / 16 + rem;
}
/*2. 使用该方法 这里效果图里面是多少尺寸,就写多少尺寸,比如某元素字体大小为24px*/
.aaa{
	font-size: px2rem(24);
}
/*某div高度为100px*/
.bbb{
	height: px2rem(100);
}

函数中的具体数值视情况而定

至此,vw+rem适配法已经完成。

移动端web页面适配方案中的通用问题
1px问题

在不同的移动设备中,css像素的1px因为dpr的不同会使用dpr个物理像素来显示,这就造成1px在不同设备上显示的粗细不一致,为解决这个问题,可采用如下方案:

伪元素+transform: scale(0.5) 方案

给需要设置1px边框的元素添加border-1px类

.border-1px:after {
            content: '';        
            position: absolute;
            top: 0;
            left: 0;
            border: 1px solid red;
            -webkit-transform-origin: 0 0;
            transform-origin: 0 0;
            
            /* 2倍屏 */
            @media screen and (min-device-pixel-ratio: 2),  (-webkit-min-device-pixel-ratio: 2){
                border-radius: 20px; // 圆角根据dpr放大相应的倍数
                width: 200%;
                height: 200%;
                -webkit-transform: scale(0.5);
                transform: scale(0.5);
            }
            /* 3倍屏 */
            @media screen and (min-device-pixel-ratio: 3),  (-webkit-min-device-pixel-ratio: 3){
                border-radius: 30px; // 圆角根据dpr放大相应的倍数
                width: 300%;
                height: 300%;
                -webkit-transform: scale(0.33);
                transform: scale(0.33);
            }

        }

还可以写成mixin的形式,见移动端设置border的1px像素解决方案

1px问题还可以通过viewport缩放来解决,如方案三。viewport根据dpr缩放后,css中的1px就是用的一个物理像素来表示。

2倍图3倍图问题

移动端开发过程中,因为手机的dpr(设备像素比不同),需要根据dpr来修改图标的大小,判断使用@2x 图 还是 @3x 图,解决高清的适配。

css3的 -webkit-min-device-pixel-ratio属性+@media媒体查询(只能用于背景图片)

/*less,sass这类css预处理语言中的混合,可以理解成自定义了一段代码,后面可以用@include调用*/
@mixin bg-image($url) {    
      background-image: url($url + "@2x.png");    
      @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3){        
            background-image: url($url + "@3x.png");    
      }
}
/*用@include调用*/
div{
  width:30px;
  height:20px;
  background-size:30px  20px;
  background-repeat:no-repeat;
  @include bg-image('../../../../static/image/map_loading');     
}

img标签的选择
对于引入的图片,如果想要图片适应不同像素密度的屏幕,并且屏幕上显示图片的实际尺寸相同,使用srcset属性用来指定多张图像。它的值是一个逗号分隔的字符串,每个部分都是一张图像的 URL,后面接一个空格,后接是像素密度描述符。浏览器根据当前设备的像素密度,选择需要加载的图像。如果srcset属性都不满足条件,那么就加载src属性指定的默认图像。

<img srcset="foo-320w.jpg,
             foo-480w.jpg 1.5x,
             foo-640w.jpg 2x"
     src="foo-640w.jpg">
     <!--srcset属性给出了三个图像URL,适应三种不同的像素密度, 后面的像素密度描述符,格式是像素密度倍数 + 字母x。1x表示单倍像素密度,可以省略。-->

如果想要针对不同屏幕,使用不同分辨率版本和尺寸的图片,使用属性srcse 和 sizes 。srcset 定义了允许浏览器选择的图像集,以及每个图像的大小(使用w单位)。sizes定义了一组媒体条件(例如屏幕宽度),指明当某些媒体条件为真时,什么样的图片尺寸是最佳选择。

<img srcset = "elva-fairy-320w.jpg 320w,
               elva-fairy-480w.jpg 480w,
               elva-fairy-800w.jpg 800w"
     sizes = "(max-width: 320px) 280px,
              (max-width: 480px) 440px,
              800px"
     src = "elva-fairy-800w.jpg" alt="Elva dressed as a fairy">

浏览器的查询过程:

  1. 查看设备宽度
  2. 检查sizes列表中哪个媒体条件是第一个为真
  3. 查看给予该媒体查询的槽大小
  4. 加载srcset列表中引用的最接近所选的槽大小的图像

参考文章:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值