简要介绍:前端开发中,静态网页通常需要适应不同分辨率的设备,常用的自适应解决方案包括媒体查询、百分比、rem和vw/vh等。本文从px单位出发,分析了px在移动端布局中的不足,接着介绍了几种不同的自适应解决方案。

  • px和视口
  • 媒体查询
  • 百分比
  • 自适应场景下的rem解决方案
  • 通过vw/vh来实现自适应

一、px和视口

在静态网页中,我们经常用像素(px)作为单位,来描述一个元素的宽高以及定位信息。在pc端,通常认为css中,1px所表示的真实长度是固定的。

那么,px真的是一个设备无关,跟长度单位米和分米一样是固定大小的吗?

字体都是16px,显然在pc端中文字正常显示,而在移动端文字很小,几乎看不到,说明在css中1px并不是固定大小,直观从我们发现在移动端1px所表示的长度较小,所以导致文字显示不清楚。

那么css中的1px的真实长度到底由什么决定呢?

为了理清楚这个概念我们首先介绍像素和视口的概念

1. 像素

像素是网页布局的基础,一个像素表示了计算机屏幕所能显示的最小区域,像素分为两种类型:css像素和物理像素。

我们在js或者css代码中使用的px单位就是指的是css像素,物理像素也称设备像素,只与设备或者说硬件有关,同样尺寸的屏幕,设备的密度越高,物理像素也就越多。下表表示css像素和物理像素的具体区别:

css像素 为web开发者提供,在css中使用的一个抽象单位
物理像素 只与设备的硬件密度有关,任何设备的物理像素都是固定的

那么css像素与物理像素的转换关系是怎么样的呢?为了明确css像素和物理像素的转换关系,必须先了解视口是什么。

2. 视口

广义的视口,是指浏览器显示内容的屏幕区域,狭义的视口包括了布局视口、视觉视口和理想视口

(1) 布局视口(layout viewport)

布局视口定义了pc网页在移动端的默认布局行为,因为通常pc的分辨率较大,布局视口默认为980px。也就是说在不设置网页的viewport的情况下,pc端的网页默认会以布局视口为基准,在移动端进行展示。因此我们可以明显看出来,默认为布局视口时,根植于pc端的网页在移动端展示很模糊。

(2) 视觉视口(visual viewport)

视觉视口表示浏览器内看到的网站的显示区域,用户可以通过缩放来查看网页的显示内容,从而改变视觉视口。视觉视口的定义,就像拿着一个放大镜分别从不同距离观察同一个物体,视觉视口仅仅类似于放大镜中显示的内容,因此视觉视口不会影响布局视口的宽度和高度。

(3) 理想视口(ideal viewport)

理想视口或者应该全称为“理想的布局视口”,在移动设备中就是指设备的分辨率。换句话说,理想视口或者说分辨率就是给定设备物理像素的情况下,最佳的“布局视口”。

上述视口中,最重要的是要明确理想视口的概念,在移动端中,理想视口或者说分辨率跟物理像素之间有什么关系呢?

为了理清分辨率和物理像素之间的联系,我们介绍一个用DPR(Device pixel ratio)设备像素比来表示,则可以写成:

在不缩放的情况下,一个css像素就对应一个dpr,也就是说,在不缩放

此外,在移动端的布局中,我们可以通过viewport元标签来控制布局,比如一般情况下,我们可以通过下述标签使得移动端在理想视口下布局:

上述meta标签的每一个属性的详细介绍如下:

属性名 取值 描述
width 正整数 定义布局视口的宽度,单位为像素
height 正整数 定义布局视口的高度,单位为像素,很少使用
initial-scale [0,10] 初始缩放比例,1表示不缩放
minimum-scale [0,10] 最小缩放比例
maximum-scale [0,10] 最大缩放比例
user-scalable yes/no 是否允许手动缩放页面,默认值为yes

其中我们来看width属性,在移动端布局时,在meta标签中我们会将width设置称为device-width,device-width一般是表示分辨率的宽,通过width=device-width的设置我们就将布局视口设置成了理想的视口。

3. px与自适应

上述我们了解到了当通过viewport元标签,设置布局视口为理想视口时,1个css像素可以表示成:

我们直到,在pc端的布局视口通常情况下为980px,移动端以iphone6为例,分辨率为375 * 667,也就是说布局视口在理想的情况下为375px。比如现在我们有一个750px * 1134px的视觉稿,那么在pc端,一个css像素可以如下计算

而在iphone6下:

也就是说在PC端,一个CSS像素可以用0.76个物理像素来表示,而iphone6中 一个CSS像素表示了2个物理像素。此外不同的移动设备分辨率不同,也就是1个CSS像素可以表示的物理像素是不同的,因此如果在css中仅仅通过px作为长度和宽度的单位,造成的结果就是无法通过一套样式,实现各端的自适应。

二、媒体查询

在前面我们说到,不同端的设备下,在css文件中,1px所表示的物理像素的大小是不同的,因此通过一套样式,是无法实现各端的自适应。由此我们联想:

如果一套样式不行,那么能否给每一种设备各一套不同的样式来实现自适应的效果?

答案是肯定的。

使用@media媒体查询可以针对不同的媒体类型定义不同的样式,特别是响应式页面,可以针对不同屏幕的大小,编写多套样式,从而达到自适应的效果。举例来说:

上述的代码通过媒体查询定义了几套样式,通过max-width设置样式生效时的最大分辨率,上述的代码分别对分辨率在0~320px,320px~550px,550px~768px以及768px~960px的屏幕设置了不同的背景颜色。

通过媒体查询,可以通过给不同分辨率的设备编写不同的样式来实现响应式的布局,比如我们为不同分辨率的屏幕,设置不同的背景图片。比如给小屏幕手机设置@2x图,为大屏幕手机设置@3x图,通过媒体查询就能很方便的实现。

但是媒体查询的缺点也很明显,如果在浏览器大小改变时,需要改变的样式太多,那么多套样式代码会很繁琐。

三、百分比

除了用px结合媒体查询实现响应式布局外,我们也可以通过百分比单位 " % " 来实现响应式的效果。

比如当浏览器的宽度或者高度发生变化时,通过百分比单位,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。

为了了解百分比布局,首先要了解的问题是:

css中的子元素中的百分比(%)到底是谁的百分比?

直观的理解,我们可能会认为子元素的百分比完全相对于直接父元素,height百分比相对于height,width百分比相对于width。当然这种理解是正确的,但是根据css的盒式模型,除了height、width属性外,还具有padding、border、margin等等属性。那么这些属性设置成百分比,是根据父元素的那些属性呢?此外还有border-radius和translate等属性中的百分比,又是相对于什么呢?下面来具体分析。

1. 百分比的具体分析

(1)子元素height和width的百分比

子元素的height或width中使用百分比,是相对于子元素的直接父元素,width相对于父元素的width,height相对于父元素的height。比如: