像素、视口、网页计量单位与移动端适配方案

像素的概念

设备像素(物理像素)

指设备能控制显示的最小物理单位,像一个个小点,每一个小像素点都是由三原色RGB组成。物理像素只是为了描述物理分辨率,在屏幕出厂时就已经固定了,单位是pt。【注意区分分辨率和物理分辨率,物理分辨率固定,而分辨率可变且不能超过物理分辨率

物理分辨率是液晶屏固有的参数不能调节,其含义是指液晶屏最高可显示的像素数,其表示方法与分辨率相同【例如,分辨率1024*768就是指横向有1024个像素点,纵向有768个像素点。】。一般来讲物理分辨率的大小可直接决定屏幕的最高分辨率,分辨率不会大于物理分辨率。

屏幕尺寸一样的情况下,分辨率越高,显示效果就越细腻。

设备独立像素

设备独立像素(又称设备无关像素 Device Independent Pixels 、密度独立性 Density Independent或设备独立像素,简称DIP或DP)是一种物理测量单位,基于计算机控制的坐标系统和抽象像素(虚拟像素),由底层系统的程序使用,转换为物理像素的应用。
典型的用途是允许移动设备软件将信息显示和用户交互扩展到不同的屏幕尺寸。允许应用程序以抽象像素为单位进行测量,而底层图形系统将应用程序的抽象像素测量值转换为适合于特定设备的物理像素。

设备独立像素代表可以通过程序控制使用的虚拟像素。在无缩放情况下,1个CSS像素等于1个设备独立像素;如果放大一倍,1个CSS像素就等于4个设备独立像素,以此类推 (宽2倍 高2倍)

通常而言,我们所说的这种可由程序调节设置的分辨率,指的就是设备独立像素。

1设备独立像素 = 1或N 物理像素
【包含的越多则屏幕看起来越清晰】

之所以需要设备独立像素,是因为不同设备的物理像素不同,不能只拿其中一个例子作为基准。

在js中可以通过window.screen.width/ window.screen.height获取屏幕尺寸(设备独立像素值)

设备像素比dpr

=设备像素/设备独立像素。
if(drp === 1:1) use 1pt show 1dp
if(drp === 2:1) use 4pt show 1dp
if(drp === 3:1) use 9pt show 1dp

像素密度PPI

单位是dpi。PPI = 对角线的分辨率 / 对角线尺寸

PC端中,未缩放的情况下,1个设备独立像素 = 1个设备像素

CSS像素

CSS像素是用于web编程的逻辑像素,以px为单位。px是相对单位,但是相对的是分辨率,跟ppi和dpr都有关系。

无缩放情况下,1个CSS像素等于1个设备独立像素

网页中的计量单位

px

px表示像素,如果理解成相对单位,那是因为它是相对于设备像素而言的;如果理解成绝对单位,那是因为它的实际显示大小与元素是无关的。通常会理解成绝对长度单位。

rem

相对HTML根元素字体大小(浏览器默认字体大小是16px)。

em

相对于父元素的字体大小。如过没有被人为设置,则相对于浏览器的默认字体尺寸。
eg.

<div>
    我是父元素div
    <p>
        我是子元素p
    p>
div>
div {
  font-size: 40px;
  width: 10em; /* 400px */
  height: 10em;
  border: solid 1px black;
}
p {
  font-size: 0.5em; /* 20px */ 
  width: 10em; /* 200px */
  height: 10em;
  border: solid 1px red;
}

但是要注意的是,浏览器默认的最小字体是12px,如果要实现更小,只能用transform:scale来缩放比例。

vw、vh

相对于视口的宽度/高度。把视口分成一百份。

%

相对于包含块的高宽或字体大小来取值。
如果是静态定位和相对定位,则相对于父元素取值;
如果是绝对定位元素,则相对于离它最近的position非static值的祖先元素;
如果是固定定位元素,则相对于视口取值。

视口viewport

上述讲述网页中的计量单位是提到了视口的概念,因此在这里也提一下。

PC端中,视口就是指浏览器的可视区域,宽度由浏览器的窗口的宽决定的,用户可以手动缩放窗口来改变视口大小。

移动端就分成三种情况:布局视口(Layout Viewport)、视觉视口(Visual Viewport)和理想视口(Ideal Viewport)。

布局视口layout viewport

一般移动设备的浏览器都默认设置了一个 viewport 元标签,定义一个虚拟的布局视口,以解决早期的页面在手机上显示的问题。其大小由浏览器厂商决定,一般设置成980px。html内的元素都是以布局视口为基准进行布局的,如果需要显式的修改布局视口的大小,可以用meta标签设置。

布局视口的宽度/高度可以通过document.documentElement.clientWidth / Height 获取。

视觉视口visual viewport

顾名思义就是用户可见区域,可以把它就当作是手机屏幕的那个框。用户可以通过缩放的操作来调整视觉视口,而不会影响布局视口。用户放大时,视觉视口将会变小,CSS 像素将跨越更多的物理像素。
默认情况下,移动端浏览器会将视觉视口缩放到与layout 布局视口相同,也就是默认打开页面就能看到整个布局视口里的内容。

视觉视口的宽度/高度可以通过
window.innerWidth / window.innerHeight 获取。

理想视口ideal viewport

理想视口就是布局视口的宽度和屏幕同宽,它并不是一种真实存在的视口。

实现方法:

<meta name="viewport" content="width=device-width">

利用meta标签设置viewport

一些重要的属性如下:

width:控制布局视口的大小。 height:和 width 相对应,指定高度。
initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例。
maximum-scale:允许用户缩放到的最大比例。 minimum-scale:允许用户缩放到的最小比例。
user-scalable:用户是否可以手动缩放

移动端适配方案

终于来到我们要讲的最后重点——移动端适配。它实现的方案有四种:

  1. rem布局
    先用meta标签设置布局视口等于设备宽度,实现理想视口。
<meta name="viewport"  content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,minimum-scale=1.0">

然后根据屏幕分辨率动态设置html的字体大小,达到等比缩放的功能,且需要保证html最终算出来的字体大小,不能小于12px。
这一步我一般使用flexible.js,js内容如下:

(function flexible(window, document) {
    var docEl = document.documentElement
    var dpr = window.devicePixelRatio || 1

    // adjust body font size
    function setBodyFontSize() {
        if (document.body) {
            document.body.style.fontSize = (12 * dpr) + 'px'
        } else {
            document.addEventListener('DOMContentLoaded', setBodyFontSize)
        }
    }
    setBodyFontSize();

    // set 1rem = viewWidth / 10
    function setRemUnit() {
        var rem = docEl.clientWidth / 10
        docEl.style.fontSize = rem + 'px'
    }

    setRemUnit()

    // reset rem unit on page resize
    window.addEventListener('resize', setRemUnit)
    window.addEventListener('pageshow', function(e) {
        if (e.persisted) {
            setRemUnit()
        }
    })

    // detect 0.5px supports
    if (dpr >= 2) {
        var fakeBody = document.createElement('body')
        var testElement = document.createElement('div')
        testElement.style.border = '.5px solid transparent'
        fakeBody.appendChild(testElement)
        docEl.appendChild(fakeBody)
        if (testElement.offsetHeight === 1) {
            docEl.classList.add('hairlines')
        }
        docEl.removeChild(fakeBody)
    }
}(window, document))

可以看到,它会把设备宽度分为10等份,然后将一等份的大小作为html根元素的font-size值。因此1rem就等于设备宽度的1等份。

由于实际开发中不可能每次都自己计算rem值,因此这里推荐一个vscode插件:px to rem & rpx & vw (cssrem)。例如,设计稿一般为750px,那么1等份就是75px,基准值就可以设置成75px,之后开发时直接在css文件里写px会自动提示相应的rem值。
则px换算成rem公式为: px值 / 75 = rem, 例如:100px=100/75=1.33rem

  1. 媒体查询

通过查询设备的宽度来执行不同的 css 代码,最终达到界面的配置。

  1. vw/vh布局

把所有需求适配屏幕大小等比缩放的元素都使用 vw 作为单位。不需要缩放的使用 px 做单位。

但是缺点是px转换成vw不一定能整除,会有一定的像素差;而且当容器使用 vw,margin 采用 px 时,很容易造成整体宽度超过 100vw,从而影响布局效果。但是使用 padding 代替 margin,结合 calc()函数使用等等方法来避免。

  1. Flex布局

高度固定,宽度自适应

参考文章

设备像素、设备独立像素、CSS像素、分辨率、PPI、devicePixelRatio 的区别

物理像素,逻辑像素(pt),css像素(px),像素比(dpr)都是什么?px,em,rem等 都是什么?有什么区别?

尚硅谷-前端移动端适配方案

浅谈移动端中的视口(viewport)

理解flexible.js所需的viewport知识

移动端适配方案

你可能感兴趣的:(前端,前端)