I know this topic is quite old but for those wrestling with React and TypeScript this might be interesting.
I've made a Dashboard component, which has a nested Grid component, which has nested Widget components, which can get props for how many columns to span - and if no value is given it defaults to 1.
I didn't like the last item in a grid to 'not complete' a full block. With this code, the last item in the grid will stretch to the end of the last grid column. It calculates it's current position so if you have a grid with unknown grid items but still want a full block, this will come in handy.
And don't forget to give the grid element in the JSX the ref={gridRef} attribute :-)
const gridRef = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
if (!gridRef.current) return;
const widgets = gridRef.current.children as HTMLCollectionOf<HTMLDivElement>;
const widgetsLeftPosition: number[] = [];
const widgetsInLastRow: HTMLDivElement[] = [];
// add offset from screenedge to array
for (let i = 0; i < widgets.length; i++) {
const currentWidgetLeftPosition = widgets[i].getBoundingClientRect().left;
widgetsLeftPosition.push(currentWidgetLeftPosition);
}
// add elements (from rear end) to array, and
// check if position of current element has same offset as first item, then break
// (which results in having only the elements of the last row in the array)
for (let i = widgetsLeftPosition.length - 1; i >= 0; i--) {
widgetsInLastRow.push(widgets[i]);
if (widgetsLeftPosition[i] === widgetsLeftPosition[0]) break;
}
// for every element in the last row: check the gridColumnEnd value and
// take the last character (which is a 'string-integer').
// parse it to a normal integer, then sum up all integers and return that value
const columnSpanStart = () => {
let sum = 0;
for (let i = 0; i < widgetsInLastRow.length; i++) {
const spanString = getComputedStyle(widgetsInLastRow[i]).gridColumnEnd;
sum += parseInt(spanString.slice(-1));
}
return sum;
};
// finally, use the returned value from columnSpanStart() as gridColumn 'start' value.
// this will overwrite the default 'grid-column-end' style given by the widget component.
const lastWidget = widgets[widgets.length - 1];
lastWidget.style.gridColumn = `${columnSpanStart()} / -1`;
}, []);