简介

CSS 响应式布局学习笔记。

浏览器视口概念

1、理想视口:可视视口 = 布局视口
    视口设置:width = device-width

2、device-width = 设备物理分辨率 / (设备像素比 * 缩放比) = document.documentElement.clientWidth
当 设备像素比 * 缩放比 = 1 时, device-width = 设备物理分辨率(设计稿实际尺寸)

3、DPR(设备像素比) 可通过 window.devicePixelRatio 获取

响应式方案-rem

代码设置

! function(win) {
    var v, initial_scale, timeCode, dom = win.document,
        domEle = dom.documentElement,
        viewport = dom.querySelector('meta[name="viewport"]'),
        flexible = dom.querySelector('meta[name="flexible"]');
    if (viewport) {
        // == meta 标签有 viewport
        var o = viewport.getAttribute("content").match(/initial\-scale=(["']?)([\d\.]+)\1?/);
        if (o) {
            initial_scale = parseFloat(o[2]);
            v = parseInt(1 / initial_scale);
        }
    } else if (flexible) {
        // == meta 标签有 flexible
        var o = flexible.getAttribute("content").match(/initial\-dpr=(["']?)([\d\.]+)\1?/);
        if (o) {
            v = parseFloat(o[2]);
            initial_scale = parseFloat((1 / v).toFixed(2))
        }
    }
    // == meta 标签无 viewport 和 flexible: 设备像素比 * 缩放比 = 1
    if (!v && !initial_scale) {
        var n = (win.navigator.appVersion.match(/android/gi),
            win.navigator.appVersion.match(/iphone/gi));
        v = win.devicePixelRatio;
        v = n ? v >= 3 ? 3 : v >= 2 ? 2 : 1 : 1, initial_scale = 1 / v
    }
    // == meta 设置 viewport
    if (domEle.setAttribute("data-dpr", v), !viewport) {
        if (viewport = dom.createElement("meta"), viewport.setAttribute("name", "viewport"), viewport.setAttribute("content", "initial-scale=" + initial_scale + ", maximum-scale=" + initial_scale + ", minimum-scale=" + initial_scale + ", user-scalable=no"), domEle.firstElementChild) {
            domEle.firstElementChild.appendChild(viewport)
        } else {
            var m = dom.createElement("div");
            m.appendChild(viewport), dom.write(m.innerHTML)
        }
    }
    win.dpr = v;
    // == 动态设置 html 节点的 font-size
    function resize() {
        var domWidth = domEle.getBoundingClientRect().width;
        if (domWidth / v > 540) {
            domWidth = 540 * v;
        }
        win.rem = domWidth / 7.5;
        domEle.style.fontSize = win.rem + "px";
    }
    win.addEventListener("resize", function() {
        clearTimeout(timeCode), timeCode = setTimeout(resize, 300)
    }, false);
    win.addEventListener("pageshow", function(b) {
        b.persisted && (clearTimeout(timeCode), timeCode = setTimeout(resize, 300))
    }, false);
    resize();
}(window);

原理解析

当设计稿尺寸(设备物理分辨率)为 750px, 设备像素比 = 2, 缩放比 = 0.5 时;
则 device-width = 设备物理分辨率 = document.documentElement.clientWidth;

在 iPhone6 尺寸时, device-width / 7.5 = 100, 代表 1rem = 100px.
在 iPhone5 尺寸时, 640 / 7.5 = 85.34px, 代表 1rem = 85.34px.

响应式方案-flex

容器的属性

display:flex
flex-direction (默认为 row)
flex-wrap (默认为 no-wrap)
flex-flow
justify-content (默认为 flex-start)
align-items (默认为 stretch)
align-content

项目的属性

order (默认为 0)
flex-grow (默认为 0, 代表剩余空间不放大)
flex-shrink (默认为 1, 代表空间不足缩小)
flex-basis (默认为 auto, 代表项目原本大小)
flex (默认为 0 1 auto)
align-self

注意项

flex 为 none: 代表 0 0 auto;
flex 为 auto: 代表 1 1 auto;

flex 为一个非负数字: 代表 flex-grow 的值; 如 flex: 1 代表 flex: 1 1 0%
flex 为两个非负数字: 代表 flex-grow 和 flex-shrink 的值, flex-basis 为 0%

flex 为 px: 代表 flex-basis 的值; 如 flex: 10px 代表 flex: 1 1 10px;
flex 为  %: 代表 flex-basis 的值; 如 flex: 20% 代表 flex: 1 1 20%

flex 为一个非负数字和一个 px/%: 代表 flex-grow 和 flex-basis 的值, flex-shrink 为 1

注意:
1. 当 flex-basis 设置为 0% 时, 其声明的 width 即失效。
2. flex: 1 为什么会占满剩余全部: 其 flex-basis 为 0% , 则剩余空间 = 容器宽 - 其余项目 - 0%, 则剩余空间分配则会全部分给此 flex: 1 元素。

响应式方案-vw+vh

vw、vh概念

1. 1vw 等于1/100的视口宽度 (Viewport Width)
2. 1vh 等于1/100的视口高度 (Viewport Height)

综上,一个页面而言,它的视窗的高度就是 100vh,宽度就是 100vw 。

响应式web设计离不开百分比。但是,CSS百分比并不是所有的问题的最佳解决方案。
CSS的宽度是相对于包含它的最近的父元素的宽度的。
但是如果你就想用视口(viewpoint)的宽度或者高度,而不是父元素的,这时候 vh 和 vw 单位就方便很多了。

vmin、vmax概念

vh和 vw 依据于视口的高度和宽度,相对的,vmin 和 vmax则关于视口高度和宽度两者的最小或者最大值。

1. vmin — vmin的值是当前vw和vh中较小的值。
2. vmax — vw和vh中较大的值。

这个单位在横竖屏的切换中,十分有用。
在一些 Demo 示例,或者大页面中,我们经常都会看到上述 4 个单位的身影。灵活使用,就可以减少很多 CSS 的代码量。

响应式方案-grid

grid 布局实战

grid 布局项目中使用的比较少,就不班门弄斧了。
这里有我自己写的一个案例: 横坐标是 12 个月, 每个月 4个星期; 纵坐标每个星期的 7 天。动态生成每个方格的颜色。
地址: https://github.com/yunaichun/animation-study/tree/master/Layout/5

参考资料

powered by Gitbook该文件修订时间: 2023-05-16 18:08:03

results matching ""

    No results matching ""