Kitten Snap

Snapping Panes of Kittens using hardware accelerated css! Detects a drag's relative direction to determine to which pane to scroll

by theoperatore

HTML

<div id='grid' class='grid'>
    <div class='box'>
        <div class='content_container'>
            <div class='content'>
                <p>Top Left</p>
            </div>
        </div>
    </div>
    <div class='box'>
        <div class='content_container'>
            <div class='content'>
                <p>Top Mid</p>
            </div>
        </div>
    </div>
    <div class='box'>
        <div class='content_container'>
            <div class='content'>
                <p>Top Right</p>
            </div>
        </div>
    </div>
    <div class='box'>
        <div class='content_container'>
            <div class='content'>
                <p>Mid Left</p>
            </div>
        </div>
    </div>
    <div class='box'>
        <div class='content_container'>
            <div class='content'>
                <p>Mid Mid</p>
            </div>
        </div>
    </div>
    <div class='box'>
        <div class='content_container'>
            <div class='content'>
                <p>Mid Right</p>
            </div>
        </div>
    </div>
    <div class='box'>
        <div class='content_container'>
            <div class='content'>
                <p>Bottom Left</p>
            </div>
        </div>
    </div>
    <div class='box'>
        <div class='content_container'>
            <div class='content'>
                <p>Bottom Mid</p>
            </div>
        </div>
    </div>
    <div class='box'>
        <div class='content_container'>
            <div class='content'>
                <p>Bottom Right</p>
            </div>
        </div>
    </div>
</div>
<!-- end wrapper -->

CSS

html, body {
    height:100%;
}
body {
    margin:0;
    overflow:hidden;
    background:#333;
}
.grid {
    height:100%;
    width:100%;
    white-space: nowrap;
    /*font-size: 0;*/
    -webkit-transform: translate3d(0, 0, 0);
    -moz-transform: translate3d(0, 0, 0);
    -ms-transform: translate3d(0, 0, 0);
    -o-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    -webkit-transition: all 300ms ease-in-out;
    -moz-transition: all 300ms ease-in-out;
    -ms-transition: all 300ms ease-in-out;
    -o-transition: all 300ms ease-in-out;
    transition: all 300ms ease-in-out;
    position:absolute;
}
.box {
    height:100%;
    width:100%;
    /*background-size: cover;*/
    padding-left:1%;
    padding-right:1%;
    background-size: cover;
    position:absolute;
}
.t_0 {
    -webkit-transform: translate3d(0, 0, 0);
    -moz-transform: translate3d(0, 0, 0);
    -ms-transform: translate3d(0, 0, 0);
    -o-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
}
.t_1 {
    -webkit-transform: translate3d(-100%, 0, 0);
    -moz-transform: translate3d(-100%, 0, 0);
    -ms-transform: translate3d(-100%, 0, 0);
    -o-transform: translate3d(-100%, 0, 0);
    transform: translate3d(-100%, 0, 0);
}
.t_2 {
    -webkit-transform: translate3d(-200%, 0, 0);
    -moz-transform: translate3d(-200%, 0, 0);
    -ms-transform: translate3d(-200%, 0, 0);
    -o-transform: translate3d(-200%, 0, 0);
    transform: translate3d(-200%, 0, 0);
}
.t_3 {
    -webkit-transform: translate3d(0, -100%, 0);
    -moz-transform: translate3d(0, -100%, 0);
    -ms-transform: translate3d(0, -100%, 0);
    -o-transform: translate3d(0, -100%, 0);
    transform: translate3d(0, -100%, 0);
}
.t_4 {
    -webkit-transform: translate3d(-100%, -100%, 0);
    -moz-transform: translate3d(-100%, -100%, 0);
    -ms-transform: translate3d(-100%, -100%, 0);
    -o-transform: translate3d(-100%, -100%, 0);
    transform: translate3d(-100%, -100%, 0);
}
.t_5 {
    -webkit-transform:...

JavaScript

window.addEventListener("load", function () {
    setTimeout(function () {
        window.scrollTo(0, 1);
    }, 0);
});

var grid = document.getElementById('grid'),
    startPos = {
        x: 0,
        y: 0
    },
    endPos = {
        x: 0,
        y: 0
    },
    dx = 0,
    dy = 0,
    curr = 0,
    nextY = 3,
    prevY = 8,
    nextX = 1,
    prevX = 2;

window.addEventListener('touchstart', start, false);
window.addEventListener('mousedown', start, false);
window.addEventListener('touchend', end, false);
window.addEventListener('mouseup', end, false);

function start(e) {
    e.preventDefault();
    e.stopPropagation();

    if (e.type === 'mousedown') {
        startPos.x = e.clientX;
        startPos.y = e.clientY;
    } else {
        startPos.x = e.changedTouches[0].clientX;
        startPos.y = e.changedTouches[0].clientY;
    }
}

function end(e) {
    e.preventDefault();
    e.stopPropagation();

    if (e.type === 'mouseup') {
        endPos.x = e.clientX;
        endPos.y = e.clientY;
    } else {
        endPos.x = e.changedTouches[0].clientX;
        endPos.y = e.changedTouches[0].clientY;
    }

    dx = endPos.x - startPos.x;
    dy = endPos.y - startPos.y;

    if (Math.abs(dx) > 25 || Math.abs(dy) > 25) {
        if (curr >= 8) {
            nextX = 0;
        }
        if (curr <= 0) {
            prevX = 8;
        }
        if (curr > 5) {
            nextY = curr - 6;
        }
        if (curr < 3) {
            prevY = curr + 6;
        }

        if (Math.abs(dx) > Math.abs(dy)) {

            //scroll content left
            if (dx > 0) {
                grid.classList.add('t_' + prevX);
                grid.classList.remove('t_' + curr);

                curr = prevX;
            }

            //scroll content right
            else {
                grid.classList.add('t_' + nextX);
                grid.classList.remove('t_' + curr);

                curr = nextX;
            }
        } else {

            //scroll content...