Navigation: uCss > Source > Modules > Layout > Grid
Modules: Config | Base | Layout | Theming | Typography | Patterns | Utilities
Implicit 2D Layouts. A smart, responsive grid engine that uses
auto-fit+minmax()to arrange content without manual column classes. Includes an Item Placement API (.gc-*,.gr-*), Subgrid alignment, and Recipes (masonry, carousels, dense).
The Grid Submodule is the heavy lifter of the Layout module. It handles 2-Dimensional layouts (rows and columns).
.g. Items wrap automatically based on their minimum width (--g-min). No media queries needed..gc-4, .gr-2--md) plus a full CSS-variable API (--gc, --gr, --ga, β¦)..g-2-1 (β
+ β
), .g-1-3 (ΒΌ + ΒΎ) and sidebar .sr/.sl for dashboards and docs..sg / .sgc lets children (like cards) adopt the parent grid's tracks β perfect header/footer alignment across siblings.clamp() β they shrink on mobile and grow on desktop automatically.[!NOTE] Implicit vs Explicit Explicit: "I want 3 columns." Implicit: "I want columns at least 256px wide." uCss defaults to Implicit because it is more robust against content changes.
We don't want to calculate 100% / 12 * 4 anymore. That logic belongs to 2013.
<div class="col-xs-12 col-md-6 col-lg-4">.<ul class="g">β¦</ul> (fluid by default) or --g-min: 300px.The uCss approach declares the intent (needs 300px per item) rather than the implementation (takes 4 columns).
Implicit grids are resilient. Add a 4th item to a 3-column explicit grid and it breaks or looks weird. Add it to an implicit grid and it just wraps to a new row. This fail-safe nature makes uCss grids perfect for CMS content where editors control the item count.
<ul class="g">.<li>Item 1</li> β three of them.<ul class="g">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
ul.g / ol.g get list resets for free (no bullets, no padding, no flow margins).
<!-- Override the minimum item width globally on this grid -->
<ul class="g" style="--g-min: 100px;">β¦</ul>
Each scenario shows an Emmet abbreviation β the expanded HTML β why it's the right choice. The canonical uCss card grid is ul.g > li.clk > article.crd β the li is the grid item (gets the item API + list reset), .clk makes the whole card clickable, and .crd is the card pattern.
Emmet: ul.g>li.clk*3>article.crd
<ul class="g">
<li class="clk"><article class="crd"><h3>Title</h3><p>Bodyβ¦</p><a>Read more</a></article></li>
<li class="clk"><article class="crd"><h3>Title</h3><p>Bodyβ¦</p><a>Read more</a></article></li>
<li class="clk"><article class="crd"><h3>Title</h3><p>Bodyβ¦</p><a>Read more</a></article></li>
</ul>
Why: fluid 3 β 2 β 1 columns with no classes; perfect for posts, products, features.
Emmet: ul.g.g-3>li.clk*6>article.crd Β· ul.g.g-4--lg.g-2--md.g-1--sm>li.clk*8>article.crd
<ul class="g g-3">
<li class="clk"><article class="crd">β¦</article></li> <!-- 6Γ -->
</ul>
<ul class="g g-4--lg g-2--md g-1--sm">
<li class="clk"><article class="crd">β¦</article></li> <!-- 8Γ -->
</ul>
Why: .g-3 is 3/2/1 out of the box; the responsive stack is 4 β 2 β 1 per breakpoint.
Emmet: article.g.g-2-1>(div+figure)
<article class="g g-2-1">
<div>β¦text columnβ¦</div>
<figure>β¦media columnβ¦</figure>
</article>
Why: β
+ β
split for article + media; collapses to a single column on tablet/mobile. Use div.g.g-2-1>(div+aside) for dashboards.
Emmet: div.g.sr>(main+aside)
<div class="g sr">
<main>β¦contentβ¦</main>
<aside>β¦sidebarβ¦</aside>
</div>
Why: content auto-sizes, sidebar minmax(16rem, 25%). .sl mirrors it left.
Emmet: ul.g.g-3>(li.clk>article.crd.sg.gr-3>(header+div+footer))*3
<ul class="g g-3">
<li class="clk"><article class="crd sg gr-3"><header>Title</header><div>Body</div><footer>CTA</footer></article></li>
<li class="clk"><article class="crd sg gr-3"><header>Much longer titleβ¦</header><div>Body</div><footer>CTA</footer></article></li>
<li class="clk"><article class="crd sg gr-3"><header>Title</header><div>Body</div><footer>CTA</footer></article></li>
</ul>
Why: every card's <header> / <div> / <footer> align to the same three rows β titles, bodies and CTA buttons line up regardless of content length.
Emmet: ul.g.g-3>(li.clk.gc-2--lg>article.crd+li.clk+li.clk)
<ul class="g g-3">
<li class="clk gc-2--lg"><article class="crd">Featured (2 cols on lg)</article></li>
<li class="clk"><article class="crd">β¦</article></li>
<li class="clk"><article class="crd">β¦</article></li>
</ul>
Why: one hero item spans 2 columns on desktop, normal grid on tablet/mobile.
Emmet: ul.g.g-ms>(li>figure)*6
<ul class="g g-ms">
<li><figure>β¦</figure></li> <!-- 6Γ, variable heights -->
</ul>
Why: variable-height masonry via CSS multi-column (with a native grid-lanes upgrade when supported). Ideal for galleries.
Emmet: ul.g.scr-3>li.clk*6>article.crd (exact) Β· ul.g.crs-3>li.clk*6>article.crd (peek) Β· ul.g.crs-3.ctrs>li.clk*6>article.crd (native buttons)
<ul class="g scr-3">
<li class="clk"><article class="crd">β¦</article></li> <!-- exactly 3 visible -->
</ul>
<ul class="g crs-3">
<li class="clk"><article class="crd">β¦</article></li> <!-- 3 + next peeking -->
</ul>
Why: .scr-N = exact edge-to-edge fits (steps, tiers); .crs-N = peeking cards signaling scrollability (products); add .ctrs for native ::scroll-button() arrows where supported.
Emmet: ul.g.g-4.dense>li*8
<ul class="g g-4 dense">
<li>β¦</li> <!-- 8Γ, varied sizes -->
</ul>
Why: grid-auto-flow: dense backfills holes with smaller items β great for mosaics and mixed-size media grids.
<section class="s">
<div>
<header>β¦</header>
<ul class="g g-3">
<li class="clk"><article class="crd">β¦</article></li>
<li class="clk"><article class="crd">β¦</article></li>
<li class="clk"><article class="crd">β¦</article></li>
</ul>
</div>
</section>
Only the ul.g is the grid β the section/container/header just show where it nests.
This Submodule is part of layout.css.
| File | Full (Raw) | Clean | Min | Gzip | Brotli |
|---|---|---|---|---|---|
grid/base.css |
10.4 KB | 8.0 KB | 6.1 KB | 1.9 KB | 1.5 KB |
grid/columns.css |
10.7 KB | 10.4 KB | 9.0 KB | 1.2 KB | 1.0 KB |
grid/subgrid.css |
9.3 KB | 8.7 KB | 7.2 KB | 1.0 KB | 0.9 KB |
grid/item/base.css |
4.7 KB | 3.9 KB | 3.1 KB | 0.8 KB | 0.7 KB |
grid/item/placement.css |
3.9 KB | 3.5 KB | 2.8 KB | 0.7 KB | 0.5 KB |
grid/recipes/masonry.css |
3.2 KB | 1.4 KB | 1.1 KB | 1.1 KB | 0.9 KB |
grid/recipes/scroll.css |
11.1 KB | 9.8 KB | 8.8 KB | 2.1 KB | 1.7 KB |
grid/recipes/misc.css |
0.5 KB | 0.4 KB | 0.3 KB | 0.3 KB | 0.2 KB |
Stats reflect the last verified build from
dist/latest. Runnpm run build:latestto regenerate.
Since this is a nested module, it is included in layout.min.css:
<link rel="preconnect" href="https://ucss.unqa.dev">
<link rel="stylesheet" href="https://ucss.unqa.dev/latest/lib/layout.min.css">
| File | Description | Download |
|---|---|---|
base.css |
Engine. The .g class and the auto-fit math. Defines --g-min, --g-g, container-query breakpoints. |
src |
columns.css |
Explicit. Fixed column presets (.g-2β¦.g-12), fractional layouts (.g-2-1, .g-1-3, β¦) and sidebars (.sr, .sl). |
src |
subgrid.css |
Nesting. .sg / .sgr set grid-template-rows: subgrid; .sgc sets grid-template-columns: subgrid (guarded by @supports). |
src |
item/base.css |
Item API. CSS-variable hooks on every grid item (--gc, --gr, --ga, --gi-*). |
src |
item/placement.css |
Span Classes. .gc-1β¦.gc-12, .gr-1β¦.gr-5, .gc-f, .gr-f + responsive variants. |
src |
recipes/masonry.css |
Gallery. .g-ms / .g-gl β CSS multi-column fallback with a native grid-lanes upgrade. |
src |
recipes/scroll.css |
Scroll. .scr-N exact-fit and .crs-N peeking carousels with snap physics. |
src |
recipes/misc.css |
Misc. .dense (auto-flow dense), .inline (inline-grid), list resets. |
src |
The magic formula:
grid-template-columns: repeat(auto-fit, minmax(var(--g-min), 1fr))
auto-fit: creates as many columns as fit the available space.minmax: enforces a minimum item-width floor. Default: clamp(16rem, calc(16rem + 4 * (100cqi - 33rem) / 55), 20rem) (β256β320px).--g-min is 200px β 5 columns.--g-min is 200px β 2 columns.1fr: distributes remaining space equally.Override per grid:
<ul class="g" style="--g-min: 200px; --g-g: 1rem;">β¦</ul>
.sg)Subgrid is one of the most important CSS layout features of the decade.
Problem: A row of cards. Card A has a short title, card B a long one β bodies start at different heights, CTAs drift.
Solution: the parent defines rows, cards adopt them:
<ul class="g g-3">
<li class="clk"><article class="crd sg gr-3">
<header>Short title</header>
<div>Body</div>
<footer>CTA</footer>
</article></li>
<li class="clk"><article class="crd sg gr-3">
<header>A much longer multi-line title here!</header>
<div>Body</div>
<footer>CTA</footer>
</article></li>
</ul>
| Class | Sets | Purpose |
|---|---|---|
.sg, .sgr, .subgrid, .subrow |
grid-template-rows: subgrid |
Align header/body/footer rows across cards |
.sgc, .subcol |
grid-template-columns: subgrid |
Align columns across children |
Both are applied inside @supports, so browsers without subgrid fall back to normal block flow.
.g-2-1)Sometimes you don't want equal columns. Available ratios:
| Class | Columns | Breakdown |
|---|---|---|
.g-2-1 |
3 | 2fr + 1fr |
.g-1-2 |
3 | 1fr + 2fr |
.g-3-1 |
4 | 3fr + 1fr |
.g-1-3 |
4 | 1fr + 3fr |
.g-2-3 |
5 | 2fr + 3fr |
.g-3-2 |
5 | 3fr + 2fr |
.sr |
2 | content + sidebar (minmax(16rem, 25%)) |
.sl |
2 | sidebar + content |
All asymmetric layouts collapse to 1 column on tablet (--md) and below.
.dense)By default, CSS Grid leaves holes when an item is too big to fit the remaining space in a row. Adding .dense enables grid-auto-flow: dense so the browser backfills those holes with smaller items.
<ul class="g g-4 dense">
<li class="gc-2 gr-2">Big featured item</li>
<li>β¦</li>
<li>β¦</li>
<li>β¦</li> <!-- auto-backfills -->
</ul>
The .g class governs the entire grid. It integrates with a parent container-query context established automatically by any non-grid ancestor.
Responsive classes use the --sm / --smd / --md / --mdl / --lg suffix system, driven by container queries:
| Suffix | Container width |
|---|---|
--sm |
< 30rem (480px) |
--smd |
< 60rem (small + medium) |
--md |
30rem β 60rem (480β960px) |
--mdl |
> 30rem (medium + large) |
--lg |
> 60rem (960px+) |
An extra-small behavior also kicks in at β€ 20rem (320px): the minimum item width shrinks so items still fit.
| Class | Desktop (lg) | Tablet (md) | Mobile (sm) |
|---|---|---|---|
.g-1 |
1 col | 1 col | 1 col |
.g-2 |
2 cols | 1 col | 1 col |
.g-3 |
3 cols | 2 cols | 1 col |
.g-4 |
4 cols | 2 cols | 1 col |
.g-5 |
5 cols | 3 cols | 1 col |
.g-6 |
6 cols | 4 cols | 2 cols |
.g-8 |
8 cols | 4 cols | 2 cols |
.g-9 |
9 cols | 6 cols | 3 cols |
.g-12 |
12 cols | 6 cols | 3 cols |
Use responsive suffixes for per-breakpoint control: .g-3--lg, .g-2--md, .g-1--sm.
Located in grid/item/. Every element inside .g (or .sg, .sgr, .sgc) automatically inherits this API.
All utilities support --sm, --smd, --md, --mdl, --lg responsive suffixes:
| Column Classes | Row Classes | Effect |
|---|---|---|
.gc-1 β¦ .gc-12 |
.gr-1 β¦ .gr-5 |
grid-column / grid-row: span N |
.gc-f |
.gr-f |
full: 1 / -1 |
.gc-2--lg |
.gr-3--md |
breakpoint-specific spans |
<ul class="g g-3">
<li class="clk gc-2--lg"><article class="crd">Featured (spans 2 on lg)</article></li>
<li class="clk"><article class="crd">Normal</article></li>
<li class="clk"><article class="crd">Normal</article></li>
</ul>
Every grid item exposes these variables at every breakpoint:
| Variable | Breakpoint variants | Controls |
|---|---|---|
--gc / --gi-col |
--gc--sm, --md, --lg |
grid-column |
--gr / --gi-row |
--gr--sm, --md, --lg |
grid-row |
--ga / --area |
--ga--sm, --md, --lg |
grid-area |
--as / --gi-as |
--gi-as--sm, --md, --lg |
align-self |
--js / --gi-js |
--gi-js--sm, --md, --lg |
justify-self |
--o / --gi-o |
--gi-o--sm, --md, --lg |
order |
--gi-mbs |
β | min-block-size |
--gi-mis |
β | min-inline-size |
<!-- Inline CSS-variable override β no utility class needed -->
<li class="clk" style="--gc--lg: span 3; --as--sm: center;"><article class="crd">β¦</article></li>
A dense variable-height gallery. Uses the CSS multi-column fallback with a native grid-lanes upgrade when supported.
.g-ms, .g-gl, .grid-lanes Β· Attributes: [data-recipe~="masonry|gallery|grid-lanes|lanes"]@supports (display: grid-lanes) β display: grid-lanes.column-width: var(--g-min) with break-inside: avoid on children. column-count is deliberately auto (via --g-cols: initial) so column-width drives the column count.<ul class="g g-ms">
<li><figure>Short card</figure></li>
<li><figure>A longer card with more contentβ¦</figure></li>
<li><figure>Short again</figure></li>
</ul>
A single-axis horizontal scroll layout with native CSS scroll snapping.
.slr, .scr(-1β¦4), .crs(-1β¦4), .ctrs Β· Attributes: [data-recipe~="slider|scroll|scroll-N|carousel|carousel-N"].scr-N)Shows exactly N items at once, mathematically subtracting gap widths.
| Class | Items visible |
|---|---|
.slr / .slider / .scr / .scr-1 |
1 (full width) |
.scr-2 |
2 exact |
.scr-3 |
3 exact |
.scr-4 |
4 exact |
.crs-N)Shows N items with the next one peeking to signal scrollability.
| Class | Items + peek |
|---|---|
.crs-1 |
1 card + peek |
.crs-2 |
2 cards + peek |
.crs-3 |
3 cards + peek |
.crs-4 |
4 cards + peek |
<!-- 3 cards visible, 4th peeking from the right -->
<ul class="g crs-3">
<li class="clk"><article class="crd">Slide 1</article></li>
<li class="clk"><article class="crd">Slide 2</article></li>
<li class="clk"><article class="crd">Slide 3</article></li>
<li class="clk"><article class="crd">Slide 4 (peeking)</article></li>
</ul>
Add .ctrs (or .scr-ctrs / .crs-ctrs) to enable native ::scroll-button() arrows where supported.
.dense / .g-d: grid-auto-flow: dense β backfills empty holes with smaller items..inline / .g-i: display: inline-grid.ul.g / ol.g: automatically removes list-style, padding-inline-start, and flow margins.| Class | Alias | Description |
|---|---|---|
.g |
[data-display~="grid"] |
Auto-fit grid. Default min β 256β320px. |
.dense |
.g-d |
Enable dense packing (backfills holes). |
.inline |
.g-i |
display: inline-grid. |
| Class | Desktop | Tablet | Mobile |
|---|---|---|---|
.g-1 |
1 col | 1 col | 1 col |
.g-2 |
2 cols | 1 col | 1 col |
.g-3 |
3 cols | 2 cols | 1 col |
.g-4 |
4 cols | 2 cols | 1 col |
.g-6 |
6 cols | 4 cols | 2 cols |
.g-12 |
12 cols | 6 cols | 3 cols |
.g-2-1 |
β + β | 1 col | 1 col |
.g-1-2 |
β + β | 1 col | 1 col |
.g-3-1 |
ΒΎ + ΒΌ | 1 col | 1 col |
.g-2-3 |
β + β | 1 col | 1 col |
.sr |
sidebar right | stacks | stacks |
.sl |
sidebar left | stacks | stacks |
Gaps are fluid clamp() values by default. Override inline:
| Variable | Controls |
|---|---|
--g-g |
all gaps (row + column) |
--g-cg |
column gap only |
--g-rg |
row gap only |
Per-breakpoint variants: --g-g--sm, --g-cg--md, --g-rg--lg.
| Class | Aliases | Effect |
|---|---|---|
.sg |
.subgrid, .sgr, .subrow |
grid-template-rows: subgrid |
.sgc |
.subcol |
grid-template-columns: subgrid |
All support responsive variants: .sg--md, .sgc--lg, etc.
| Column span | Row span | Full |
|---|---|---|
.gc-1 β¦ .gc-12 |
.gr-1 β¦ .gr-5 |
.gc-f / .gr-f |
Add --sm, --smd, --md, --mdl, --lg suffixes for breakpoint control.
ul.g / ol.g for repetitive card/content grids β list resets come free and each li is a grid item..g-ms for galleries, .scr-N for steps/tiers, .crs-N for product carousels..sr / .sl for docs and blog layouts; .g-2-1 for editorial article + figure.To add a custom .g-7:
.g-7 {
--g-cols--lg: 7;
--g-cols--md: 4;
--g-cols--sm: 2;
--g-min--lg: 0px; /* Force fit β don't apply the floor on large screens */
}
<!-- Breaks at 120px instead of the default ~256px -->
<ul class="g" style="--g-min: 120px">β¦</ul>
<div class="g" style="
--gta: 'hero hero sidebar'
'main main sidebar'
'footer footer footer';
--gtr: 200px 1fr auto;
--gtc: 1fr 1fr 300px;
">
<header style="--ga: hero">Hero</header>
<main style="--ga: main">Main</main>
<aside style="--ga: sidebar">Sidebar</aside>
<footer style="--ga: footer">Footer</footer>
</div>
Navigation: uCss > Source > Modules > Layout > Grid
Modules: Config | Base | Layout | Theming | Typography | Patterns | Utilities
License: MPL-2.0 Copyright: Β© 2026 Shukhrat (Alive π) β€» UNQA
src/lib/
βββ config/ # 1. CONFIGURATION (The Brain)
β βββ root/ # - Semantic Modules
β β βββ colors.css # - Palettes & Themes
β β βββ typography.css # - Fonts & Scales
β β βββ layout.css # - Radius & Spacing
β β βββ patterns.css # - Component Vars
β βββ adapters/ # - CMS Adapters
β β βββ blocksy.css # - Blocksy Theme
β β βββ gutenberg.css # - WordPress Block Editor
β βββ root.css # - Entry Point
β
βββ base/ # 2. BASE (The Foundation)
β βββ html/ # - HTML Engine
β β βββ reset.css # - Normalization
β β βββ typography.css # - Text Defaults
β β βββ flow.css # - Smart Flow Engine
β β βββ lists.css # - List Styles
β β βββ forms.css # - Input Styling
β β βββ helpers.css # - HTML Utilities
β βββ html.css # - Entry Point
β
βββ layout/ # 3. LAYOUT (The Skeleton)
β βββ grid/ # <== YOU ARE HERE
β β βββ base.css # - Core `.g` engine & container queries
β β βββ columns.css # - Explicit presets & asymmetric layouts
β β βββ subgrid.css # - `.sg` / `.sgc` subgrid alignment
β β βββ item/
β β β βββ base.css # - CSS variable API for all grid items
β β β βββ placement.css# - `.gc-*` / `.gr-*` span utility classes
β β βββ recipes/
β β βββ masonry.css # - `.g-ms` / `.g-gl` masonry gallery
β β βββ scroll.css # - `.scr` / `.crs` carousels with snap
β β βββ misc.css # - `.dense`, `.inline`, list resets
β βββ flex/ # - Flex Engine
β βββ section/ # - Structural Sections
β βββ query.css # - Container Query Helper (`.cq` / `.cquery`)
β
βββ patterns/ # 4. PATTERNS (The Components)
β βββ button/
β βββ card/
β βββ ...
β
βββ theming/ # 5. THEMING (The Skin)
β βββ set/
β βββ ...
β
βββ typography/ # 6. TYPOGRAPHY (The Voice)
β βββ title.css
β βββ text.css
β βββ controls/
β
βββ utilities/ # 7. UTILITIES (The Tools)
βββ display.css
βββ position.css
βββ size.css
βββ ...