Jeet's Ratio-Based Grid: Why It Works and When to Move On
Jeet's ratio-based grid eliminates breakpoint classes but is unmaintained since 2018. This post shows how its fluid columns work, provides a Stylus-to-CSS-Grid migration example, and outlines when to move on.
17 Apr 2026, 18:18 UTC

The problem with breakpoint-heavy grids
Most CSS grid systems force you to write separate classes for mobile, tablet, and desktop. You end up with markup like col-md-6 col-lg-4 and a mental model that ties layout to fixed viewport ranges. When a design calls for a sidebar that moves above content on small screens, you add wrapper divs or utility classes, bloating both HTML and CSS.
Jeet, a Stylus/Sass grid framework last updated in 2018, took a different approach: it replaces column counts with ratios. You write col(1/3) and get a fluid 33.33% column that recalculates automatically when nested. No breakpoint classes, no extra wrappers for source-order changes. That simplicity is appealing, but the framework is unmaintained and its Stylus dependency conflicts with modern build tools. This post walks through how Jeet's ratio system works, shows a worked example, and outlines a practical migration path to native CSS Grid.
How ratio-based columns work
Jeet's core mixin is span() (Stylus) or @include span() (Sass). You pass a fraction, decimal, or percentage — span(1/2), span(0.5), or span(50%) all produce the same flexible column with consistent gutters. The framework calculates the width and the left margin (gutter) from a single gutter value defined in the container.
Because the math is ratio-based, nesting multiplies ratios. A col(1/2) inside a col(1/3) yields a column that is 1/6 of the root container. This is powerful but differs from additive systems like Bootstrap's 12-column grid, where nesting resets the column count.
Fluid responsive behavior without breakpoints
Jeet's shift() and unshift() helpers move columns using positive/negative margins derived from the same ratio system. For example, a sidebar that appears before content on mobile but after on desktop can be achieved by shifting the content column on larger viewports — no extra wrapper markup, no media queries in your component styles. The container's center() mixin sets a max-width and auto margins, equivalent to max-width: 1200px; margin-inline: auto; in plain CSS.
Worked example: Stylus to CSS Grid
Below is a minimal Stylus file that uses Jeet for a two-column layout with a nested inner column. Save it as layout.styl in a project that has jeet installed (npm i jeet@7.2.0).
@import 'jeet'
.wrap
center(max-width: 1200px)
.main
col(2/3)
.sidebar
col(1/3)
.nested
col(1/2) // inside .main, this becomes 1/3 of viewport
Compile from the project root (where node_modules lives) with:
stylus --include node_modules layout.styl -o layout.css
Expected output (expanded):
.wrap {
max-width: 1200px;
margin-left: auto;
margin-right: auto;
}
.main {
width: 66.6666%;
margin-left: 1.6666%;
}
.sidebar {
width: 33.3333%;
margin-left: 1.6666%;
}
.main .nested {
width: 50%;
margin-left: 1.6666%;
}
Notice the nested .nested width is 50% of its parent (.main), which equals 33.33% of the viewport — the multiplicative ratio in action.
Equivalent CSS Grid layout (no preprocessor needed):
.wrap {
max-width: 1200px;
margin-inline: auto;
display: grid;
grid-template-columns: 2fr 1fr; /* 2/3 and 1/3 */
gap: 1.6666%; /* approximates Jeet's gutter */
}
.main .nested {
display: grid;
grid-template-columns: 1fr 1fr; /* 1/2 each */
gap: 1.6666%;
}
The Grid version uses fr units for ratios and gap for gutters. It eliminates the preprocessor dependency and works in all modern browsers.
Trade-offs and limitations
- Unmaintained: The last npm publish (
jeet@7.2.0) dates to March 2018. No updates for PostCSS, Dart Sass 2.x, or CSS Grid fallback strategies. - Rounding errors: Mixing fixed-pixel gutters with fluid ratios inside the same container can produce off-by-one-pixel issues in older browsers.
- Stylus dependency: The Stylus version relies on the pre-1.0
styluspackage, which may conflict withvite-plugin-stylusoresbuildStylus plugins. - No TypeScript definitions: IDE autocomplete requires manual
.d.tsfiles or a Stylus/Sass language server.
If your team already uses Jeet and the build pipeline is stable, the ratio system remains a concise way to express fluid layouts. For new projects or when upgrading tooling, the maintenance burden outweighs the convenience.
Actionable migration checklist
- Audit Jeet usage: Search for
col(,span(,shift(,center(in your Stylus/Sass files. - Map each component to Grid: Replace
col(1/3)withgrid-column: span 1inside a parent that declaresgrid-template-columns: repeat(3, 1fr)orgrid-template-columns: 1fr 1fr 1fr. Usegapfor gutters. - Handle source-order changes: Use
grid-column-start/grid-column-endororderinstead ofshift()/unshift(). - Test in a feature branch: Compile the migrated CSS and compare rendered widths with the Jeet output (use browser dev tools to inspect computed
widthandmargin-left). - Remove Jeet from dependencies: Once all components pass visual regression tests, uninstall
jeetand the legacystyluspackage.
To verify the current Jeet output yourself, run the Stylus compile command above and check that .main shows width: 66.6666% and margin-left: 1.6666%. For Sass projects, use sass --style=expanded input.scss output.css after @use 'jeet' as *; and confirm width: 25%; margin-left: 2.0833%; for @include span(1/4).
Closing thought
Jeet's ratio-based API solved a real problem: writing responsive layouts without breakpoint soup. Today, native CSS Grid provides the same fluidity with zero dependencies and better tooling support. If you're maintaining a Jeet codebase, the migration path is straightforward — replace ratio mixins with fr units and gap, then drop the preprocessor. The result is lighter, future-proof CSS that any browser can read.