Grid-Pro v3.5.1

By PointPSD

Base-10 proportional layout engine based on the actual container width. No media queries. No breakpoints. A single CSS class.

Base-10 Container-based Masonry Zero-config ~30 KB

Test in real time

5-5 3-7 3-4-3 7-3 2-6-2 1-2-4-2-1 2-2-2-2-2 4-6 1-2-7 4-2-1 2-1 1-1-1-1-1 3-2-1
12px
(0 = auto)
Width: -- -- columns --

What is Grid-Pro?

The problem

With native CSS Grid, repeat(auto-fit, minmax(...)) creates equal columns. It's impossible to express relative proportions (this column = 2x wider than that one).

Media queries force you to think in viewport size, not container size. A component in a 300px sidebar and the same component full-width receive the same breakpoints.

The Grid-Pro solution

A single CSS class is enough: grid-1-2-7. The numbers are weights on a base-10 scale: each unit equals 10% of the container width. Here, 10% + 20% + 70% = 100% of the row.

When the sum of weights exceeds 10 (100%), extra children wrap to the next row automatically. No media queries, no breakpoints — the proportions are fixed percentages of the container.

<!-- Instead of writing complex CSS... -->
<div class="grid-1-2-7">
  <div>10% (1)</div>
  <div>20% (2)</div>
  <div>70% (7)</div>
</div>

<!-- Result: repeat(10, 1fr) + span 1, span 2, span 7 -->

Base-10 scale

Each weight unit equals 10% of the container width. A row is complete when the sum reaches 10 (100%). grid-5-5 creates two 50% columns. grid-2-6-2 creates a 20%-60%-20% layout. Weights beyond 10 per row wrap to the next line.

Base-10 mode (sum = 10)
grid-5-5 — 2 equal columns (50% + 50%)
5
5
grid-3-7 — 30% / 70% split
3
7
grid-2-6-2 — sidebar - content - sidebar (20% - 60% - 20%)
Sidebar
Main content
Sidebar
grid-1-2-4-2-1 — pyramid (10% - 20% - 40% - 20% - 10%)
1
2
4
2
1
Ratio mode (sum < 10)

When the sum of weights is less than 10, Grid-Pro switches to ratio mode: weights become CSS fr units, stretched to fill 100% of the container. grid-4-2-1 → 4fr 2fr 1fr (57% + 29% + 14%).

grid-4-2-1 — proportional 4:2:1 ratio (57% + 29% + 14%)
4
2
1
grid-2-1 — 2/3 + 1/3 split (67% + 33%)
2
1
grid-1-1-1-1-1 — 5 equal columns via ratio (20% each)
1
1
1
1
1
<!-- Base-10 (sum=10) -->
<div class="grid-2-6-2 gap-2">
  <div>Sidebar</div>
  <div>Main content</div>
  <div>Sidebar</div>
</div>

<!-- Ratio (sum=7 → 4fr 2fr 1fr) -->
<div class="grid-4-2-1 gap-2">
  <div>57%</div>
  <div>29%</div>
  <div>14%</div>
</div>

Proportional at any width

Grid-Pro uses a base-10 grid system: repeat(10, 1fr). Each weight unit represents 10% of the container width. The columns always fill the container proportionally — no breakpoints, no collapse.

Resize the window or drag the slider below to see the proportions hold at every width.

1200px
1
2
4
2
1
Current state: -- columns --
Philosophy: no media queries are used. The proportions are fixed percentages of the container (each weight = 10%). The same component in a narrow sidebar and full-width keeps the same column ratios — automatically.

Gap system

Use the utility classes gap-0 through gap-7 for uniform spacing, or gap-x-* / gap-y-* to control horizontal and vertical separately. You can also use the CSS variable --gridpro-gap directly.

gap-0 (0px)
A
B
C
gap-3 (16px)
A
B
C
gap-6 (48px)
A
B
C
gap-x-6 gap-y-1 — large horizontal gap, small vertical
1
2
3
4
5
6
ClassCSS VariableValue
gap-0--gridpro-gap0px
gap-1--gridpro-gap4px
gap-2--gridpro-gap8px
gap-3--gridpro-gap16px
gap-4--gridpro-gap24px
gap-5--gridpro-gap32px
gap-6--gridpro-gap48px
gap-7--gridpro-gap64px

Vertical stacking (Pinterest-style)

Add the class gridpro-masonry to the container. The engine measures the actual height of each child and calculates the number of micro-rows (4px) needed via grid-row-end: span N. Items stack vertically filling gaps.

80px
150px
100px
200px
120px
170px
90px
140px
110px
<div class="grid-3-4-3 gridpro-masonry gap-2">
  <div style="min-height: 80px">A</div>
  <div style="min-height: 150px">B</div>
  <div style="min-height: 100px">C</div>
  <!-- ... -->
</div>
Note: masonry is based on getBoundingClientRect().height. Images must have explicit dimensions or be fully loaded before apply() runs.

More or fewer children than weights

Fewer children

Only the weights matching available children are used. grid-2-6-2 with 2 children assigns span 2 and span 6 (the 3rd weight is ignored).

Child 1 (span 2)
Child 2 (span 6)
grid-2-6-2 + 2 children = span 2 + span 6
More children

Extra children wrap to the next row, cycling through the weights pattern (CSS Grid auto-placement).

Row 1 — A
Row 1 — B
Row 2 — C
Row 2 — D
grid-3-7 + 4 children = 2 rows

CustomEvent gridpro:applied

On every layout change, the container emits a CustomEvent with a detail object containing the grid state. Useful for animating transitions, updating an external calculation, or logging.

const el = document.getElementById('ma-grille');

el.addEventListener('gridpro:applied', function(e) {
  console.log(e.detail.columns);  // 3 (number of first-row columns)
  console.log(e.detail.template); // "1fr 2fr 7fr"
  console.log(e.detail.collapsed);// always false (no collapse)
});
PropertyTypeDescription
detail.columnsnumberNumber of columns in the first row
detail.templatestringFirst-row weights as fr units (e.g.: "1fr 2fr 7fr")
detail.collapsedbooleanAlways false (no responsive collapse in base-10 mode)

Programmatic usage

The plugin auto-initializes on load. For dynamic elements (created after DOM ready), use the public API.

GridPro.init(el, options?)

Attaches observers (ResizeObserver + MutationObserver) and applies the grid once. Only runs once per element (internal flag).

const el = document.getElementById('dynamic-grid');

GridPro.init(el, {
  debounce:         150,  // resize debounce in ms (default: 80)
  autoObserve:     true, // attach observers (default: true)
  equalHeight:     false,
  masonryBaseRow:  4,
  migrateLegacyRows: true
});
OptionTypeDefaultDescription
debouncenumber80ResizeObserver debounce delay (ms)
autoObservebooleantrueIf false, no observers (manual control)
equalHeightbooleanfalseForce all items to the tallest item's height
masonryBaseRownumber4Base micro-row height for masonry calculations (px)
migrateLegacyRowsbooleantrueAuto-unwrap legacy .gridpro-row wrappers
GridPro.apply(el)

Recalculates and applies the grid immediately. Does not attach observers. Useful after a class or content change you manage yourself.

// After a dynamic class change
el.className = 'grid-3-4-3';
el._gridproSig = null; // invalidate cache
GridPro.apply(el);
GridPro.destroy(el)

Disconnects all observers (ResizeObserver + MutationObserver), removes inline grid styles, removes .gridpro-active, and dispatches a gridpro:destroyed event.

GridPro.destroy(el);
// el is now back to its original state
GridPro.refresh(el)

Invalidates the signature cache and re-applies the grid immediately. Shortcut for el._gridproSig = null; GridPro.apply(el).

GridPro.refresh(el);
// signature invalidated + grid re-applied
GridPro.initAll(root?, options?)

Initializes all Grid-Pro containers found within a root element (defaults to document). Useful for dynamically loaded sections.

// Initialize all grids in a dynamically loaded section
const section = document.getElementById('new-section');
GridPro.initAll(section);
GridPro.configure(options)

Sets global defaults for all Grid-Pro instances. Call before init() or initAll().

GridPro.configure({
  debounce: 100,
  mobileBreakpoint: 640,
  masonryBaseRow: 8
});
OptionTypeDefaultDescription
debouncenumber80ResizeObserver debounce delay (ms)
mobileBreakpointnumber768Container width threshold for mobile single-column mode (px)
masonryBaseRownumber4Base micro-row height for masonry calculations (px)
Force grid mode

By default, the mode is auto-detected from the weight sum. Add .gridpro-ratio or .gridpro-base10 to override.

ClassEffect
.gridpro-ratioForce ratio mode (fr units, 100% width)
.gridpro-base10Force base-10 mode (repeat(10, 1fr) + span)
.gridpro-masonryEnable masonry vertical packing
.gridpro-equal-heightForce all items to the tallest item's height
Equal-height mode

Add the class gridpro-equal-height (or pass { equalHeight: true }) to make all items match the tallest item's height. Incompatible with masonry.

Behavior without JavaScript

If JavaScript fails to load, the following CSS rule takes over automatically. The layout won't be proportional but will remain functional thanks to auto-fit. As soon as JS initializes and adds .gridpro-active, the fallback is neutralized.

/* Fallback no-JS */
[class*="grid-"]:not(.gridpro-active) {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--gridpro-gap, 12px);
}

Dashboard Analytics

Grid-Pro makes it easy to build responsive dashboard layouts. Here's how to structure a complete analytics interface using only Grid-Pro classes — KPI cards, charts, and data panels adapt fluidly to any container width.

grid-5-5 — KPI cards (2x2 responsive grid)
Total visits
Unique visitors
Countries
Today
grid-7-3 — line chart + doughnut (70% / 30%)
Line chart — Visits per day
Doughnut — By country
grid-5-5 — two bar charts (50% / 50%)
Bar chart — By hour
Bar chart — Top cities
<!-- Dashboard layout with Grid-Pro -->

<!-- KPI -->
<div class="grid-5-5 gap-2">
  <div class="kpi-card">...</div>
  <div class="kpi-card">...</div>
  <div class="kpi-card">...</div>
  <div class="kpi-card">...</div>
</div>

<!-- Charts: 70% + 30% -->
<div class="grid-7-3 gap-2">
  <div><!-- Line chart --></div>
  <div><!-- Doughnut --></div>
</div>

<!-- Charts: 50% + 50% -->
<div class="grid-5-5 gap-2">
  <div><!-- Bar chart --></div>
  <div><!-- Bar chart --></div>
</div>
Data filtering

The admin dashboard includes server-side filtering to exclude specific IPs (e.g. 127.0.0.1) and cities from all analytics — KPI counts, charts, and data tables are all computed from the filtered dataset.

Tip: Combine grid-7-3 for main+sidebar chart layouts and grid-5-5 for equal panels. The proportions remain stable regardless of the container width — ideal for embedded dashboard widgets.

Installation

CDN
<link rel="stylesheet"
 href="https://cdn.jsdelivr.net/npm/@darkhan666/grid-pro@3.5.1/dist/grid-pro.min.css">
<script src="https://cdn.jsdelivr.net/npm/@darkhan666/grid-pro@3.5.1/dist/grid-pro.min.js"></script>
npm
npm install @darkhan666/grid-pro

import GridPro from "@darkhan666/grid-pro";
import "@darkhan666/grid-pro/css";
Manuel
<link rel="stylesheet"
 href="/assets/css/grid-pro.css">
<script src="/assets/js/grid-pro.js"></script>
Compatibility: Chrome 64+, Firefox 69+, Safari 13.1+, Edge 79+. Requires CSS Grid, ResizeObserver and MutationObserver.