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);