JSFiddle - React, Tailwind, and code Playground

by BurpmanJunior

HTML

<div id="grid" class="clearfix">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
    <div>10</div>
    <div>11</div>
    <div>12</div>
    <div>13</div>
    <div>14</div>
    <div>15</div>
    <div>16</div>
    <div>17</div>
    <div>18</div>
    <div>19</div>
    <div>20</div>
    <div>21</div>
    <div>22</div>
    <div>23</div>
    <div>24</div>
    <div>25</div>
    <div>26</div>
    <div>27</div>
    <div>28</div>
    <div>29</div>
    <div>30</div>
</div>

SCSS

#grid{
    margin: 15px auto;
    max-width: 600px;
    & > div{
        width: 20%;
        font-family: sans-serif;
        float: left;
        padding: 30px 15px;
        text-align: center;
        background-color: #777;
        color: #fff;
        font-weight: bold;
        font-size: 14px;
        transition: background-color 300ms, color 300ms;
        &[data-direction]{
            font-size: 0px;
            &:after{
                font-size: 14px;
                content: attr(data-direction) ' : ' attr(data-distance);
            }
        }
        &[data-distance="1"]{
            background-color: #ddd;
            color: #333;
        }
        &[data-distance="2"]{
            background-color: #ccc;
            color: #444;
        }
        &[data-distance="3"]{
            background-color: #aaa;
            color: #666;
        }
        &[data-distance="4"]{
            background-color: #999;
            color: #777;
        }
        &[data-direction="this"]{
            background-color: #fff;
            color: #333;
        }
    }
}

.clearfix{
    clear: both;
    &:before{
        content: '';
        zoom: 1;
    }
    &:after{
        content: '';
        clear: both;
        display: table;
    }
}

*{
    box-sizing: border-box;
}

JavaScript

/**
 * GRID DIRECTION
 */
var gridDirection = {
    wrap: document.getElementById('grid'), // Main element
    throttleBuffer: 10, // Mouse event throttle limit (function runs p/second)
    scaleBuffer: 0.1, // Scale buffer for single direction paths
    /**
     * Initialize events
     */
    init: function () {
        var _g = this;
        _g.bindEvents();
    },
    /**
     * Bind mouse events and throttles
     */
    bindEvents: function () {
        var _g = gridDirection;
        _g.poll = new Date().getTime(); // Set initial poll timestamp
        // Mouse move within grid
        _g.wrap.addEventListener('mousemove', function (e) {
            var now = new Date().getTime();
            if (now > _g.poll + _g.throttleBuffer) {
                // Within throttle buffer range
                _g.poll = now;
                _g.offsetCalc(e);
            }
        });
        // Mouse out grid
        _g.wrap.addEventListener('mouseout', function (e) {
            var remove = false;
            // Check if mouse out of grid and not inner elements
            if (e.toElement === null) {
                remove = true;
            } else if (e.toElement.parentElement !== _g.wrap) {
                remove = true;
            }
            if (remove) {
                // Remove data attributes
                var elems = _g.wrap.getElementsByTagName('div');
                for (var i = 0; i < elems.length; i++) {
                    elems[i].removeAttribute('data-direction');
                    elems[i].removeAttribute('data-distance');
                }
            }
        });
    },
    /**
     * Calculate offsets, distances and apply attributes
     */
    offsetCalc: function (e) {
        _g = gridDirection;
        // Main grid coords
        var wrapOffset = {
            x: _g.wrap.offsetLeft,
            y: _g.wrap.offsetTop
        };
        // Main grid size
        var wrapSize = {
            x: _g.wrap.offsetWidth,
            y:...