SO-76856866
by David Thomas
HTML
<form action="#" method="post">
<fieldset>
<label>
<span class="labelText">Number of grid-cells:</span>
<input type="number" min="1" max="20" step="1" name="size"></label>
<label>
<span class="labelText">grid-column colours:</span>
<input type="text" name="colors"></label>
</fieldset>
</form>
<!--
data-size: an integer, to define the number of cells on each axis,
data-colors: a comma-separated list of colors to cycle through:
-->
<div class="colored-grid" data-size="10" data-colors="red, green"></div>
CSS
*,
::before,
::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
margin: 0;
display: flex;
flex-flow: column nowrap;
gap: 1rem;
justify-content: center;
align-items: center;
min-height: 100vh;
/* using syntax from level 4 of the
CSS Colors Module: */
background-color: rgb(255 255 255 / 0.9);
font-family: Arial, sans-serif;
}
form {
backdrop-filter: blur(3px) brightness(300%) hue-rotate(25deg);
background-color: #fff7;
position: sticky;
top: 0;
}
fieldset {
display: flex;
gap: 1rem;
justify-content: space-between;
}
label {
display: grid;
gap: 0.5rem;
padding: 0.5rem;
}
.colored-grid {
counter-reset: cell;
display: grid;
gap: 5px;
height: auto;
grid-auto-rows: 50px;
grid-template-columns: repeat(var(--size), 50px);
}
.grid-cell {
background-color: var(--backgroundColor);
counter-increment: cell;
display: grid;
place-content: center;
}
.grid-cell::before {
content: counter(cell, decimal-leading-zero);
}
.even {
background-color: red;
}
.odd {
background-color: green;
}
JavaScript
// some simple utilities to reduce typing;
// caching a reference to the document:
let D = document,
// an alias for document.createElement(), with the option to provide
// properties for the created element:
create = (tag, props) => Object.assign(D.createElement(tag), props),
// an alias for both document.querySelector() - by default - and
// Element.querySelector(), if an Element node is passed as the
// context argument:
get = (selector, context = D) => context.querySelector(selector),
// caching a reference to the element in which the grid should
// be appended:
gridParent = get('.colored-grid[data-size]');
// defining a function to create the grid, taking one argument,
// the element in which the created elements are to be placed:
let createGrid = (source) => {
// if there is no HTMLElement passed to the function we
// return false and quit the function:
if (!source || 1 !== source.nodeType) {
return false;
}
// while the source element has any firstChild (this includes
// text-nodes, comment nodes, and elements:
while (source.firstChild) {
// we use parentNode.removeChild to remove that firstChild;
// had the childNodes been only elements, we could have
// used HTMLElement.remove(), but that would (probably) have
// left an accumulation of text-nodes behind in the DOM (which
// I personally find messy, as inconsequential as it may be):
source.removeChild(source.firstChild);
}
// using destructuring assignment to declare the variables
// 'sz' and 'c', as aliases for 'size' and 'color' from
// the source.dataset Object, as the variables need to
// be modified for use in the function and I prefer to
// use the 'meaningful' names once they're ready for use:
let {
size: sz,
colors: c
} = source.dataset,
// here we create the 'size' variable, after using
// parseInt() to convert the 'sz' string to a base-10
// integer:
size = parseInt(sz, 10),
// and...