Margo Grid
A twelve column grid with named lines, full-bleed support and real subgrid nesting, tuned by four variables.
API
Variables
Four variables tune the whole system, and the fifth is derived from them. Padding and gutters are fully independent — the padding is real padding on the container, the gutters exist only between columns — so any combination is valid, including a padding smaller than the gutter.
| variable | |
|---|---|
--margo-grid-max-width | width cap of the content area, before the side padding |
--margo-grid-padding | side padding of the container, independent from the gutters |
--margo-grid-gutter-x | gap between columns |
--margo-grid-gutter-y | gap between rows |
--margo-grid-bleed | derived: the distance from the content area to the viewport edge |
Containers
| utility | |
|---|---|
margo-grid | the root container: centres, pads, and defines the twelve tracks |
margo-grid-sub | nested grid that reuses the parent tracks through subgrid |
margo-grid-flat | standalone twelve columns, no max width and no padding |
margo-container | same width and padding as margo-grid, without any column |
Columns and rows
| utility | |
|---|---|
margo-col-* | a single column by index: margo-col-4 occupies column four |
margo-col-start-* | start at the beginning of column N |
margo-col-end-* | end at the end of column N, inclusive |
margo-col-span-* | span N columns from wherever the item starts |
margo-row-* | place on row N, spanning one row |
margo-row-start-* | start on row N, keeping the current end |
margo-row-span-* | span N rows from wherever the item starts |
Full bleed
Bleeding is not a column but a negative margin sized to --margo-grid-bleed, the distance between the content area and the viewport edge. Because it is a margin, it works from any column and at any nesting depth, and the matching padding utility brings the content back onto the grid.
| utility | |
|---|---|
margo-col-full | edge to edge of the viewport, escaping max width and padding |
margo-col-content | back to the centred content area, dropping any bleed |
margo-col-start-full | bleed off the left edge, keeping the current end line |
margo-col-start-content | start at the content edge, dropping any left bleed |
margo-col-end-full | bleed off the right edge, keeping the current start line |
margo-col-end-content | end at the content edge, dropping any right bleed |
margo-col-span-full | span the full bleed width regardless of where the item starts |
margo-pl-bleed | padding equal to the bleed on the start side |
margo-pr-bleed | padding equal to the bleed on the end side |
margo-px-bleed | padding equal to the bleed on both sides |
Tuning a single grid
These set the grid variables rather than the CSS properties, so they never depend on utility order to win and they cascade into nested grids unless one overrides them again.
| utility | |
|---|---|
margo-gutter-* | both gutters, on the spacing scale: margo-gutter-4 |
margo-gutter-x-* | column gap only |
margo-gutter-y-* | row gap only |
margo-padding-* | side padding; feeds the bleed, so full-bleed children stay exact |
Examples
Usage
A margo-grid centres a twelve column content area, caps it at the maximum width and pads it on both sides. Direct children sit on the whole content area by default, so a plain container is already aligned before you place anything.
<div className="margo-grid">
<aside className="margo-col-span-3" />
<main className="margo-col-start-4 margo-col-end-content" />
</div>Responsive placement
Every utility takes the standard variants, against the breakpoints the kit declares as numbers — 480, 640, 768, 900, 1080, 1280, 1920 — so a placement can change per breakpoint without leaving the class attribute.
<div className="margo-col-start-4 900:margo-col-end-10 max-900:margo-col-start-content" />Details
Named lines
The tracks carry names, which is what makes the utilities readable rather than arithmetic: content-start and content-end bound the content area, and every column exposes a col-start and a col-end.
grid-template-columns:
[content-start] repeat(12, [col-start] minmax(0, 1fr) [col-end]) [content-end];Rows have no template and no names on purpose: they are addressed by index. A named row line would only be meaningful in a layout whose rows are known in advance, which is not the general case.
Nesting
margo-grid-sub does not create new tracks: it borrows the parent's through subgrid. Grandchildren therefore keep aligning to the same twelve columns at any depth, which a nested grid of its own could only approximate.
<section className="margo-grid">
<div className="margo-col-span-8 margo-grid-sub">
<article className="margo-col-span-4" />
<article className="margo-col-span-4" />
</div>
</section>The nested container must span the columns it wants to inherit. Inside it children are auto-placed, one column each unless they carry a span utility.
Bleeding from anywhere
<nav className="margo-col-start-full margo-col-end-3 margo-pl-bleed">
<Item as={Link} to="/margo-ui">
<Item.Label label="Introduction" />
</Item>
</nav>