Chapter 28 of 40

Theming and dark mode with CSS variables

Everything is a CSS variable – light and dark are built in, your brand is a few lines away.

After this chapter you can

  • override --ge-table-* variables
  • switch light and dark
  • scope a theme to one table
  • mirror the table for Arabic and Hebrew (since 1.1.98)

Everything is a CSS variable

main.css (chapter 4 (Installation)) defines more than 100 variables with the prefix --ge-table-: backgrounds and text per area and side (chapter 11 (TableModel & areas)), borders, zebra rows, hover, focus, selection, progress bars, tree arrows. A light and a dark set are built in.

@guiexpert/table/css/table-color-vars.css (excerpt)
html, html[data-theme="light"] {
--ge-table-bg: #fff;
--ge-table-header-center-bg: rgba(233, 233, 233, 0.5);
--ge-table-header-center-text: #000;
--ge-table-body-center-text: var(--ge-table-header-center-text);
…
}
html[data-theme="dark"] {
…
}

Your own look

Override the variables in a stylesheet that is loaded after main.css:

src/theme.css
html[data-theme="light"] .brand-table {
--ge-table-header-center-bg: #eef2ff; /* indigo-50 */
--ge-table-header-center-text: #3730a3; /* indigo-800 */
--ge-table-body-center-text: #111827; /* the body text follows the header colour by default */
--ge-table-body-west-text: #111827;
--ge-table-body-east-text: #111827;
--ge-table-row-even-bg: #fdf2f8; /* zebra: pink-50 */
--ge-table-hover-row-bg: rgba(244, 114, 182, 0.18);
--ge-table-focus-border: #db2777;
--ge-table-body-center-selected-range-bg: rgba(79, 70, 229, 0.22);
--ge-table-color-progress-bar: #f472b6;
--ge-table-footer-center-bg: #e0e7ff;
}
html[data-theme="dark"] .brand-table {
--ge-table-header-center-text: #f9a8d4; /* pink-300 */
--ge-table-row-even-bg: rgba(129, 140, 248, 0.08);
--ge-table-hover-row-bg: rgba(244, 114, 182, 0.2);
--ge-table-focus-border: #f472b6;
--ge-table-body-center-selected-range-bg: rgba(129, 140, 248, 0.35);
--ge-table-body-center-selected-range-text: #ffffff;
--ge-table-color-progress-bar: #f472b6;
}

Here the selectors end with .brand-table, so only this one table is themed – CSS variables are inherited, a class on any parent is enough. Drop the class to theme every table of the app.

Light and dark

The table follows the attribute data-theme on <html>:

// light / dark: one attribute on <html> – the built-in variables of both themes are already there
const setTheme = (theme: "light" | "dark") => {
document.documentElement.dataset.theme = theme;
try { localStorage.setItem("theme", theme); } catch { /* private mode */ }
};
themeButton.addEventListener("click", () =>
setTheme(document.documentElement.dataset.theme === "dark" ? "light" : "dark"));
Live Brand theme
Screenshot: Brand theme Screenshot: Brand theme
“light / dark” switches this whole website – the table switches with it. Untick “brand theme” to compare with the default look.

Right-to-left: Arabic, Hebrew, Persian

One option mirrors the whole table: TableOptionsIf.direction = "rtl". The first column is on the right, horizontal scrolling starts on the right, fixed columns, the tree indent, header groups, the sort icon and the column resize handle (now on the left edge) follow – and so do the arrow keys: → moves to the previous column. "auto" takes the direction of the page (<html dir="rtl">).

const tableModel = TableFactory.createTableModel({
rows: orders,
columnDefs,
fixedLeftColumnCount: 1 // "left" = start: stays on the RIGHT in right-to-left
});
const tableOptions: TableOptionsIf = {
...new TableOptions(),
direction: rtl ? "rtl" : "ltr" // or "auto": the direction of the page (<html dir="rtl">)
};
Live 100,000 orders from right to left
Screenshot: 100,000 orders from right to left Screenshot: 100,000 orders from right to left
Untick “right-to-left” to compare – the same model and options, only direction changes.

“Left” and “right” in option names mean start and end: fixedLeftColumnCount fixes columns on the right, the class ge-table-text-align-left aligns text to the start (right) – numbers with ge-table-text-align-right move to the left, like in a right-to-left Excel sheet (and the Excel export is one). Positions of the API count from the start, too: TableApi.scrollToPixel(), the scrollLeft of EventListenerIf.onScroll() and the stored state.

More

The showcase Look and feel switches between several complete themes, Right-to-left shows Arabic sales data. The documentation lists all CSS classes and variables.

Next

Merged cells: chapter 29 (Rowspan & colspan).

API used in this chapter

Showcases