function getItemGridCoords(element) {
function digitsAndSpacesOnly(string) {
return string.replace(/[^\d\s.]/g, '');
}
function parseTemplate(gridTemplate) {
// parses a CSS grid-template-[row|column] to Numbers and does cumulative summation
// "100px 100px 100px" → [100,100,100] → [100,200,300]
return digitsAndSpacesOnly(gridTemplate).split(/\s/gmi).map(Number).reduce((array,currentValue) => {
array.push(currentValue + array[array.length-1]);
return array;
},[0]);
}
function findIndexOfClosest(array,target) {
return array.reduce((prev,curr,indexCurr) => {
return (Math.abs(curr - target) < Math.abs(array[prev] - target) ? indexCurr : prev);
});
}
const grid = element.parentElement;
const computedStyles = getComputedStyle(grid);
const getGapsAdder = gap => (n,i) => n + i * gap;
const colsPositions = parseTemplate(computedStyles['grid-template-columns']).map(getGapsAdder(digitsAndSpacesOnly(computedStyles['column-gap'])));
const rowsPositions = parseTemplate(computedStyles['grid-template-rows']).map(getGapsAdder(digitsAndSpacesOnly(computedStyles['row-gap'])));
const bounds = element.getBoundingClientRect();
const gridBounds = grid.getBoundingClientRect();
return {
col : findIndexOfClosest(colsPositions, bounds.left - gridBounds.left),
row : findIndexOfClosest(rowsPositions, bounds.top - gridBounds.top),
};
}
for (let element of document.querySelectorAll('.grid > *')) {
element.innerHTML = JSON.stringify(getItemGridCoords(element));
}
.grid {
font-family: monospace;
display: grid;
grid : auto-flow dense / repeat(12,1fr);
gap: 0.5em;
}
.grid > * {
white-space: nowrap;
background: aliceblue;
min-height: 2.5em;
}
.whole {
grid-column: auto / span 12;
}
.two-thirds {
grid-column: auto / span 8;
}
.half {
grid-column: auto / span 6;
}
.third {
grid-column: auto / span 4;
}
.skyscraper {
grid-row: auto / span 3;
}
<div class='grid'>
<span class='whole'></span>
<span class='half'></span>
<span class='half'></span>
<span class='half'></span>
<span class='half'></span>
<span class='half'></span>
<span class='half'></span>
</div>
<hr>
<div class='grid'>
<span class='third'></span>
<span class='third'></span>
<span class='third'></span>
<span class='half'></span>
<span class='half'></span>
<span class='half'></span>
<span class='half'></span>
</div>
<hr>
<div class='grid'>
<span class='third skyscraper'></span>
<span class='third'></span>
<span class='third'></span>
<span class='two-thirds'></span>
<span class='third'></span>
<span class='third'></span>
<span class='half'></span>
<span class='half'></span>
</div>