PGrid docs

Styling

PGrid ships a thin, opinionated default stylesheet and exposes every structural element through a stable class. You style the grid by overriding those classes, attaching your own classes via config, or both.

Three places to style

  1. Per cell, via config. Use cssClass on a column, row, or cell. Most styling lives here — it's data-driven and stays close to the grid declaration.
  2. Globally, by overriding pgrid classes. The grid emits a stable set of .pgrid-* classes; override them in your own stylesheet to retheme.
  3. Programmatically, via extensions. Use the cellAfterRender hook to add classes based on data (status-based row colors, hover effects, etc). See Extensions.
Don't fight the layout. The 6-pane layout, scrollbars, and absolute positioning are load-bearing — overriding the structural CSS (positions, widths, scrollbar dimensions) will break virtualization. Stick to colors, borders, fonts, padding, and your own additive classes.

CSS class reference

Every class PGrid emits, and what it's for.

Container & panes

.pgridThe root element you mounted into.
.pgrid-content-paneWrapper holding all six panes.
.pgrid-top-left-pane / -top-pane / -left-pane / -center-pane / -bottom-left-pane / -bottom-paneThe six freeze panes. Each contains a matching -inner wrapper.

Cells

.pgrid-cellEvery cell — header and body. Absolutely positioned within its pane.
.pgrid-cell-contentInner wrapper that holds the cell text. Centered vertically. Style padding/text-align here.
.pgrid-cell-selectionDefault selection class. Override or replace via selection.cssClass.
.pgrid-row-headerAdded to every cell whose row is in the header range.
.pgrid-text-overflow-host + .pgrid-text-ellipsis / -clip / -wrapSet by TextOverflowExtension. Don't override unless you know what you're doing.

Editor & scrollbar

.pgrid-cell-text-editorThe default inline text input.
.pgrid-col-resize-handleThe drag handle injected by ColumnResizeExtension.
.pgrid-hscroll / -vscroll / -hscroll-thumb / -vscroll-thumbCustom scrollbar tracks and thumbs.

Cell data-* attributes

Useful for selectors that target specific positions:

data-row-indexVisible row index (header rows are 0..headerRowCount-1).
data-col-indexColumn index.
/* Style every cell in column 3 without using cssClass */
.pgrid-cell[data-col-index="3"] { background: #fef3c7; }

Per-column / row / cell styling

The recommended way to style — declarative and data-driven. PGrid concatenates these classes in priority order: cell > row > column. All matching classes are applied; later ones win on conflicting properties.

const grid = new PGrid({
    columns: [
        { id: 0, field: 'id',     title: 'ID',     cssClass: 'col-id' },
        { id: 1, field: 'salary', title: 'Salary', cssClass: 'col-money' }
    ],
    rows: [
        { i: 5, cssClass: 'row-summary', height: 40 }
    ],
    cells: [
        { r: 5, c: 1, cssClass: 'cell-grand-total' }
    ],
    /* … */
});
.col-money {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: #15803d;
}

.row-summary {
    font-weight: 600;
    background-color: #f1f5f9;
    border-top: 2px solid #cbd5e0;
}

.cell-grand-total {
    background-color: #fef3c7;
}

Theming

Two practical patterns:

Scope a theme to a wrapper class

Wrap your grid in a container with a theme class, then scope your overrides under it. This lets you switch themes by toggling a single class — and host multiple themed grids on the same page.

<div class="theme-dark">
    <div id="grid" style="height: 400px;"></div>
</div>
.theme-dark .pgrid-cell {
    background: #0f172a;
    color: #e2e8f0;
    border-bottom: 1px solid #1e293b;
    border-right:  1px solid #1e293b;
}

.theme-dark .grid-header-row {
    background-color: #1e293b !important;
    color: #f1f5f9 !important;
}

.theme-dark .grid-cell-selection {
    background-color: rgba(56, 189, 248, 0.2) !important;
    box-shadow: inset 0 0 0 2px #38bdf8 !important;
}

Live demo: Themes (default / compact / spreadsheet / dark switcher).

Override the LESS source

If you import the LESS sources directly (recommended only when you're already using LESS), the variables in styles/themes/default.less are overridable: @grid-cell-border, @grid-cell-bg, @grid-row-header-bg, @grid-cell-selection-bg, @grid-cell-selection-border, @grid-outer-border, @grid-column-header-bg.

Recipes

Zebra striping

Add a class on odd rows during render. Don't forget to remove it in cellAfterRecycled — cells are reused as you scroll.

const zebra = {
    cellAfterRender(e) {
        if (e.rowIndex % 2 === 1) e.cell.classList.add('row-zebra');
    },
    cellAfterRecycled(e) {
        e.cell.classList.remove('row-zebra');
    }
};

new PGrid({ /* … */ extensions: [zebra] });
.row-zebra { background-color: #fafbfc; }

Status-driven row color

const statusRowColor = {
    cellAfterRender(e) {
        if (!e.dataRow) return;
        e.cell.classList.toggle('row-overdue', e.dataRow.status === 'Overdue');
        e.cell.classList.toggle('row-paid',    e.dataRow.status === 'Paid');
    },
    cellAfterRecycled(e) {
        e.cell.classList.remove('row-overdue', 'row-paid');
    }
};
.row-overdue { background-color: #fef2f2; }
.row-paid    { background-color: #f0fdf4; }

Row hover

Light up every cell of the row under the cursor.

const rowHover = {
    init(grid) { this._grid = grid; this._row = -1; },
    gridAfterRender() {
        this._grid.view.getElement().addEventListener('mouseover', (e) => {
            const cell = e.target.closest('.pgrid-cell');
            if (!cell) return;
            const r = parseInt(cell.dataset.rowIndex);
            if (r === this._row) return;
            this._highlight(this._row, false);
            this._highlight(r, true);
            this._row = r;
        });
    },
    _highlight(r, on) {
        if (r < 0) return;
        this._grid.view.getElement()
            .querySelectorAll(`.pgrid-cell[data-row-index="${r}"]`)
            .forEach(c => c.classList.toggle('row-hover', on));
    }
};
.row-hover { background-color: #eff6ff !important; }

Custom selection

Pass your own class to the selection extension and style it however you like.

new PGrid({
    selection: { cssClass: 'cell-selected' },
    /* … */
});
.cell-selected {
    background-color: #e0f2fe !important;
    box-shadow: inset 0 0 0 2px #0284c7;
}

Compact mode

Tighter rows, smaller font, lighter borders. Combine config (rowHeight) with CSS.

new PGrid({ rowHeight: 24, /* … */ });
.theme-compact .pgrid-cell {
    font-size: 12px;
    border-right: none;
    border-bottom: 1px solid #ececef;
}

Editor styling

The default text editor uses .pgrid-cell-text-editor. Custom editors render into a floating container that's appended to document.body — give it a wrapper class to scope your styles. See the Custom editors sample.

// Inside your editor's attach(e):
e.cell.classList.add('my-editor-host');
e.cell.appendChild(myInput);
.my-editor-host {
    background: #fff;
    box-shadow: inset 0 0 0 2px #0ea5e9, 0 4px 12px rgba(0,0,0,0.08);
    border-radius: 4px;
    display: flex;
    align-items: stretch;
}

Scrollbars

PGrid renders its own scrollbar tracks/thumbs in .pgrid-hscroll / .pgrid-vscroll with corresponding -thumb children. Default thumbs use the browser scrollbar styling, so the easiest path is targeting ::-webkit-scrollbar on those elements.

.pgrid-hscroll::-webkit-scrollbar,
.pgrid-vscroll::-webkit-scrollbar { width: 10px; height: 10px; }

.pgrid-hscroll::-webkit-scrollbar-thumb,
.pgrid-vscroll::-webkit-scrollbar-thumb {
    background: #cbd5e0;
    border-radius: 5px;
}