我们通常在写移动端页面时,往往都会在html页面中加入这样一段话

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

可能我们只知道这三个字段的含义(视口宽度等于设备宽度,屏幕缩放为1,禁止用户缩放),但是为什么要这么写,其原理又是什么呢?

我们先看一个简单的demo吧。

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test 02</title>
</head>
<style>
body{
margin: 0;
}
.pic{
width: 320px;
height: 568px;
background-color: #72DFFF;
color: white;
font-size: 60px;
text-align: center;
line-height: 568px;
font-family: cursive;
}
</style>
<body>
<div class="pic"> 320*568 </div>
</body>
</html>

该demo展示一个宽度为320px的div,我们在iphone5上面打开看一下。

有没有感觉很诡异?明明iphone5的分辨率是320px*568px(我使用的是谷歌的mobile模拟),但是只显示了三分之一左右。

在回答此问题之前,我们需要先普及一下一些移动端的概念。

px:逻辑像素

dp:设备像素(物理像素)

dpr:设备像素缩放比

(某一方向上-->计算:dpr = 设备像素/逻辑像素,平面上-->计算:1px = (dpr)² *dp)

ppi:屏幕每英寸的像素数量,即单位英寸内的像素密度(计算:分辨率平方后开跟/屏幕尺寸)

ppi与dpr的关系表

  ldpr mdpr hdpr xhdpr
ppi 120 160 240 320
默认缩放比 0.75 1.0 1.5 2.0

我们得知iphone5的尺寸为4英寸,设备分辨率为1136dp*640dp,由此我们可以得出iphone5的分辨率为320px*568px,如下图(retina为高清)。

该页面展示三分之一的原因是ios中默认的布局viewport是980px,然后根据刚才的计算的iphone5分辨率才会出现此情况。

逻辑像素(css pixels)与设备像素(device pixels)的区别------------

我们姑且认定设备的pixels为正确(标准)的pixels宽度。这些pixels决定了你工作所用的那些设备上正式的分辨率。

如果用户缩放(zoom)了浏览器,当然必须改变计算方式。

现代浏览器上的缩放,是基于“伸展”pixels。结果是,html元素上的宽度并没有因为缩放200%而由128pix变成256px,而是真实的pixels的被计算成了双倍。html元素在形式上依然是128CSS的pixels,即便它占用了256设备的pixels 。

换言之,缩放200%将一个单位的CSS的pixels变成了4倍的设备的pixels那么大,即宽度 * 2、高度 * 2,面积扩大了2 * 2.

下列图片将清楚的解释这个概念。如图1-1.有4个1像素,缩放为100%的html元素,CSS的pixels完整的和设备的pixels重叠

当我们缩小浏览器时,CSS的pixels开始收缩,导致1单位的设备的pixels上重叠了多个CSS的pixels,如图1-2

同理,放大浏览器时,相反的事情发生了,CSS的pixels开始扩大,导致1单位的CSS的pixels上重叠了多个设备的pixels,如图1-3

总体而言,你只需要关注CSS的pixels,这些pixels指定你的样式被如何渲染。

就像刚开始的那个小demo,在pc以及iphone5上展示是两种完全不同的效果。

在这里我普及一个知识点,对于viewport,苹果手机浏览器默认做了两件事——

1.页面渲染在一个980px(IOS)的viewport(安卓viewport宽度不固定)

2.缩放

说的详细一些,viewport,就是手机浏览器把页面放到一个虚拟的窗口中,窗口可大于或小于手机的可视区域,一般会大于可视区域。这样不会破坏没有针对手机浏览器优化的网页的布局,用户可以通过平移或缩放来看网页的其它部分。

这也就是为什么我们没写viewport,手机会默认将布局宽度置为980px的原因。

为什么要有viewport?
一个300多像素的屏幕,放一个1000多像素的页面,会混乱,所以要先虚拟一个980像素的页面,然后进行缩放。

为什么不使用默认980px的布局viewport
1.宽度不可控,不同设备(安卓)默认值可能不同
2.页面缩小版展示,交互不友好
3.有缩放,缩放后有滚动
4.font-size 可能要设置40px才等于pc上12px,不规范

然后为了在iphone5上正常展示,我们需要写这样一个viewport

<meta name="viewport" content="width=320">

这样效果ok,但是如果我们的设备是iphone6,iphone6s呢?

<meta name="viewport" content="width=375">

显然是不符合规定的,所以我们需要设置

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

但是每个不同的设备都会有不同的缩放比
window.innerWidth/document.body.clientWidth 为 initial-scale
度量viewport/布局viewport [Layout Viewport(布局视口)]
比如如果要让iphone6展示1000px的页面,只设置"width=device-width",肯定都会挤在一起。

所以需要让缩放比为1,设置initial-scale=1,所以最终版本是这样

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

最后总结一下移动端中的三个viewport——

1.布局视口

document.body.clientWidth 为手机浏览器viewport宽度(布局viewport),默认980
跟width=device-width相关,其值等于meta标签中的width
initial-scale = 2 ,它会跟着缩小一倍
当你需要使用js而不是媒体查询来编写业务逻辑的时候,这很有帮助
if(document.body.clientWidth >= 400){

  .class{...}
}
等价于
@media all and (max-width>=400){

  .class{...}
}

我们用到的vw,vh尺寸单位代表视口的百分比,比如width:50vh,这里的视口就是指布局视口,因为如果是视觉视口,每次用户缩放都会导致元素狂傲发生变化,先不说这个变化带来的大计算量,这种设计对用户来说本身就是毫无意义的。

2.视觉视口

window.innerWidth
屏幕上显示的网站区域尺寸,会受缩放的影响

3.理想视口

screen.width

它是对设备来说最理想的布局视口尺寸。

-----------------------------------------------------------------------------------------------------------------------

在手机上,桌面视口被拆分成两个——布局视口限制你的css布局,视觉视口决定用户能看到什么。

其实这么多的viewport看起来可能会乱一点,但事实并不是这样。最佳实践就是让浏览器直接使用它的理想视口,即把布局视口设置为理想视口,然后使用媒体查询来响应不同的理想视口就OK。

响应式设计的核心——
width和height的媒体查询设置了当前布局视口的宽高。
使用最佳mate标签后,就可以放心的抛开布局视口的宽度,只专注于理想视口
@media all and (max-width:400) {
  .class {
    ...
  }
}

浅谈移动端三大viewport的更多相关文章

  1. 浅谈移动端适配-rem

    对于移动端开发来说,无可避免的就是直面各种设备不同分辨率和不同DPR(设备像素比)的问题,在此忽略其他兼容性问题的探讨. 一. 移动端开发有关于像素的概念: 1.设备像素(dp),也叫物理像素.指设备 ...

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

    在 PC 端,视口指的是浏览器的可视区域,其宽度和浏览器窗口的宽度保持一致.在 CSS 标准文档中,视口也被称为初始包含块,它是所有 CSS 百分比宽度推算的根源,给 CSS 布局限制了一个最大宽度. ...

  3. 浅谈移动端之touch事件--手指的滑动事件

    今天台风‘海马’袭击深圳,全市停工.现分享一篇关于touch的文章,望指教! 原理: 当开始一个touchstart事件的时候,获取此刻手指的横坐标startX和纵坐标startY: 当触发touch ...

  4. 开园子啦(浅谈移动端以及h5的发展)

    一.前言 一直以来都梦想着写几篇博客,忙于工作一直也没有抽出时间来写一下.看看大熊君.小v君等都在努力写博客,我这个不太善于言表的少年,也是在忍不住了.否则会被人家拉下更远.先简单介绍一下自己,目前我 ...

  5. 浅谈移动端rem的用法

    一 什么是rem? “font size of the root element 这是w3c的定义 也就是说是相对于根节点(html节点)的字体大小的单位. 目前主流的浏览器基本都支持rem这个单位, ...

  6. 浅谈移动端设备标识码:DeviceID、IMEI、IDFA、UDID和UUID

    ---恢复内容开始--- 转:https://www.jianshu.com/p/38f4d1a4763b [心路历程] 最近刚好在思考工作中统计数据所用的标识码产生的数据误差到底有多大,借此机会几番 ...

  7. 浅谈移动端 View 的显示过程

    作者:个推安卓开发工程师 一七 随着科技的发展,各种移动端早已成为人们日常生活中不可或缺的部分,人们使用移动端产品工作.社交.娱乐……移动端界面的流畅性已经成为影响用户体验的重要因素之一.那么你是否思 ...

  8. 浅谈移动端设备标识码:DeviceID、IMEI、IDFA、UDID和UUID -费元星

    在公司做数据分析的时候,发现NA端有很多ID,所有来系统的理解一下,有问题大家多指出   [心路历程] 最近刚好在思考工作中统计数据所用的标识码产生的数据误差到底有多大,借此机会几番搜索资料+请教大神 ...

  9. 干货|浅谈iOS端短视频SDK技术实现

    短视频SDK主要包含"视频录制"和"视频编辑"这两个核心功能. 视频录制包括:视频采集.美颜.滤镜.摄像头切换.视音频采集参数设置等功能: 视频编辑包括:视频导 ...

随机推荐

  1. LeetCode 108——将有序数组转化为二叉搜索树

    1. 题目 2. 解答 一棵高度平衡的二叉搜索树意味着根节点的左右子树包含相同数量的节点,也就是根节点为有序数组的中值. 因此,我们将数组的中值作为根节点,然后再递归分别得到左半部分数据转化的左子树和 ...

  2. Centos7 下nginx nginx-1.13.4 安装

    环境:CentOS Linux release 7.3.1611 (Core)  Linux localhost.localdomain 3.10.0-514.26.2.el7.x86_64 #1 S ...

  3. ptrdiff_t类型

    一.特性 1. 这是一种标准库类型 2. 是两个指针相减的结果的类型(因为差值可能为负值,所以是一种带符号类型) 3. 和size_t一样,ptrdiff_t也是一种定义在<cstddef> ...

  4. how to install pygraphviz on windows 10 with python 3.6

    Here's what worked for me: Win 7 AMD64 Install MSFT C++ compiler. Install Anaconda for Win AMD64, Py ...

  5. WPF+数据库+三层

    1.计算类 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespac ...

  6. ACM 第十天

    动态规划2 1.树形DP 2.概率DP 3.区间DP 模板 ; len < n; len++) { //操作区间的长度 , j = len; j <= n; i++, j++) { //始 ...

  7. (七)类、超类和子类 ——(多态,动态绑定,final类,类型转换,抽象类)

    java中所有的继承都是公有继承. 在子类中的构造其内可以初始化超类的公有域,但不能初始化超类的私有域. 因此需要在子类构造前的第一行使用super()语句初始化超类的私有域. 如果超类没有不带参数的 ...

  8. Debian常用設置

    1. 更新軟件源 sudo cp /etc/apt/sources.list /etc/apt/sources.list_bak #備份 sudo vi /etc/apt/sources.list / ...

  9. YaoLingJump开发者日志(二)

      熟悉了一点LGame里的套路,可以正式开工了.   增加了一个信息栏,显示得分.硬币数.生命值和当前关卡(仿照了超级玛丽的布局).   准备瑶玲的各种动画(静止.奔跑.跳跃.趴下.休息和死亡等). ...

  10. 使用 Python 操作 Git 版本库 - GitPython

    GitPython 是一个用于操作 Git 版本库的 python 包, 它提供了一系列的对象模型(库 - Repo.树 - Tree.提交 - Commit等) 用于操作版本库中的相应对象. 版本库 ...