JSFiddle - React, Tailwind, and code Playground
HTML
<div class="items"></div>
CSS
body {
margin: 0;
overflow: hidden;
}
.items {
display: flex;
width: 100vw;
height: 100vh;
}
.col {
display: flex;
flex-direction: column;
flex-grow: 1;
}
.cell {
border: 0px solid silver;
flex-grow: 1;
background: black;
position: relative;
}
.cell::before {
content: "";
position: absolute;
width: 100%;
height: 100%;
background: white;
border-radius: 50%;
}
.cell.selected { background: white; }
.cell.selected::before { background: black; }
.cell:hover,
.cell.selected:hover::before { background: #555; }
.cell:hover::before,
.cell.selected:hover { background: #bbb; }
.tl::before { border-top-left-radius: 0; }
.tr::before { border-top-right-radius: 0; }
.bl::before { border-bottom-left-radius: 0; }
.br::before { border-bottom-right-radius: 0; }
JavaScript
const ROWS = 6;
const COLS = 6;
const classes = [
{ name: 'tl', coord: [ [ [ -1, 0 ], [ -1, -1 ], [ 0, -1 ] ], [ [ 0, -1 ], [ -1, 0 ] ] ] },
{ name: 'tr', coord: [ [ [ 0, -1 ], [ 1, -1 ], [ 1, 0 ] ], [ [ 0, -1 ], [ 1, 0 ] ] ] },
{ name: 'bl', coord: [ [ [ 0, 1 ], [ -1, 1 ], [ -1, 0 ] ], [ [ 0, 1 ], [ -1, 0 ] ] ] },
{ name: 'br', coord: [ [ [ 1, 0 ], [ 1, 1 ], [ 0, 1 ] ], [ [ 0, 1 ], [ 1, 0 ] ] ] },
];
const cell = (x, y) =>
(x < 0 || y < 0 || x >= COLS || y >= ROWS)
? $()
: $cells.eq(x * ROWS + y);
$('.items').html(
Array(COLS)
.fill(`<div class="col">${Array(ROWS).fill('<div class="cell"></div>').join('')}</div>`)
.join('')
);
const $cells = $('.cell');
function updateCellClasses() {
$cells.each((i, n) => {
const $this = $(n);
const selected = $this.hasClass('selected');
const y = $this.index();
const x = $this.closest('.col').index();
classes.forEach(({ name, coord }) => {
const c = coord[+selected];
const m = selected ? 'some' : 'every';
const t = c[m](([ dx, dy ]) => cell(x + dx, y + dy).hasClass('selected'));
$this.toggleClass(name, selected ? t : !t);
});
});
}
$cells.click(e => {
$(e.target).toggleClass('selected');
updateCellClasses();
});
[ [ 1, 1 ], [ 1, 2 ], [ 2, 2 ] ].forEach(([ x, y ]) => cell(x, y).addClass('selected'));
updateCellClasses();