响应式布局方案

栏目: CSS · 发布时间: 5年前

内容简介:说到响应式布局方案,我们首先需要了解视口这个概念在早期的时候我们没有专门针对手机尺寸写的页面,所以在用手机浏览页面的时候我们看到的都是专门针对PC端的页面,在这种情况下页面会被严重压缩,而且会极大的影响页面的结构和布局,为了解决这个 问题,苹果公司提出了视口的概念,因为我们早期的PC端的页面的版心一般是960px,为了容纳这个页面,我们在手机建立一个虚拟的区域,大小一般为980px,来容纳PC的页面,以方便用户来浏览页面但是在如今移动端快速发展的时候,我们有了专门针对手机屏幕尺寸的的移动端页面,所以在写移动

说到响应式布局方案,我们首先需要了解视口这个概念

视口

在早期的时候我们没有专门针对手机尺寸写的页面,所以在用手机浏览页面的时候我们看到的都是专门针对PC端的页面,在这种情况下页面会被严重压缩,而且会极大的影响页面的结构和布局,为了解决这个 问题,苹果公司提出了视口的概念,因为我们早期的PC端的页面的版心一般是960px,为了容纳这个页面,我们在手机建立一个虚拟的区域,大小一般为980px,来容纳PC的页面,以方便用户来浏览页面

但是在如今移动端快速发展的时候,我们有了专门针对手机屏幕尺寸的的移动端页面,所以在写移动端的页面的时候我们需要调整视口的宽度,保证页面内容会在手机屏幕尺寸大小的页面上进行展示

<!--告诉浏览器如何调整设备的视口大小-->
<meta name="viewport" content="width=device-width ,initial-scale=1.0,user-scalable=no,maximun-scale=1.0,minimum-scale=1.0">
<meta name="viewport">
 <!--告诉浏览器根据当前设备的尺寸调整视口的大小-->
<meta name="viewport" content="width=device-width">
<!--初始缩放比例为1 ,该声明和width是同样的效果,但是为了保证所有的浏览器都能兼容,所以我们都会写-->
<meta name="viewport" content="initial-scale=1.0"> 
 <!--设置用户不可以对页面大小进行缩放-->
<meta name="viewport" content="user-scalbale-no">
<meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0">

媒体查询

媒体类型

媒体查询可以为不同的设备规定不同的样式,常用的一般有三种设备 screen(计算机屏幕,该值是默认值)、print(打印预览)、all(所有设备)

@media screen

媒体属性

媒体属性用来规定在指定的符合某些条件的情况下为指定的元素设置样式,需要注意媒体属性必须用 () 包起来,否则无效,常用的媒体属性有

width 可视区域宽度,取值格式为指定宽度或者范围,如 @media (width: 900px){ }

height 可视区域高度,取值格式为指定宽度或者范围,如 @media (max-height: 900px){ }

device-width 设备宽度,取值格式为指定宽度或者范围,如 @media (max-device-width: 5000px) { }

device-height 设备高度 取值格式为指定宽度或者范围,如 @media (max-device-height: 5000px) { }

orientation 设备是竖屏还是横屏模式,可选值有landscape(横屏)、portrait(竖屏),如 @media (orientation: landscape) { }

aspect-ratio 可视区域宽高比,取值格式为水平像素/垂直像素,如@media (device-aspect-ratio:16/9) { }

device-aspect-ratio 设备宽高比,取值格式为水平像素/垂直像素,如@media (device-aspect-ratio:16/9) { }

例如我们要针对某个设备的 body 在横屏时设置的背景颜色是黑色,在竖屏的时候背景是白色,那么可以使用以下写法

html, body {
    height: 100%;
    }
@media  (orientation: landscape) {
    body{
        background-color:#000;
    }
}
@media  (orientation: portrait) {
    body{
        background-color:#fff;
    }
}

逻辑操作符

媒体查询可以使用三种操作符,通过操作符配合媒体属性来判断是否载入媒体属性下的样式表

&
||

配合逻辑操作符设置设备在可视窗口大小变化时背景颜色发生改变

html,body{
    height: 100%;
}
    
@media screen and (max-width: 500px ){<!--在屏幕尺寸小于500px时body背景颜色为skyblue-->
    body{
        background-color: skyblue;
    }
}
@media screen and (min-width: 501px) and (max-width: 800px){<!--在屏幕尺寸为501-800px时,背景颜色为灰色-->
    body{
        background-color: #ccc;
    }
}
@media screen and (min-width: 900px){<!--在屏幕尺寸为900px以上时,body背景颜色为yellowgreen-->
    body{
        background-color: yellowgreen;
    }
}

vw、vh布局方案

在CSS3规范中引入了 vwvh 单位,分别将视口划分为100份,一个vw单位相当于视口宽度的1%,一个vh相当于视口高度的1%,需要注意的是不同于百分比的布局方案,vw和vh不受父元素宽高的影响,只由视口的大小决定

同时还有两个单位 vmaxvmin , vmax 表示取视口宽度和高度中比较大的值,将其等分为100份, vmin 表示取比较小的值,将其等分为100份

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <style>
        .box{
            width: 100vmin;
            height: 100vmax;
            background-color:deepskyblue;
        }
        .box div{
            width: 50vh;
            height: 50vw;
            background-color: mediumseagreen;
        }
    </style>
    <title>vw、vh</title>
</head>
<body>
<div class="box">
    <div/>
</div>
</body>
</html>

目前浏览器的支持情况

响应式布局方案

rem布局

rem是css中的一个单位,是根据根字体大小来设定的,也就是html的font-size

在正常的UI设计稿件的时候一般设置大小为640/750px大小,我们一般选择将稿件等分为20份(20份在设备大小和稿件大小一般可以除尽,我们尽量避免出现小数)

那么如果UI稿件为640px大小,每一份的大小为32px,假设UI稿件上有一个160*160大小的元素,那么该元素占整个页面的160/32份

同时我们也将屏幕分为20份,以Iphon为例(屏幕大小为320px),那么每份大小为16px,我们通过媒体查询将html根字体大小设置为16px,那么在UI稿件上160px大小的元素在Iphon5上的实际大小为160/32 rem,那么通过这个公式我们就可以通过JavaScript设置不同的根节点字体大小来进行适配

我们来写一个简单的例子

(function (doc, win) {
       var docEl = doc.documentElement,
/*
          document.documentElement
          返回文档的根节点
        * orientationchange 在用户移动端设备屏幕垂直或水平旋转移动设备时被触发
        * resize 事件,在绑定元素大小发生变化时触发该事件,例如检测屏幕变化:
        * window.addEventLisenter("resize",function(){
        *      alert("屏幕大小变化了")
        * })
        *
        * resize 属性,css3新增属性,用来指定用户是否可以缩放该元素
        * none:用户无法调整该元素尺寸
        * both:用户可以调整元素的高度和宽度
        * horizontal:用户可调整元素的宽度
        * vertical:用户可调整元素的宽度
        * */
           resizeEvt = "orientationchange" in window ? "orientationchange" : "resize",
           recalc = function () {
               var clientWidth = docEl.clientWidth;
               if (clientWidth >= 640) {
                   clientWidth = 640
               }
               if (!clientWidth) return;

               docEl.body.style.fontSize = (clientWidth / 640) * 100 + "px";
           };
       win.addEventListener("resizeEvt", recalc, false);
/*
         * DOMContentLoaded 该事件会在load事件之前触发,在DOM树构建完成时就触发
         * 而load事件则是在DOMContentLoaded事件触发之后,继续加载图片等外部文件完成后触发
         * */
       doc.addEventListener("DOMContentLoaded", recalc, false)
   })(document, window)

之前一直在使用手淘的rem布局方案,可以大概看一下源码

;(function(win, lib) {
    var doc = win.document;
    var docEl = doc.documentElement;
    var metaEl = doc.querySelector('meta[name="viewport"]');
    var flexibleEl = doc.querySelector('meta[name="flexible"]');
    var dpr = 0;
    var scale = 0;
    var tid;
 
    var flexible = lib.flexible || (lib.flexible = {});

    if (metaEl) {
        console.warn('将根据已有的meta标签来设置缩放比例');
        //获取初始缩放比例
        var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
        if (match) {
            scale = parseFloat(match[1]); //取整
            dpr = parseInt(1 / scale); //1
        }
    } else if (flexibleEl) {
        var content = flexibleEl.getAttribute('content');
        if (content) {
            var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
            var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
            if (initialDpr) {
                dpr = parseFloat(initialDpr[1]);
                scale = parseFloat((1 / dpr).toFixed(2));
            }
            if (maximumDpr) {
                dpr = parseFloat(maximumDpr[1]);
                scale = parseFloat((1 / dpr).toFixed(2));
            }
        }
    }

    if (!dpr && !scale) {
        //检测的当前设备的版本
        var isAndroid = win.navigator.appVersion.match(/android/gi);
        var isIPhone = win.navigator.appVersion.match(/iphone/gi);
        //window.devicePixelRatio 该属性返回当前显示设备的物理像素分辨率与css像素分辨率的比值,该值也可以被解释为像素大小的比例
        //简单来说就是一个css像素的大象相对于一个物理像素大小的比值
        //可以通过重写window.devicePixelRatio来更改此属性,例如window.devicePixelRatio=2;
        //dpr css/物理 比例
        //scale 缩放比例
        var devicePixelRatio = win.devicePixelRatio;
        if (isIPhone) {
            // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
            if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
                dpr = 3;
            } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
                dpr = 2;
            } else {
                dpr = 1;
            }
        } else {
            // 其他设备下,仍旧使用1倍的方案
            dpr = 1;
        }
        scale = 1 / dpr;
    }

    docEl.setAttribute('data-dpr', dpr);
    //判断页面是否存在 metaEl
    if (!metaEl) {
        metaEl = doc.createElement('meta');
        metaEl.setAttribute('name', 'viewport');
        metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
        if (docEl.firstElementChild) {
            docEl.firstElementChild.appendChild(metaEl);
        } else {
            var wrap = doc.createElement('div');
            wrap.appendChild(metaEl);
            doc.write(wrap.innerHTML);
        }
    }

    function refreshRem(){
        var width = docEl.getBoundingClientRect().width;
        //getBoundingClientRect
        //返回一个DOMRect对象,包含一组矩形的集合,该集合内是与该元素相关的css边框集合
        /*
        * DOMRect
        * bottom:8
        * height:8
        * left:0
        * right:520
        * top:0
        * width:520
        * x:0
        * y:0
        * */
        if (width / dpr > 540) {
            width = 540 * dpr;
        }
        //阿里的布局方案默认将屏幕分成十份,当然,如果愿意我们可以对其进行更改
        var rem = width / 10;
        docEl.style.fontSize = rem + 'px';
        flexible.rem = win.rem = rem;
    }
    // resize 在设备宽度发生改变时触发
    win.addEventListener('resize', function() {
        clearTimeout(tid);
        tid = setTimeout(refreshRem, 300);
    }, false);
    //pageshow firefox/open的一个事件,在chrome中不会触发
    //在页面后退时静态资源会直接重缓存中读取
    win.addEventListener('pageshow', function(e) {
        if (e.persisted) {
            clearTimeout(tid);
            tid = setTimeout(refreshRem, 300);
        }
    }, false);
    //document.readyState 描述文档的加载状态
    /*
    * loding 文档仍然在加载中
    * interactive 文档已经加载完成并已经被解析,但是图像,框架之类的资源仍然在加载中
    * complete 说有资源都已经加载完成,load事件即将被触发
    * 在状态改变时document.readyState事件将被触发
    * */
    if (doc.readyState === 'complete') {
        doc.body.style.fontSize = 12 * dpr + 'px';
    } else {
        //DOMContentLoaded 在文档加载完成后触发,不会等待图像,框架等资源,参考$(function(){}) / $.ready()
        doc.addEventListener('DOMContentLoaded', function(e) {
            doc.body.style.fontSize = 12 * dpr + 'px';
        }, false);
    }


    refreshRem();

    flexible.dpr = win.dpr = dpr;
    flexible.refreshRem = refreshRem;
    //rem 2 px  转化方法
    flexible.rem2px = function(d) {
        var val = parseFloat(d) * this.rem;
        if (typeof d === 'string' && d.match(/rem$/)) {
            val += 'px';
        }
        return val;
    }
    //px 2 rem  转化方法
    flexible.px2rem = function(d) {
        var val = parseFloat(d) / this.rem;
        if (typeof d === 'string' && d.match(/px$/)) {
            val += 'rem';
        }
        return val;
    }

})(window, window['lib'] || (window['lib'] = {}));

阿里的布局方法主要是通过dpr来设置不同屏幕下的不同比例关系,具体的关于dpr的解释可以看下面这篇文章

移动web开发之像素和DPR


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Data-intensive Text Processing With Mapreduce

Data-intensive Text Processing With Mapreduce

Jimmy Lin、Chris Dyer / Morgan and Claypool Publishers / 2010-4-30 / USD 40.00

Our world is being revolutionized by data-driven methods: access to large amounts of data has generated new insights and opened exciting new opportunities in commerce, science, and computing applicati......一起来看看 《Data-intensive Text Processing With Mapreduce》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具