<div id="container">
<div class="item grey"></div>
<div class="item purple"></div>
<div class="item orange"></div>
<div class="item blue"></div>
</div>
#container{
display: grid;
width: 100%;
height: 350px;
grid-template-columns: [full-start] 1fr 1fr [full-end];
grid-template-rows: 100px 1fr 100px;
grid-gap: 20px;
}
.purple {
grid-row: span 2;
}
.blue {
grid-column: span 2;
}
const container = document.getElementById("container");
const inspector = document.createElement('div');
inspector.setAttribute('style', `
position: absolute;
height: ${container.offsetHeight}px;
width: ${container.offsetWidth}px;
top: ${container.offsetTop}px;
left: ${container.offsetLeft}px;
background: rgba(58, 250, 8, .5);
`);
document.body.appendChild(inspector);
// get the rows/columns/gaps
const styles = window.getComputedStyle(container);
const rows = styles.getPropertyValue("grid-template-rows");
const columns = styles.getPropertyValue("grid-template-columns");
const rowGap = styles.getPropertyValue("grid-row-gap");
const columnGap = styles.getPropertyValue("grid-column-gap");
// convert the rows and columns into a format we can work with
const columnData = parseGridTemplate(columns, columnGap);
const rowData = parseGridTemplate(rows, rowGap);
console.log("columnData", columnData);
console.log("rowData", rowData);
/*
Converts a grid template string into an array of grid line objects
Example input: "[full-start] 300px 300px [full-end]"
Example outut:
[{
"start": -1,
"end": 1,
"name": "full-start"
},
{
"start": 299,
"end": 301,
"name": null,
"gap": 20
},
{
"start": 619,
"end": 621,
"name": "full-end"
}]
*/
function parseGridTemplate(templateStr, gap = "0px") {
const gapSize = parseFloat(gap.replace("px", ""));
// splits at and space that isn't between two [ ] brackets
const parsedArray = templateStr.split(/\s(?![^[]*])/);
let lines = [];
let currentPosition = 0;
// add in any missing names as ""
// "200px [center-start] 300px [center-end] 400px" becomes:
// "'' 200px [center-start] 300px [center-end] 400px ''"
let allItems = [];
parsedArray.forEach((item, index) => {
if (item.includes("px")) {
// add a null name before it if missing
if (!parsedArray[index - 1] || parsedArray[index - 1].includes("px")) {
allItems.push("");
}
}
allItems.push(item);
});
// handle last item
if (parsedArray[parsedArray.length - 1].includes("px")) {
allItems.push("");
}
allItems.forEach((item, index) => {
if (item.includes("px")) {
const trackSize = parseFloat(item.replace("px", ""));
currentPosition += trackSize;
} else {
let newLine = {
start: currentPosition - 1,
end: currentPosition + 1,
name: getName(item)
};
// add gaps on just the inner lines
// and count it for positioning
if (index !== 0 && index !== allItems.length - 1 && gapSize !== 0) {
newLine.gap = gapSize;
currentPosition += gapSize;
}
lines.push(newLine);
}
});
return lines;
}
function getName(item) {
return item.includes("[") ? item.match(/\[(.*)\]/)[1].trim() : null;
}
Also see: Tab Triggers