JSFiddle - React, Tailwind, and code Playground

Copyright © 2018 by Isaac J. Lee, all rights reserved.

HTML

<div id='myContainer'>
    <ul id='myList'>
        <!-- Will be dynamically generated -->
    </ul>
</div>

<div id='myDashboard'>
    <div id='myInstructions'>
        You can click on an item to select it.
    </div>
    <div>
        Number of list items: <span id='numListItems'></span>
    </div>
    <div>
        Time to change opacity: <span id='timeToChangeOpacity'></span>
    </div>
</div>

SCSS

#myList {
    display: grid;
    grid-template-columns: repeat(4, auto);
    list-style: none;

    .list-item {
        background-color: darkslateblue;
        color: aliceblue;
        box-shadow: 0 0 8px 2px rgba(0, 0, 0, 0.12);

        max-width: 160px;
        border-radius: 4px;
        margin: 8px;
        padding: 8px;

        font-family: 'Arial';
        text-transform: uppercase;
        transform: skewY(-4deg);

        &:hover {
            background-color: goldenrod;
            color: honeydew;
            cursor: pointer;
        }
        
        &.isOpaque {
            opacity: 0.1;
            transition: opacity 0.4s;
        }
        
        &:not(.isOpaque) {
            opacity: 1;
            transition: opacity 0.2s;
        }
    }
}

body {
    #myContainer {
        height: 500px;
        overflow-y: scroll;
        margin-bottom: 20px;
        border: 1px solid black;
    }
    
    #myDashboard {
        height: 80px;
        
        div {
            color: steelblue;
            font-family: 'Arial';
            font-size: 24px;
            font-weight: bold;
            
            margin-bottom: 10px;
        }
    }
}

JavaScript

const numListItems = 1000;
let myList = document.getElementById('myList');

const createListItems = (seed) => {
    let x = seed;

    for (let index = 0; index < numListItems; index++) {
        x = (x % 2) ? (3*x + 1) : (x/2);

        let listItem = document.createElement('li');
        listItem.innerHTML = x.toString(16);
        listItem.id = `myListItem_${index}`;
        listItem.classList.add('list-item');

        listItem.addEventListener('click', (event) => {
            event.stopPropagation();

            highlightListItem(index);
        });

        myList.appendChild(listItem);
    }

    document.getElementById('numListItems').innerHTML = numListItems;
};

const highlightListItem = (myIndex) => {
    const t0 = performance.now();

    for (let index = 0; index < numListItems; index++) {
        let myListItem = document.getElementById(`myListItem_${index}`);

        if (index === myIndex) {
            myListItem.classList.remove('isOpaque');

        } else {
            myListItem.classList.add('isOpaque');

        }
    }

    const t1 = performance.now();

    const timeElapsed = Math.ceil(100 * (t1 - t0)) / 100;
    document.getElementById('timeToChangeOpacity').innerHTML = `${timeElapsed} ms`;
};

const resetHighlights = () => {
    const t0 = performance.now();

    for (let index = 0; index < numListItems; index++) {
        let myListItem = document.getElementById(`myListItem_${index}`);

        myListItem.classList.remove('isOpaque');
    }

    const t1 = performance.now();

    const timeElapsed = Math.ceil(100 * (t1 - t0)) / 100;
    document.getElementById('timeToChangeOpacity').innerHTML = `${timeElapsed} ms`;
};

createListItems(7579309213675935);

document.addEventListener('click', resetHighlights);