zhilizhili-ui 荡平ie8910 还我前端清净地

zhilizhili-ui 给大家带来一个目前最新版本的ie8方案

特色

  • flexbox部分功能

  • vw

  • vh

  • calc部分功能

  • angular1.4

todo

avalon是因为无法和polyfill.js和谐共处 无法使用flexbox 真可惜

webcomponent 无法在ie8 ie9上使用 也就无法解决这些问题了 不过cordova解决方案里会有

flexbox

flexbox 我使用的是 flexibility.js github地址 作为兼容方案
那么作为一款快速开发的方案 emmet 解决方案也是会有的

我举个例子

如果想要使用一个flex row layout
就可以直接在sublime中输入zen-flex-row 变成预设语句 .layout.flex.horizontal>.layout__item*
再变成相应html代码
webcomponents 版本不太一样 具体之后文章给出方案

注意

不过注意的是flexibility 无法正确计算外部长度
justify-content 全部属性可以通过测试

为什么没撑满 因为设置了高度
ie8 ie9测试截图 一样效果 不重复截图
zhilizhili-ui 荡平ie8910 还我前端清净地_第1张图片

align-items 全部属性可以测试通过
zhilizhili-ui 荡平ie8910 还我前端清净地_第2张图片

这里再说一下 一个注意点 flex布局item是height撑满的 不是100% 注意效果一样而已 如果你对item设置过高度就会按你设置的高度计算 就算align-items:stretch没用

vw vh

其实后来我发现 我实现的和vw vh写法上有些不同 不过标准写法 也会实现的
这里我要说说设计师 和 前端之间的配合问题

通常 我们在写pc端响应式布局的时候 都喜欢确认一个基准布局 比如1920 高度在pc端不定 其实没啥说的 我个人也不推荐vh 不过还是要支持的

早期固定式设计 大家都喜欢一种960的布局 大家都懂就不上图了
为什么是960呢 因为这时候的屏幕都在1024 1366左右
后来 1920 出现了 就这样
zhilizhili-ui 荡平ie8910 还我前端清净地_第3张图片

然后你的老板看到了
zhilizhili-ui 荡平ie8910 还我前端清净地_第4张图片

所以这时候一般设计师就改成了这样 通常是1200 为什么是1200 因为还有1440这种屏幕啊
zhilizhili-ui 荡平ie8910 还我前端清净地_第5张图片

这时候大家通常的做法是单独的写一套css 最后在分析分析将 重复可以利用的提取出来

这是正确的 不过我要说的是 对于这样的web app呢 是否有种哭的感动 不要说用100% 一路继承下去 烦死了
zhilizhili-ui 荡平ie8910 还我前端清净地_第6张图片

通常这里有两种做法rem vw 不过vw更简单些 另外可能很多能人没有注意到 bootstrap 很早就提供了一个
zhilizhili-ui 荡平ie8910 还我前端清净地_第7张图片

这个我以后说到手机端优化布局的时候会说

media 这个的确就是在特定条件下触发 用于更换样式
不过rem vw这类单位可以无损适应屏幕拉伸 变大 rem要做点兼容 也是可以的

media query是用来做断点查询的 这点很重要

pc端vw大概是个什么样子
zhilizhili-ui 荡平ie8910 还我前端清净地_第8张图片

ie8浏览器在放大时候会有4px的边 所以最大化时会有些差异

如何去实现ie8下的vw支持了 首先要获取屏幕的宽高
不过值得注意的是首先要收集到浏览器的滚动条宽度

当body元素未加载时加入

window.documentElementclientWidthWithScrollBar = document.documentElement.clientWidth;

当body元素加载完成时 document的宽度会有所改变 body和html都为100%的宽度
这就说明不会含有滚动条宽度 所以在pc端vw和100%效果是不太一样的 这个我后面会统一一个dw单位

window.scrollBarWidth = window.documentElementclientWidthWithScrollBar - document.documentElement.clientWidth;

后面我们就可以得到滚动条的宽度

要说这个实现的方法 我们要用sass或者postcss之类样式预处理工具

首先说说页面上js和css的如何通讯 首先我们确定一下通讯格式 json
sass 可以讲map变成json SassyJSON github链接

然后如何将字符串放置到页面上呢 我们知道浏览器在分析css时会把一些不合法的属性给扔掉
不过有哪两个属性例外 content font-family 其中font-family兼容性最好

这时候我们在页面上部署一个meta标签

head里的标签也可以接受font-family属性

var content = window.getComputedStyle(
    document.querySelector('meta[name="support-vw-vh"]')
).fontFamily.replace(/\\/g, "").replace(/'/g, '')
content = content.slice(1, content.length - 1);

var parseobj = {};

try {
    parseobj = new Function('return (' + content + ');')();
} catch (e) {
    console.log("vw vh:没有什么要兼容的 intersting");
    return false;
}

使用getComputedStyle可以得到标签解析后的style 不过要恢复转义

ie8没有getComputedStyle 所以我们要自己写

!('getComputedStyle' in this) && (this.getComputedStyle = (function () {
    function getPixelSize(element, style, property, fontSize) {
        var
            sizeWithSuffix = style[property],
            size = parseFloat(sizeWithSuffix),
            suffix = sizeWithSuffix.split(/\d/)[0],
            rootSize;

        fontSize = fontSize != null ? fontSize : /%|em/.test(suffix) && element.parentElement ? getPixelSize(element.parentElement, element.parentElement.currentStyle, 'fontSize', null) : 16;
        rootSize = property == 'fontSize' ? fontSize : /width/i.test(property) ? element.clientWidth : element.clientHeight;

        return (suffix == 'em') ? size * fontSize : (suffix == 'in') ? size * 96 : (suffix == 'pt') ? size * 96 / 72 : (suffix == '%') ? size / 100 * rootSize : size;
    }

    function setShortStyleProperty(style, property) {
        var
            borderSuffix = property == 'border' ? 'Width' : '',
            t = property + 'Top' + borderSuffix,
            r = property + 'Right' + borderSuffix,
            b = property + 'Bottom' + borderSuffix,
            l = property + 'Left' + borderSuffix;

        style[property] = (style[t] == style[r] == style[b] == style[l] ? [style[t]]
            : style[t] == style[b] && style[l] == style[r] ? [style[t], style[r]]
            : style[l] == style[r] ? [style[t], style[r], style[b]]
            : [style[t], style[r], style[b], style[l]]).join(' ');
    }

    function CSSStyleDeclaration(element) {
        var
            currentStyle = element.currentStyle,
            style = this,
            fontSize = getPixelSize(element, currentStyle, 'fontSize', null);

        for (property in currentStyle) {
            if (/width|height|margin.|padding.|border.+W/.test(property) && style[property] !== 'auto') {
                style[property] = getPixelSize(element, currentStyle, property, fontSize) + 'px';
            } else if (property === 'styleFloat') {
                style['float'] = currentStyle[property];
            } else {
                style[property] = currentStyle[property];
            }
        }

        setShortStyleProperty(style, 'margin');
        setShortStyleProperty(style, 'padding');
        setShortStyleProperty(style, 'border');

        style.fontSize = fontSize + 'px';

        return style;
    }

    CSSStyleDeclaration.prototype = {
        constructor: CSSStyleDeclaration,
        getPropertyPriority: function () {},
        getPropertyValue: function ( prop ) {
            return this[prop] || '';
        },
        item: function () {},
        removeProperty: function () {},
        setProperty: function () {},
        getPropertyCSSValue: function () {}
    };

    function getComputedStyle(element) {
        return new CSSStyleDeclaration(element);
    }

    return getComputedStyle;
})(this));

核心算法如下 具体是什么 我项目里看就是了

    function cal(propval) {
        if (typeof propval != "string") {
            return propval;
        }

        if (propval.indexOf('vw') > -1) {
            return viewportwidth * rel(propval, "vw") / 100 + "px";
        } else if (propval.indexOf('vh') > -1) {
            return viewportheight * rel(propval, "vh") / 100 + "px";
        } else {
            return propval;
        }
    }

如何找到我们放置的style呢 首先是不可以通过document.styleSheets[index]方式直接获取的
因为你无法知道她在页面中处于styleSheets哪个部分 那么可以写innerHTML吗 ie8不支持head中style写innerHTML ie的CSSStyleSheet有一个owningElement属性 其他可能有owningNode属性 所以可以循环找拥有对应id的styleSheets了

    var sheet = false;

    for (var i = 0; i < document.styleSheets.length; i++) {
        if (document.styleSheets[i].owningElement.id == id) {
            sheet = document.styleSheets[i];
        }
    }

calc

calc 的实现方式其实和vw vh差不多 就不多说了
不过值得注意的是 calc(100% - $unit)的实现不是那么完美 fallback要做好

这里说说应用

最常见的8格grid 自带
zhilizhili-ui 荡平ie8910 还我前端清净地_第9张图片

要兼容到ie8

自适应宽度变化 其实没啥必要 但是咱们有vw这个单位 用啊

首先说下原理

首先是代码 因为要兼容 必须多一层container

1
2
3
4
5
6
  1. 首先我们为每个layout__item加上margin-top margin-left
    zhilizhili-ui 荡平ie8910 还我前端清净地_第10张图片

  2. 这时候我们要去除1 ~ 4上的margin-top

@for $i from 1 through ($numrow - 1) {
    $ret: "";
            $ret: $basesel + str-repeat(" + .layout__item", $i);
            #{$ret} {
                margin-top: 0;
            }
}
        $ret: str-repeat(" + .layout__item", $numrow);
        #{$ret} {
            @include polyfill-advance-set((
                margin-top: $gutter #vw
            ));
        }        

这里我们说下 ie8 可以使用 :first-child + $class == nth-child(2)
+ $class 实际上就是 nth-child(n+2) 大家自己体会下
zhilizhili-ui 荡平ie8910 还我前端清净地_第11张图片

  1. 现在我们只要用一个container盖住 就可以了
    zhilizhili-ui 荡平ie8910 还我前端清净地_第12张图片

angular

首先 avalon 是不错的可以兼容到ie8的方案 不过无法和flexbox兼容方案并存 这也挺遗憾的
不过这次带来的angular的版本是1.4 github地址

本文项目地址

这是一个可以使用的项目 可以在ie8 ie9上运行
github地址

你可能感兴趣的:(html,css,javascript)