Skip to main content

Theming & CSS Variables

OGrid is designed to inherit your application's design system. Each UI package integrates with its framework's theming mechanism, and the core grid exposes CSS variables and props for fine-grained control.

CSS Variables

OGrid exposes CSS custom properties that you can override to change the grid's appearance globally or per-instance.

VariableDefaultDescription
--ogrid-selection#217346Cell selection highlight color (active cell border, range background)

Override globally:

:root {
--ogrid-selection: #0066cc;
}

Or scope it to a specific grid instance using the className prop:

.my-grid {
--ogrid-selection: #8b5cf6;
}
<OGrid className="my-grid" columns={columns} data={data} getRowId={(item) => item.id} />

Framework Theming

Each UI package inherits styles from its framework's theme system. OGrid does not fight your theme -- it builds on top of it.

Radix UI (@alaarab/ogrid-react-radix)

Radix is the lightest implementation. It uses CSS Modules (.module.scss) for all grid styles. Override styles with standard CSS specificity or by targeting the grid's class names.

Fluent UI (@alaarab/ogrid-react-fluent)

The Fluent implementation renders with Fluent UI v9 components, which inherit from FluentProvider. Wrap your app in a FluentProvider with your theme:

import { FluentProvider, webLightTheme } from '@fluentui/react-components';
import { OGrid } from '@alaarab/ogrid-react-fluent';

function App() {
return (
<FluentProvider theme={webLightTheme}>
<OGrid columns={columns} data={data} getRowId={(item) => item.id} />
</FluentProvider>
);
}

Fluent also uses CSS Modules for grid-specific styles (cell selection, fill handle, etc.).

Layout Mode

The layoutMode prop controls how the grid sizes itself:

ModeBehavior
'fill' (default)Grid stretches to fill its parent container. The parent must have a defined height.
'content'Grid sizes itself based on content. Width fits columns; height fits rows.
{/* Fill parent container */}
<div style={{ height: 600 }}>
<OGrid layoutMode="fill" columns={columns} data={data} getRowId={(item) => item.id} />
</div>

{/* Size to content */}
<OGrid layoutMode="content" columns={columns} data={data} getRowId={(item) => item.id} />
tip

When using layoutMode="fill", make sure the grid's parent has a defined height (explicit px/vh/%, or flex layout). Without it, the grid will collapse to zero height.

Suppress Horizontal Scroll

To prevent horizontal scrolling (useful when all columns fit the viewport), set suppressHorizontalScroll:

<OGrid suppressHorizontalScroll columns={columns} data={data} getRowId={(item) => item.id} />

This sets overflow-x: hidden on the grid's scroll container.

Per-Cell Styles

Use cellStyle on a column definition to apply inline styles to individual cells. It accepts a static style object or a function for conditional styling:

Static Style

const columns = [
{
columnId: 'amount',
name: 'Amount',
type: 'numeric' as const,
cellStyle: { fontWeight: 600 },
},
];

Dynamic Style (Per-Row)

const columns = [
{
columnId: 'status',
name: 'Status',
cellStyle: (item) => ({
color: item.status === 'Active' ? '#16a34a' : '#dc2626',
fontWeight: 600,
}),
},
];

Numeric Column Alignment

Set type: 'numeric' on a column to right-align cell content automatically:

{
columnId: 'price',
name: 'Price',
type: 'numeric',
valueFormatter: (value) => `$${Number(value).toFixed(2)}`,
}

Custom Wrapper Class

The className prop adds a CSS class to the grid's outermost wrapper element. Use it for scoped styling:

<OGrid className="dashboard-grid" columns={columns} data={data} getRowId={(item) => item.id} />
.dashboard-grid {
border: 1px solid #e5e7eb;
border-radius: 8px;
overflow: hidden;
}

Column Width Control

Control column widths through the column definition:

PropDescription
minWidthMinimum column width in pixels
defaultWidthInitial column width in pixels
idealWidthPreferred width (used for auto-sizing)
{
columnId: 'description',
name: 'Description',
minWidth: 150,
defaultWidth: 300,
}

Users can resize columns by dragging the column border. Listen for resize events with onColumnResized:

<OGrid
columns={columns}
data={data}
getRowId={(item) => item.id}
onColumnResized={(columnId, width) => {
localStorage.setItem(`col-width-${columnId}`, String(width));
}}
/>

Theme presets (new in 2.9)

Instead of mapping --ogrid-* variables to your design system one-by-one, import a pre-built preset that bridges every token at once. Currently the shadcn/Tailwind v4 preset ships with @alaarab/ogrid-react-radix:

import "@alaarab/ogrid-react-radix/styles/index.css";
import "@alaarab/ogrid-react-radix/styles/preset-shadcn.css";

The preset maps --ogrid-bg → var(--card), --ogrid-fg → var(--card-foreground), --ogrid-header-bg → var(--muted), --ogrid-primary → var(--primary), --ogrid-accent → var(--ring), --ogrid-border → var(--border), --ogrid-radius → var(--radius), --ogrid-font → var(--font-sans), and derived states (--ogrid-selected-row-bg, --ogrid-range-bg, etc.) via color-mix(in oklch, var(--ring) 12%, transparent) so they auto-tint to your primary/ring hue.

Both light and dark modes follow your shadcn theme automatically — no hand-authored [data-theme="dark"] override blocks needed. The .dark class on <html> (Tailwind v3+/shadcn convention) is fully supported.

New theming tokens (2.9)

In addition to the colors documented above, 2.8.0 added a radius/font/ring scale that preset-shadcn.css bridges automatically:

VariableDefaultDescription
--ogrid-radius6pxBase corner radius — buttons, inputs, popovers
--ogrid-radius-smcalc(--ogrid-radius * 0.6)Tighter — checkboxes, tags
--ogrid-radius-lgcalc(--ogrid-radius * 1.4)Looser — cards, dialogs
--ogrid-radius-xlcalc(--ogrid-radius * 1.8)Largest — hero surfaces
--ogrid-radius-full9999pxPills, dots
--ogrid-fontinheritFont family for grid chrome
--ogrid-font-size13pxBase body font-size
--ogrid-ringvar(--ogrid-accent)Focus ring color

Override --ogrid-radius once and every corner in OGrid scales (sm/lg/xl are calc()'d from the base).

Dark mode signals

OGrid honors three dark-mode activation signals:

  1. prefers-color-scheme: dark — system preference (auto)
  2. [data-theme="dark"] on any ancestor (explicit)
  3. .dark on any ancestor — Tailwind v3+/shadcn convention (explicit)

Opt out of auto-dark on a deliberate-light-mode app by setting [data-theme="light"] or .light on <html>.