Styling

Tailwind and SCSS in a theme, the colour and font tokens the engine sets, and dark mode.

Read this when you want to change colours, fonts or spacing, or support dark mode.

A theme styles itself with Tailwind CSS (small utility classes like flex and px-4) and SCSS (CSS with nesting and variables). Both are set up for you in the starter theme.

How the files fit together

app/styles/
  app.css          Tailwind layers, then imports app.scss
  app.scss         imports the folders below, in order
  01-settings/     variables, fonts, breakpoints
  02-generic/      reset, RTL and LTR rules, animations
  03-elements/     buttons, forms
  04-components/   header, footer, product, cart …
  05-utilities/    small fixes

The root route links it once, by URL, with ThemeStylesheet:

app/routes/__root.tsx
import { ThemeStylesheet } from '@salla.sa/twilight-theme-engine/tanstack';
import appCssUrl from '../styles/app.css?url';

// inside <head>:
<ThemeStylesheet href={appCssUrl} />

The starter also passes critical, so the home and product pages inline a smaller critical stylesheet instead and app/client.tsx adds app.css once the first screen has painted. See Performance.

The numbered folders follow the ITCSS idea: general rules first, specific ones last, so later rules win without !important. Put new styles in the folder that matches what you style.

Components in the starter theme often keep their markup clean and write the Tailwind classes in SCSS with @apply. You can also use utility classes directly in your markup.

Tailwind setup

Tailwind must scan every file that contains class names, including the engine's, or those classes are dropped from the build:

tailwind.config.cjs
module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx,scss,css}',
    './node_modules/@salla.sa/twilight-theme-engine/dist/**/*.js',
    './node_modules/@salla.sa/twilight-components-react/dist/**/*.js',
  ],
  darkMode: 'class',
  theme: { extend: { colors: { primary: 'var(--color-primary)' } } },
  plugins: [require('@salla.sa/twilight-tailwind-theme'), require('@tailwindcss/forms')],
};

The primary colour points at a CSS variable, so it follows the merchant's choice.

Colour and font tokens

The merchant picks a main colour and a font in the dashboard. In the browser the engine turns them into CSS variables on <html>. Use these instead of hard-coding values:

VariableMeaning
--color-primaryThe merchant's main colour
--color-primary-dark, --color-primary-lightDarker and lighter shades of it
--color-primary-reverseReadable text colour on top of the primary colour
--font-mainThe chosen font

The starter theme applies the font to the whole page:

app/styles/app.css
body {
  font-family: var(--font-main);
}

Add your own tokens in 01-settings/global.scss under :root, as the starter does with --s-radius.

Dark mode is your choice

The engine does not give you a dark theme by itself. What it does:

  • It adds color-mode-dark or color-mode-light to <body>, based on the merchant's colour settings.
  • It adds footer-is-dark or footer-is-light from the footer_is_dark setting.

Tailwind is configured with darkMode: 'class', so dark: utilities only apply under a .dark class that your theme must add. The simplest path is to style the body classes directly:

body.color-mode-dark {
  --color-text: #e5e7eb;
  background: #111;
}

Decide per theme whether you want this at all. Many themes only offer a dark footer, using the footer_is_dark setting (see Settings).

Make styles work in both directions

Prefer logical classes so one stylesheet works in Arabic and English: ms-4 instead of ml-4, text-start instead of text-left. The full list is in Languages and RTL.

Next: Languages and RTL, to translate your theme.

On this page