JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://rawgithub.com/Rich-Harris/Ractive/master/build/Ractive.min.js"></script>
<div id='container'></div>
<script id='tpl' type='text/ractive'>
<h1>HTTP Status Dogs</h1>
<p><a href='http://httpstatusdogs.com/'>http://httpstatusdogs.com/</a></p>
{{# statusDogs }}
<div class='status-dog'>
<a href='http://httpstatusdogs.com/{{code}}-{{slug}}'>
<img data-src='http://httpstatusdogs.com/wp-content/uploads/{{thumb}}' intro='lazyload'>
<span>{{status}}</span>
</a>
</div>
{{/ statusDogs }}
</script>
CSS
body {
font-family: 'Helvetica Neue', 'Arial';
font-size: 16px;
color: #353535;
}
.status-dog {
display: inline;
float: left;
margin: 0 1em 1em 0;
text-align: center;
background-color: #f4f4f4;
}
.status-dog img {
width: 300px;
height: 230px;
opacity: 0;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
transition: opacity 1s;
}
.status-dog img.loaded {
opacity: 1;
}
.status-dog span {
display: block;
padding: 0.5em 0;
}
.status-dog a {
text-decoration: none;
}
.status-dog a:hover {
text-decoration: underline;
}
JavaScript
var ractive;
// Define a `lazyload` transition and make it globally available
(function () {
var scrollHandler, lazyloaders, Lazyloader;
Lazyloader = function ( node, src ) {
this.node = node;
this.src = src;
};
Lazyloader.prototype = {
visible: function () {
var boundingClientRect = this.node.getBoundingClientRect();
return (
( boundingClientRect.top < window.innerHeight ) &&
( boundingClientRect.bottom > 0 ) &&
( boundingClientRect.left < window.innerWidth ) &&
( boundingClientRect.right > 0 )
);
},
load: function () {
var node = this.node, src = this.src, img = new Image();
img.addEventListener( 'load', loadHandler = function () {
node.src = src;
node.classList.add( 'loaded' );
img.removeEventListener( 'load', loadHandler );
});
img.src = src;
}
};
scrollHandler = function ( event ) {
var i = lazyloaders.length;
while ( i-- ) {
lazyloader = lazyloaders[i];
if ( lazyloader.visible() ) {
lazyloader.load();
lazyloaders.splice( i, 1 );
}
}
if ( !lazyloaders.length ) {
window.removeEventListener( 'scroll', scrollHandler );
}
};
lazyloaders = [];
Ractive.transitions.lazyload = function ( node, complete, params, isIntro ) {
if ( isIntro ) {
setTimeout( function () { // wait until next repaint, otherwise layout is wrong
var lazyloader;
if ( !lazyloaders.length ) {
window.addEventListener( 'scroll', scrollHandler );
}
...