移动端页面之 viewport 和 rem 布局

viewport

viewport 是用户网页的可视区域。viewport 翻译为中文可以叫做「视区」

手机浏览器是把页面放在一个虚拟的「窗口」(viewport)中,通常这个虚拟的「窗口」(viewport)比屏幕宽,这样就不用把每个网页挤到很小的窗口中(这样会破坏没有针对手机浏览器优化的网页的布局),用户可以通过平移和缩放来看网页的不同部分。

viewport 设置例子
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
    <title></title>
    <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
	<meta name="viewport" content="width=device-width,initial-scale=1.5,minimum-scale=1,maximum-scale=2,user-scalable=no" />
	<!--<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>-->
	<style>
		div {
			width: 100px;
			height: 100px;
			background-color: red;
		}
	</style>
</head>
<body>
	<div></div>
</body>
</html>
一般常用 viewport 设置
<meta name="viewport" content="width=device-width, initial-scale=1.0">

viewport 属性说明

  • width:控制 viewport 的大小,可以指定的一个值,如果 600,或者特殊的值,如 device-width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。
  • height:和 width 相对应,指定高度。
  • initial-scale:初始缩放比例,也即是当页面第一次加载的时候缩放比例。
  • maximum-scale:允许用户缩放到的最大比例。
  • minimum-scale:允许用户缩放到的最小比例。
  • user-scalable:用户是否可以手动缩放。

另外 Apple 在 iOS 10 中为了提高Safari中网站的辅助功能屏蔽了「user-scalable:no」功能,即设置了「user-scalable:no」用户也可以手动缩放,但可以通过 JS 添加监听事件解决:

解决 iOS 10 无法使用 user-scalable:no
window.onload = function () {
    document.addEventListener('touchstart', function (event) {
        if (event.touches.length > 1) {
            event.preventDefault();
        }
    })
    var lastTouchEnd = 0;
    document.addEventListener('touchend', function (event) {
        var now = (new Date()).getTime();
        if (now - lastTouchEnd <= 300) {
            event.preventDefault();
        }
        lastTouchEnd = now;
    }, false)
}

像素密度

像素密度

resolution 表示设备的像素密度,或者叫屏幕密度,它表示在一个物理尺寸上面所能显示的像素的数量,一般我们会用 dpi 这个单位来表示像素密度 ,dpi 是 dots per inch 的简写形式,也就是每英寸的点数,或者叫每英寸的像素数 。

不同的设备的屏幕密度是不一样的,比如 iPhone 3G 的屏幕密度是 162 dpi,屏幕的分辨率在垂直方向的时候,宽是 320px,高是 480px。到了 iPhone 4 的时候,屏幕密度就变成了 326 dpi,差不多是 iPhone 3G 屏幕密度的一倍,因为密度变大了,所以它能显示的像素数也会变大,iPhone 4 的屏幕分辨率在垂直方向的时候,宽是 640px,高是 960px ,比 iPhone 3G 扩大了一倍。因为 iPhone 3G 和 iPhone 4 的屏幕都是 3.5 寸,所以更大的屏幕密度,可以使用更多的像素来显示元素的细节,比如文字,在高密度的设备上,会显示的更清晰。苹果为这种高密度的屏幕起了个名字,叫 Retina 视网膜屏幕。

CSS 像素

CSS 像素是一个相对的值,比如要显示一个设置好的 10px × 10px 的 div,这个 div 如果在 iPhone 3G 上显示便是一个 10px × 10px 的 div,但在 iPhone 4 上显示这个 div,CSS 像素就会变成为 20px × 20px,否则因为 iPhone 4 像素密度比较高,div 显示看起来会比 iPhone 3G 上面缩小一倍,所以为了保持元素显示的一致性,高密度设备会自动放大元素。

另外不同设备的像素比是不同的,如电脑上 1080P 全高清屏在 Windows 10 下默认设置是以 125% 的 dpi 设置,像素比即 1.25倍,所以在开发时可以通过按住 Ctrl 键加上鼠标滚轮让页面缩放比例改为 80% 即可正常显示。

可以在 Screen Sizes > 上查询不同设备关于屏幕尺寸的信息。

获取当前设备的像素比
alert( window.devicePixelRatio )

rem 布局

如上所述近年来 px 单位在移动设备上的混乱情况,开发移动端页面时使用 px 会有很多的坑,所以开始转向使用其他的单位。

在 CSS 中,相对单位定义的大小是不固定的,一般是相对其他长度而言。

em 和 rem

在 CSS 中, em 是相对于“当前元素” 的字体大小而言的。其中, 1em 等于“当前元素” 字体大小。这里的字体大小指的是以 px 为单位的 font-size 值。例如,当前元素的 font-size 值为 10px,则 1em 等于 10px ;当前元素的 font-size 值为 20px,则 1em 等于 20px,以此类推。此外需要注意一下,如果当前元素的 font-size 没有定义,则当前元素会继承父元素的 font-size。如果当前元素的所有祖先元素都没有定义 fontsize,则当前元素会继承浏览器默认的 font-size。

em 使用技巧

text-indent
如 font-size: 12px,那么使用此时如果我们想设置首行缩进两个字符就可以灵活的时候 text-indent: 2em;

统一单位
大多数浏览器的默认字体大小为 16px,如下例子通过 16px × 62.5% = 10px 将浏览器默认字体大小设置为{body:62.5%},那么 1rem = 10px

此时只要将我们原先设置好的 px 值除以 10 就可以得到对应的 rem 值,是很方便的技巧,但是问题又来了,em 单位是基于当前元素的 font-size 进行计算

如上例子,那么 p 的宽度就需要这么计算:

宽度除以当前元素字体大小(150px ÷ 15px = 10rem)

这时问题就显现了,如果页面过于复杂那么计算起来是十分麻烦的,这时候 rem 来了。

rem

rem 是相对于 HTML 根节点字体大小进行计算,解决了 em 仅相当于当前元素字体大小计算带来的开发不便的问题。

动态设置及 rem 的一种使用方法
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <!--<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=0.5,minimum-scale=0.5,maximum-scale=0.5"/>-->
    <title></title>
    <!--生成meta标签-->
    <script>
        //		创建一个meta标签
        var meta = document.createElement("meta");
        //		设置name,配置的是视口
        meta.name = "viewport";
        //		设置视口的具体参数值

        //		获取像素比
        var ra = window.devicePixelRatio;
        //		alert( ra );
        var scale = (1 / ra).toFixed(1);

        meta.content = "width=device-width,user-scalable=no,initial-scale=" + scale + ",minimum-scale=" + scale + ",maximum-scale=" + scale;

        //		把创建好的meta放到head标签中
        document.head.appendChild(meta);
    </script>

    <!--计算根节点字体大小-->
    <script>
        (function () {
            var html = document.documentElement;
            var htmlWidth = html.getBoundingClientRect().width;
            html.style.fontSize = htmlWidth / 16 + "px";
        })()
    </script>
    <style>
        div {
            width: 8rem;
            height: 8rem;
            /*width: 320px;
			height: 320px;*/
            background-color: red;
            border: 1px solid #000;
        }
    </style>
</head>

<body>
    <div></div>
</body>

</html>

如上例子,假设我们拿到一张 640px 的开发效果图,那么就假设以 640px 的屏幕宽度进行开发,已知默认大多数浏览器默认字体大小为 16px,那么我们计算到的 HTML 根节点字体大小为 40px。

那么如上图我们需要显示一个长宽为 320 px 的 div 时只要将 320px ÷ 40px = 8rem

 

参考来源

响应式网页设计 >

disable viewport zooming iOS 10 safari? >

Conners Hua

欢迎入群讨论:Telegram >QQ群 42302626 >(不交流不和谐话题)

发表评论

电子邮件地址不会被公开。