zoukankan      html  css  js  c++  java
  • HTML

    HTML网页样式根据手机分辨率自适应

    转自:https://blog.csdn.net/u010071211/article/details/80474286

    问题:不同手机型号屏幕尺寸大不相同,导致同样的文字,有的显示一行,有的显示多行。

    通过查资料和自己的尝试解决;网页开发习惯的px单位,手机html开发不适用

    源代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <!--防止手机页面缩放-->
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
        <title>Document</title>
    </head>
    <body>
    <!-- 文字单位设置为rem即可,通过微信开发者工具切换手机型号查看效果。 -->
    <div style='border:1px red solid;border-radius:100px;font-size:1rem;'>测试手机端文字的自适应</div>
    </body>
    <script>
        /*    利用js计算当前设备的DPR,动态设置在html标签上,并动态设置html的font-size,*/
        !function (win, lib) {
            var timer,
                doc = win.document,
                docElem = doc.documentElement,
    
                vpMeta = doc.querySelector('meta[name="viewport"]'),
                flexMeta = doc.querySelector('meta[name="flexible"]'),
    
                dpr = 0,
                scale = 0,
    
                flexible = lib.flexible || (lib.flexible = {});
    
            // 设置了 viewport meta
            if (vpMeta) {
                console.warn("将根据已有的meta标签来设置缩放比例");
                var initial = vpMeta.getAttribute("content").match(/initial-scale=([d.]+)/);
    
                if (initial) {
                    scale = parseFloat(initial[1]); // 已设置的 initialScale
                    dpr = parseInt(1 / scale);      // 设备像素比 devicePixelRatio
                }
    
            }
            // 设置了 flexible Meta
            else if (flexMeta) {
                var flexMetaContent = flexMeta.getAttribute("content");
                if (flexMetaContent) {
    
                    var initial = flexMetaContent.match(/initial-dpr=([d.]+)/),
                        maximum = flexMetaContent.match(/maximum-dpr=([d.]+)/);
    
                    if (initial) {
                        dpr = parseFloat(initial[1]);
                        scale = parseFloat((1 / dpr).toFixed(2));
                    }
    
                    if (maximum) {
                        dpr = parseFloat(maximum[1]);
                        scale = parseFloat((1 / dpr).toFixed(2));
                    }
                }
            }
    
            // viewport 或 flexible
            // meta 均未设置
            if (!dpr && !scale) {
                // QST
                // 这里的 第一句有什么用 ?
                // 和 Android 有毛关系 ?
                var u = (win.navigator.appVersion.match(/android/gi), win.navigator.appVersion.match(/iphone/gi)),
                    _dpr = win.devicePixelRatio;
    
                // 所以这里似乎是将所有 Android 设备都设置为 1 了
                dpr = u ? ((_dpr >= 3 && (!dpr || dpr >= 3))
                        ? 3
                        : (_dpr >= 2 && (!dpr || dpr >= 2))
                            ? 2
                            : 1
                    )
                    : 1;
    
                scale = 1 / dpr;
            }
    
            docElem.setAttribute("data-dpr", dpr);
    
            // 插入 viewport meta
            if (!vpMeta) {
                vpMeta = doc.createElement("meta");
    
                vpMeta.setAttribute("name", "viewport");
                vpMeta.setAttribute("content",
                    "initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no");
    
                if (docElem.firstElementChild) {
                    docElem.firstElementChild.appendChild(vpMeta)
                } else {
                    var div = doc.createElement("div");
                    div.appendChild(vpMeta);
                    doc.write(div.innerHTML);
                }
            }
    
            function setFontSize() {
                var winWidth = docElem.getBoundingClientRect().width;
    
                if (winWidth / dpr > 540) {
                    (winWidth = 540 * dpr);
                }
    
                // 根节点 fontSize 根据宽度决定
                var baseSize = winWidth / 10;
    
                docElem.style.fontSize = baseSize + "px";
                flexible.rem = win.rem = baseSize;
            }
    
            // 调整窗口时重置
            win.addEventListener("resize", function () {
                clearTimeout(timer);
                timer = setTimeout(setFontSize, 300);
            }, false);
    
    
            // 这一段是我自己加的
            // orientationchange 时也需要重算下吧
            win.addEventListener("orientationchange", function () {
                clearTimeout(timer);
                timer = setTimeout(setFontSize, 300);
            }, false);
    
    
            // pageshow
            // keyword: 倒退 缓存相关
            win.addEventListener("pageshow", function (e) {
                if (e.persisted) {
                    clearTimeout(timer);
                    timer = setTimeout(setFontSize, 300);
                }
            }, false);
    
            // 设置基准字体
            if ("complete" === doc.readyState) {
                doc.body.style.fontSize = 12 * dpr + "px";
            } else {
                doc.addEventListener("DOMContentLoaded", function () {
                    doc.body.style.fontSize = 12 * dpr + "px";
                }, false);
            }
    
            setFontSize();
    
            flexible.dpr = win.dpr = dpr;
    
            flexible.refreshRem = setFontSize;
    
            flexible.rem2px = function (d) {
                var c = parseFloat(d) * this.rem;
                if ("string" == typeof d && d.match(/rem$/)) {
                    c += "px";
                }
                return c;
            };
    
            flexible.px2rem = function (d) {
                var c = parseFloat(d) / this.rem;
    
                if ("string" == typeof d && d.match(/px$/)) {
                    c += "rem";
                }
                return c;
            }
        }(window, window.lib || (window.lib = {}));
    </script>
    </html>

    扩展:

    viewport

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

    物理像素(physical pixel)

    物理像素又被称为设备像素,他是显示设备中一个最微小的物理部件。每个像素可以根据操作系统设置自己的颜色和亮度。正是这些设备像素的微小距离欺骗了我们肉眼看到的图像效果。

    设备独立像素(density-independent pixel)

    设备独立像素也称为密度无关像素,可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素(比如说CSS像素),然后由相关系统转换为物理像素。

    CSS像素

    CSS像素是一个抽像的单位,主要使用在浏览器上,用来精确度量Web页面上的内容。一般情况之下,CSS像素称为与设备无关的像素(device-independent pixel),简称DIPs。

    屏幕密度

    屏幕密度是指一个设备表面上存在的像素数量,它通常以每英寸有多少像素来计算(PPI)。

    设备像素比(device pixel ratio)

    设备像素比简称为dpr,其定义了物理像素和设备独立像素的对应关系。它的值可以按下面的公式计算得到:

    设备像素比 = 物理像素 / 设备独立像素

    在JavaScript中,可以通过window.devicePixelRatio获取到当前设备的dpr。而在CSS中,可以通过-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio进行媒体查询,对不同dpr的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)。

    dip或dp,(device independent pixels,设备独立像素)与屏幕密度有关。dip可以用来辅助区分视网膜设备还是非视网膜设备。

    众所周知,iPhone6的设备宽度和高度为375pt * 667pt,可以理解为设备的独立像素;而其dpr为2,根据上面公式,我们可以很轻松得知其物理像素为750pt * 1334pt。

    如下图所示,某元素的CSS样式:

     2px;
    height: 2px;

    在不同的屏幕上,CSS像素所呈现的物理尺寸是一致的,而不同的是CSS像素所对应的物理像素具数是不一致的。在普通屏幕下1个CSS像素对应1个物理像素,而在Retina屏幕下,1个CSS像素对应的却是4个物理像素。

    meta标签

    <meta>标签有很多种,而这里要着重说的是viewport的meta标签,其主要用来告诉浏览器如何规范的渲染Web页面,而你则需要告诉它视窗有多大。在开发移动端页面,我们需要设置meta标签如下:

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

    代码以显示网页的屏幕宽度定义了视窗宽度。网页的比例和最大比例被设置为100%。

    CSS单位rem

    rem就是相对于根元素<html>的font-size来做计算。而我们的方案中使用rem单位,是能轻易的根据<html>的font-size计算出元素的盒模型大小。而这个特色对我们来说是特别的有益处。

  • 相关阅读:
    判断回溯法中的标记数组vis在回溯的时候是否要取消标记?
    Linux多线程开发I
    答题小程序开发
    答题活动小程序
    今天来谈谈答题小程序的上下游生态
    挑战答题小程序V2.0
    可以免费出题的答题小程序
    挑战答题小程序上线了
    通过小程序反编译来谈谈小程序的分包加载机制?
    本文介绍下答题小程序V6.0
  • 原文地址:https://www.cnblogs.com/helios-fz/p/13065402.html
Copyright © 2011-2022 走看看