To read old documentation v0.3.2 click here

Introduction

Rows & Columns is a JavaScript layout engine for CSS Grid that works by placing elements directly on grid lines. This gives precise two-dimensional control over child <div> placement without extra wrapper elements.

Unlike traditional frameworks, Rows & Columns lets you define layouts in HTML or JavaScript while keeping your markup flat and semantic. You no longer need excessive <div class='row'> or <div class='column'> wrappers, and CSS code is greatly simplified.

THE OLD WAY (DIV SOUP)

To split a column into two rows, most frameworks require an extra wrapper div.

<div class="row">
  <div class="col-4">Sidebar</div>
  <div class="col-8">
    <!-- Wrapper needed for vertical split -->
    <div class="column">
      <div class="col-6">Top Content</div>
      <div class="col-6">Bottom Content</div>
    </div>
  </div>
</div>
            

THE ROWSCOLUMNS WAY

No wrappers needed. Layout is defined by grid line placement, keeping HTML flat and semantic.

<div layout="Grid.col(30, (70).row(50, 50))">
  <div>Sidebar</div>
  <div>Top Content</div>
  <div>Bottom Content</div>
</div>
            

Live Result

The engine automatically calculates positions and sizes using line placement to fit elements into a recursive grid:

Sidebar
Top Content
Bottom Content

GETTING STARTED

Installation

Rowscolumns is zero-dependency and extremely lightweight (~6KB). You can use it with a package manager or directly in the browser.

1. Package Manager (Recommended)

Best for React, Vue, Next.js, Vite, and modern build pipelines.

npx create-vite@latest my-rc-website
cd my-rc-website
npm install rowscolumns

2. Vanilla HTML/CDN (No Installation required)

To use Rowscolumns in a static HTML file, you must use type="module" or manually download index.mjs from the dist folder.

CDN (Fastest)
Local File
<!-- Import directly from UNPKG (No Installation required)-->
<script type="module">
  // 1. Import Engine
  import { Engine } from 'https://unpkg.com/rowscolumns/dist/index.mjs';
  
  // 2. Initialize (Starts the observer)
  Engine.init();
</script>
<!-- If you manually downloaded the dist folder -->
<script type="module">
  // 1. Import the Engine from your built file
  import { Engine } from './dist/index.mjs';

  // 2. Initialize the Engine
  // (This installs the .col/.row extensions and starts the resize listener)
  Engine.init();

  console.log("RowsColumns Engine Initialized!");
</script>

3. Framework Imports

If you are using a framework, import from the specific sub-package to get the correct wrapper components.

React
Vue 3
Angular
// Import Component + Logic Variables
import { Layout, Grid, lg, sm } from 'rowscolumns/react';
// Import Component + Logic Variables
import { Layout, Grid, lg, sm } from 'rowscolumns/vue';
// Import Standalone Component
import { RowscolumnsComponent } from 'rowscolumns/angular';
// Import Logic
import { Grid, lg, sm } from 'rowscolumns';

CORE CONCEPTS

Grid Basics: Columns & Rows

Before creating grids, it’s important to understand how rows and columns work and the core functionality of the library. The library extends Number.prototype, defines Grid as a constant set to 100, and supports method chaining. Unlike many frameworks, this library prioritises CSS Grid over Flexbox, which makes it truly two-dimensional.

Making Columns

Use .col(a, b, c...) to split space horizontally.

HTML
React
<div layout="Grid.col(20, 80)">
  <div>20</div>
  <div>80</div>
</div>
20
80

Tip : You can make infinite columns Grid.col(10, 10, 10, 10, 10, 10, 10, 10, 10, 10...)

Making Rows

Use .row(a, b, c...) to split space vertically.

HTML
React
<div layout="Grid.row(30, 70)">
  <div>30</div>
  <div>70</div>
</div>
30
70

Making Grid (Recursion)

You can nest rows inside columns infinitely. Here is a 50/50 split, where the right side is split into 3 rows.

HTML
React
<div layout="Grid.col(50, (50).row(10, 10, 30))">
  <div>Left</div>
  <div>Right 1</div>
  <div>Right 2</div>
  <div>Right 3</div>
</div>
Left
Right 1
Right 2
Right 3

Responsive Grid

In Rowscolumns, you define the relative weight of columns rather than fixed pixel widths. This allows you to create layouts that breathe naturally as the screen grows, without ever writing a margin or padding rule.

Dynamic Gutter Logic

In this example, we create a layout where the center content stays stable, but the side "gutters" expand on larger screens to keep the content focused.

  • On Mobile (sm): The grid behaves as a 12-unit system (1 + 10 + 1). The side gutters are thin, giving the main content maximum room.
  • On Desktop (lg): The grid automatically shifts to an 18-unit system (4 + 10 + 4). The content remains centered, while the side gutters grow to create a professional, wide-screen feel.
HTML (Inline Syntax)
React
<!-- 
  The side columns take 1 unit of weight on mobile 
  and expand to 4 units on large screens. 
-->
<div layout="Grid.col({ sm: 1, lg: 4 }, 10, { sm: 1, lg: 4 })">
  <div>Side Gutter</div>
  <div>Main Content (10 Units)</div>
  <div>Side Gutter</div>
</div>
<Layout 
  layout={Grid.col(
    { sm: 1, lg: 4 }, 
    10, 
    { sm: 1, lg: 4 }
  )}
>
  <div>Side Gutter</div>
  <div>Main Content</div>
  <div>Side Gutter</div>
</Layout>

Visual Demo: Resize your browser window to see the blue content area stay stable while the gray gutters expand.

Gutter
Main Content (Weight: 10)
Gutter

Tip: Because the weights are proportional, the engine automatically calculates the percentages. You don't need to worry about the total sum; just focus on the ratio between parts.

Layout Modification

With native execution in v1.2.0, layout modification becomes intuitive and math-driven. You can define column sizes using fractions, decimals, and standard CSS units directly. This allows for faster, cleaner, and more flexible layout adjustments.

1. Native Math (Fractions)

Instead of calculating percentages manually, simply type fractions. This allows you to define any number of columns, beyond the usual 12 or 24.

HTML
React
<div layout="Grid.col(1/3, 1/3, 1/3)">
<Layout layout={Grid.col(1/3, 1/3, 1/3)}>
1/3
1/3
1/3

2. CSS Units (Fixed Sizes)

You can pass strings to use standard CSS units like px, rem, or %. These act as fixed tracks.

HTML
React
<div layout="Grid.col('150px', 1, '150px')">
<Layout layout={Grid.col('150px', 1, '150px')}>
150px
Fluid (1fr)
150px

3. Decimals

The engine treats 0.5 exactly the same as 50 or 1/2. It calculates the ratio based on the total sum of siblings.

HTML
React
<div layout="Grid.col(0.7, 0.3)">
<Layout layout={Grid.col(0.7, 0.3)}>
0.7
0.3

4. Variables (Golden Ratio)

The engine provides built-in variables: lg (61.8) and sm (38.2).

HTML
React
<div layout="Grid.col(lg, sm)">
<Layout layout={Grid.col(lg, sm)}>
lg
sm

5. Mixed Units & Recursion

You can mix fixed CSS strings, auto, and ratios. You can also apply recursion directly to string units (e.g. splitting a '200px' column into rows).

HTML
React
<div layout="Grid.col(
  ('200px').row(1,1), // Fixed col split into 2 rows
  'auto', 
  'auto'
)">
<Layout layout={Grid.col(
  ('200px').row(1,1), 
  'auto', 
  'auto'
)}>
200px (Row 1)
200px (Row 2)
Auto
Auto

Customisation

External Styling (Classes & IDs)

While .props() is great for quick adjustments, you often want to control the container's dimensions using standard CSS classes or IDs. This keeps your layout logic separate from your sizing logic.

The framework respects all standard class names and IDs applied to the element.

HTML + CSS
React
<style>
  /* Standard CSS */
  .hero-container {
      height: 300px;
      width: 80%;
      margin: 0 auto; /* Center it */
      border: 2px solid red;
  }
</style>

<!-- Apply class here -->
<div class="hero-container" layout="Grid.col(50, 50)">
   <div>Left</div>
   <div>Right</div>
</div>
import './App.css'; // Contains .hero-container styles

export default function App() {
  return (
    <Layout 
      className="hero-container" 
      layout={Grid.col(50, 50)}
    >
       <div>Left</div>
       <div>Right</div>
    </Layout>
  );
}

(The container below is restricted to 80% width and centered via CSS)

50%
50%

Easy Recursive Loops

To make 12 equal columns manually would be tedious. Because v1.2.0 uses native JS, you can generate arrays dynamically!

HTML
React
<script>
  window.twelveCols = Array(12).fill(1); 
</script>

<div layout="Grid.col(...twelveCols)">
   <!-- 12 Divs -->
</div>
1
2
3
4
5
6
7
8
9
10
11
12

Utilities Methods

When using Grid().row() and Grid().col() recursively, layouts may not align as expected because of the declarative syntax. To handle these cases, Rowscolumns provides 4 utility methods that let you style, offset, or span grid items without breaking the layout. These methods work by applying CSS directly through JavaScript.

Styling Methods

Styling methods are only for styling the container it uses CSS property. If inline styling is written it will be overridden by the these styling methods.

.props({ styles })

Apply CSS properties to the grid container (like gap, padding, margins).

HTML
React
Grid.col(50, 50).props({ gap: '20px', padding: '10px' })
Grid.col(50, 50).props({ gap: '20px', padding: '10px' })

.childProps({ styles }, [indices])

Apply CSS properties to specific children. Indices are 1-based.

HTML
React
Grid.col(33, 33, 33).childProps({ background: 'turquoise' }, [2])
Grid.col(33, 33, 33).childProps({ background: 'turquoise' }, [2])
1
2 (Styled)
3

Tip : You can select multiple children always. .childProps({ background: 'turquoise' }, [1, 3]) This will apply to 1st and 3rd children.

Markup Methods

Markup methods affect the structure of the grid, rather than just its appearance. They modify how grid slots are created and positioned.

.offset([indices])

Creates "Ghost" slots. Useful for creating gaps. In this demo, we skip the middle slot (Index 2), forcing the 2nd Box to jump to the 3rd slot.

<Layout layout={Grid.col(33, 33, 33).offset([2])}>
  <div>1</div>
  <div>2</div>
</Layout>
1
3

Tip : You can also use it directly on the element Grid.col(33, (33).offset(), 33)

.span({ direction }, [indices])

Expands an item across multiple tracks (Spanning). Directions: top (top), right (right), bottom (bottom), left (left).

Examples:
.span({right:1}, [1]) spans the first child to the right;
.span({left:1}, [2]) spans the second child to the left;
.span({bottom:1}, [1, 2])spans first and second child downward;
.span({top:1}, [2]) upward by 2.

The second parameter targets child indices (1-based), so [1] is the first child, [2] the second, and multiple can be set like [1,3].

<Layout layout={Grid.col(33, 33, 33).offset([2]).span({right:1}, [1])}>
  <div>1</div>
  <div>2</div>
</Layout>
1
2

LAYOUTS

Advanced Layout Patterns

The "Holy Grail" (12-Column Style)

Instead of arbitrary percentages, you can use the classic 12-column system fractions. Here, we create a layout with a Header, a 3-column Sidebar, a 9-column Content area, and a Footer. Where Footer and Header are taken 1-rows and Body 2-rows. This makes a perfect two dimensional

Grid.row(
  1/4,                           // Header 1 of 4
  (2/4).col(3/12, 5/12),         // Body 2 of 4 with columns: Sidebar (3/12) + Content (5/12)
  1/4                           // Footer 1 of 4
)
Header (Span 12)
Sidebar (Span 3)
Main Content (Span 9)
Footer (Span 12)

Deep Recursion (Mondrian Style)

Grid.col(50, (50).row(50, (50).col(50, 50)))
Left
Top
Btm Left
Btm Right

Golden Ratio

You can create a golden-ratio layout (Fibonacci spiral) using the built-in lg and sm variables (lg = 61.8, sm = 38.2).

Each split rotates the layout, and the smaller section becomes the container for the next split, producing a centered spiral:

Grid.col(
  lg,
  sm.row(
    lg,
    sm.col(
      sm.row(
        sm.col(
          lg,
          sm.row(
            lg,
            sm.col(
              sm.row(
                sm.col(lg, sm)
              , lg)
            , lg)
          )
        , lg)
      , lg)
    , lg)
  )
)

For a more visual effect, you can also add rounded corners to the children to create the spiral curve:

Complex Symmetry

Creating a symmetrical 23-element layout in standard HTML requires complex nesting or manual percentage calculations. With Rowscolumns, you just mirror the layout string.

Comparison: In standard CSS, you would need to calculate width: 4.34%, width: 8.69%, etc., or use complex Flexbox nesting. Here, it is one line of logic.

Grid.col( 
  (10).row(1,1,1,1,1,1,1,1),  // Left Wing (8 rows)
  (20).row(1,1,1),            // Inner Left (3 rows)
  40,                         // Center (1 big col)
  (20).row(1,1,1),            // Inner Right (3 rows)
  (10).row(1,1,1,1,1,1,1,1)   // Right Wing (8 rows)
)

Massive Rhythm (20 Columns)

Handling 20+ columns in native CSS Grid often involves tedious repeat() syntax or manual fractional math. Rowscolumns handles the math for any number of elements instantly.

This example generates 20 columns that progressively grow larger, creating a visual rhythm.

Grid.col(1, 2, 3, 4, 5, 6, 7 ... 20)

Asymmetrical Balance

Standard grids often feel rigid. By using a 6-column base and the .span() method, elements can cross the center axis, creating dynamic, asymmetrical balance.

This layout uses .offset() to create negative space and .span() to bridge columns.

Grid.col(
  (1).row(1,1,1,3).span({right:1},[3,4]),
  (1).row(2,1,3).span({right:1},[1]).offset([2,3]),
  (1).row(2,2,1,1).offset([1]).span({right:1},[1]),
  (1).row(1,1,2,2).offset([3]).span({right:1},[3]),
  (1).row(3,1,2).offset([3]).span({right:1},[2,1]),
  (1).row(3,1,1,1).offset([1,2])
).props({gap:'5px'})

Or more simplified.

Grid.col(
  (1).row(1,1,1,3),
  (1).row(2,1,3),
  (1).row(2,2,1,1),
  (1).row(1,1,2,2),
  (1).row(3,1,2),
  (1).row(3,1,1,1)
)
.span({right:1},[3,4,5,6,11,12,13])
.offset([6,7,8,14,18,19,20])

DEVELOPMENT

Responsive Design

Rowscolumns v1.6.X introduces Inline Responsive Objects. While you can still use multiple attributes, you can now define full responsiveness within a single method using the { breakpoint: value } syntax.

Attribute / KeyBreakpointDevice
xs / layout0pxMobile (Default)
sm / layout-sm≥ 576pxLarge Phones
md / layout-md≥ 768pxTablets
lg / layout-lg≥ 992pxLaptops
xl / layout-xl≥ 1200pxDesktops

The 'none' Keyword

The 'none' keyword is a special layout value. It doesn't just hide the element; it collapses the grid track entirely so that gaps and margins disappear, making surrounding elements slide into place perfectly.

Real World Example: The Navbar

Let's build a responsive navigation bar using the new inline syntax:

  • Mobile: Logo (Left), Menu (Right). The Search Bar is hidden and its space is collapsed.
  • Desktop: Logo, a large Search Bar in the middle, and the Menu.
HTML (v1.6.X)
React
<!-- 
  The 2nd column uses an object:
  - sm: 'none' (Hidden, no space taken)
  - md: 1 (Takes available space on tablets+)
-->
<div layout="Grid.col(auto, { sm: 'none', md: 1 }, auto).props({ gap: '15px' })">
   <div>Logo</div>
   <input type="text" placeholder="Search..." />
   <button>Menu</button>
</div>
<Layout 
  // Unified logic in one attribute
  layout={Grid.col(
    'auto', 
    { sm: 'none', md: 1 }, 
    'auto'
  ).props({ gap: '15px' })} 
>
   <div>Logo</div>
   <input type="text" placeholder="Search..." />
   <button>Menu</button>
</Layout>

Resize your browser window to see the Search Bar appear and disappear without leaving "ghost" gaps!

LOGO
Search documentation...
MENU

Pro Tip: Responsive Multi-Weights

You can even change the relative weights of columns dynamically:

Grid.col({ sm: 1, md: 5, lg: 10 })

This single column will take 1 unit of space on mobile, 5 on tablets, and 10 on large screens.

Multi-Framework Support

Rowscolumns provides dedicated wrappers for the modern web ecosystem. The logic remains the same, but the syntax adapts to your framework.

React
Vue 3
Angular
npx create-vite@latest my-rc-website
cd my-rc-website
npm install rowscolumns

1. Setup

import { Layout, Grid, lg, sm } from 'rowscolumns/react';

2. Responsive Layout

Pass objects directly to props. Note that we keep the dash syntax for consistency.

export const App = () => {
  return (
    <Layout 
      // Mobile (Default)
      layout={Grid.col(100)}
      
      // Tablet (768px+)
      layout-md={Grid.col(50, 50)}

      // Desktop (992px+)
      layout-lg={Grid.col(lg, sm)}
    >
       <div>Box 1</div>
       <div>Box 2</div>
    </Layout>
  );
};

1. Setup

<script setup>
import { Layout, Grid, lg, sm } from 'rowscolumns/vue';
</script>

2. Responsive Layout

Use standard Vue binding : to pass the layout objects.

<template>
  <Layout 
    :layout="Grid.col(100)"
    :layout-md="Grid.col(50, 50)"
    :layout-lg="Grid.col(lg, sm)"
  >
     <div>Box 1</div>
     <div>Box 2</div>
  </Layout>
</template>

1. Setup (Component)

Import the standalone component and define your grids in the class.

import { Component } from '@angular/core';
import { RowscolumnsComponent } from 'rowscolumns/angular';
import { Grid, lg, sm } from 'rowscolumns';

@Component({
  standalone: true,
  imports: [RowscolumnsComponent],
  templateUrl: './app.component.html'
})
export class AppComponent {
  mobile = Grid.col(100);
  tablet = Grid.col(50, 50);
  desktop = Grid.col(lg, sm);
}

2. Template (HTML)

Bind the class properties to the component inputs.

<rc-layout 
  [layout]="mobile" 
  [layout-md]="tablet" 
  [layout-lg]="desktop"
>
   <div>Box 1</div>
   <div>Box 2</div>
</rc-layout>

3. Run

npm run dev

Now visit http://localhost:5173/

Layout vs. Components

Rowscolumns is strictly a Layout Engine. It decides where elements go, not what they look like.

This means it works perfectly with external CSS, CSS Modules, or UI Libraries (Bootstrap, Material, Tailwind).

External CSS / Modules

You define the structure in the attribute, and the look in your CSS file.

<!-- CSS -->
<style>
  .card { background: white; shadow: 0 4px 10px rgba(0,0,0,0.1); }
  .btn  { background: blue; color: white; }
</style>

<!-- HTML -->
<div layout="Grid.col(50, 50)">
   <div class="card">Product Info</div>
   <button class="btn">Buy Now</button>
</div>

Using with UI Kits (Bootstrap / Tailwind)

Because Rowscolumns doesn't pollute the children with layout classes, you can drop in components from other frameworks directly.

<div layout="Grid.col(33, 33, 33).props({gap:'20px'})">
   
   <!-- Tailwind Card -->
   <div class="bg-white rounded-lg shadow-lg p-6">
      Tailwind Card
   </div>

   <!-- Bootstrap Button -->
   <button class="btn btn-primary btn-lg">
      Bootstrap Button
   </button>

   <!-- Material UI style -->
   <div class="mui-paper elevation-3">
      Material Component
   </div>

</div>

OTHERS

Support Rows & Columns

If you find Rows & Columns useful and want to support its development, your contribution helps add new features, and improve the framework.

Global Support

Support from India

  • UPI / Google Pay / PhonePe / Paytm: abhimm5@upi

Even if you cannot donate, sharing the project, starring it on GitHub, or contributing feedback helps a lot!

About

Rowscolumns was created to bridge the gap between Design Tools (which think in groups, frames, and auto-layout) and CSS Code (which thinks in classes and flow).

By moving layout logic into a recursive mathematical structure, we keep the DOM clean and the styles separated.

License

Rowscolumns is open-source software licensed under the MIT License. You are free to use it in personal and commercial projects.

Community & Contribution

Built by Abhimm5. Contributions are welcome on GitHub.

Star on GitHub View on NPM