如何使用HTML5/CSS3实现延迟加载

作者:root

/* main styles */
*,
*:before,
*:after {
    box-sizing: border-box;
    padding: 0;
    margin: 0;
}
body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
    font-size: 100%;
    color: #444;
    background-color: #fff;
    overflow-x: hidden;
    overflow-y: scroll;
}
article {
    max-width: 40em;
    padding: 0 4em;
    margin: 0 auto;
}
h1,
h2 {
    font-weight: normal;
    margin-top: 1em;
}
p,
a {
    margin-top: 1em;
}
h2 + p {
    margin-top: 0;
}
ul,
ol {
    margin: 1em 0 0 2em;
}
li {
    margin-top: 0.5em;
}
pre {
    white-space: pre;
    padding: 2px 6px;
    margin-top: 1em;
    background-color: #ddd;
    border-radius: 3px;
    overflow: auto;
}
code {
    font-size: 1.1em;
}
img {
    max-width: 100%;
}
a.primary {
    width: 100vw;
    left: 50%;
    margin-left: -50vw;
}
a.full {
    clear: both;
    width: 100%;
    box-shadow: 0 3px 4px #000;
}
a.boxout1,
a.boxout2 {
    clear: both;
    float: left;
    width: 60%;
    margin: 1em 1em 0 -4em;
    box-shadow: 0 3px 4px #000;
}
a.boxout2 {
    float: right;
    margin: 1em -4em 0 1em;
}
/* progressive image CSS */
a.progressive {
    position: relative;
    display: block;
    overflow: hidden;
    outline: none;
}
a.progressive:not(.replace) {
    cursor: default;
}
a.progressive img {
    display: block;
    width: 100%;
    max-width: none;
    height: auto;
    border: 0 none;
}
a.progressive img.preview {
    filter: blur(2vw);
    transform: scale(1.05);
}
a.progressive img.reveal {
    position: absolute;
    left: 0;
    top: 0;
    will-change: transform, opacity;
    animation: reveal 1s ease-out;
}
@keyframes reveal {
    0% {
        transform: scale(1.05);
        opacity: 0;
    }
    100% {
        transform: scale(1);
        opacity: 1;
    }
}


// progressive-image.js
if (window.addEventListener && window.requestAnimationFrame && document.getElementsByClassName) window.addEventListener('load', function() {
    // start
    var pItem = document.getElementsByClassName('progressive replace'),
        timer;
    window.addEventListener('scroll', scroller, false);
    window.addEventListener('resize', scroller, false);
    inView();

    // throttled scroll/resize
    function scroller(e) {
        timer = timer || setTimeout(function() {
            timer = null;
            requestAnimationFrame(inView);
        }, 300);
    }

    // image in view?
    function inView() {
        var wT = window.pageYOffset,
            wB = wT + window.innerHeight,
            cRect, pT, pB, p = 0;
        while (p < pItem.length) {
            cRect = pItem[p].getBoundingClientRect();
            pT = wT + cRect.top;
            pB = pT + cRect.height;
            if (wT < pB && wB > pT) {
                loadFullImage(pItem[p]);
                pItem[p].classList.remove('replace');
            } else p++;
        }
    }

    // replace with full image
    function loadFullImage(item) {
        if (!item || !item.href) return;
        // load image
        var img = new Image();
        if (item.dataset) {
            img.srcset = item.dataset.srcset || '';
            img.sizes = item.dataset.sizes || '';
        }
        img.src = item.href;
        img.className = 'reveal';
        if (img.complete) addImg();
        else img.onload = addImg;
        // replace image
        function addImg() {
            // disable click
            item.addEventListener('click', function(e) {
                e.preventDefault();
            }, false);
            // add full image
            item.appendChild(img).addEventListener('animationend', function(e) {
                // remove preview image
                var pImg = item.querySelector && item.querySelector('img.preview');
                if (pImg) {
                    e.target.alt = pImg.alt || '';
                    item.removeChild(pImg);
                    e.target.classList.remove('reveal');
                }
            });
        }
    }
}, false);