Skip to content

Common variable patterns

Some of River's variables work together to achieve bigger interface changes, others have unique behaviours that aren't always intuitive.

Auto-generated variables

By default River automates some colours, using either color-mix or HSL. These auto-overrides can be replaced as most are set as variables. For example:

  • A second background color: --crm-layer2-bg-color is auto-generated with: --crm-layer2-bg-color: color-mix(in srgb,var(--crm-layer1-bg-color) 95%,#000 5%);
  • Hover states for buttons are generated from the colour of the button: --crm-primary-hover-color: color-mix(in srgb,var(--crm-primary-color) 75%,#000 25%);
  • Semantic emphasis colours (success, warning, info, danger) both cascade into and auto-generate related colour variables. Once you set --crm-success-color an HSL transform creates --crm-success-light-color which is also used for --crm-alert-success-bg-color, which in turn generates with color mix --crm-alert-success-border-color. Another HSL transform creates --crm-notify-success-color.

Therefore once you've chosen a colour for --crm-success-color in your Stream you don't need to worry about all the other success related variables as they will be auto-generated from the colour you chose.

But perhaps you need to tweak --crm-notify-success-color because you've chosen a lighter colour for --crm-notify-bg-color rather than the dark default and it's no longer legible. Your stream can just define that specific variable, or point to a different semantic variable (such as crm-success-ink-color, which is the variable for the success colour on the normally light page background).

Dark mode variables

The variables for dark mode are defined in core/css/_dark.css and the related Stream dark.css overrides (streams/[stream-name]/_dark.css). They should follow the same category name and order.

To swap light and dark colours over, do not swap the values of primitive variables like --crm-c-amber-light and --crm-c-amber-dark; but instead change semantic and component variables to point to different colours.

Because of auto-generated variables (see above), changing one variable in _dark.css sometimes flows into multiple other auto-generated variables.

Variable pairs for contrast

Many colour variables exist in pairs of background/foreground colours to ensure a legible contrast ratio. For Semantic variables the foreground colour is marked with -text- while for Component variables the background colour is marked with -bg-. For example:

/* Primary colour pattern (semantic) */
--crm-primary-color: var(--crm-inverse-bg-color);
--crm-primary-text-color: var(--crm-text-light-color);

/* Info colour pattern (semantic) */
--crm-info-color: var(--crm-c-blue-dark);
--crm-info-text-color: var(--crm-text-light-color);

/* Accordion header (component) */
--crm-accordion-header-bg-color: var(--crm-secondary-color);
--crm-accordion-header-color: var(--crm-secondary-text-color);

/* Table header (component) */
--crm-table-header-bg-color: var(--crm-paper);
--crm-table-header-color: var(--crm-text-color);

/* Tabs (component) */
--crm-tab-bg-color: var(--crm-layer1-bg-color);
--crm-tab-color: var(--crm-text-color);

/* Dropdown (component) */
--crm-dropdown-bg-color: var(--crm-secondary-hover-color);
--crm-dropdown-color: var(--crm-text-light-color);
--crm-dropdown-hover-bg-color: var(--crm-paper);
--crm-dropdown-hover-text-color: var(--crm-text-color);
If you're changing either one of these colours you should check its paired colour to make sure it still meets legible and accessible contrast ratios. These can be checked with a tool such as WebAIM's Contrast Checker. A 4.5:1 contrast ratio is needed for WCAG AA and 7:1 for WCAG AAA.

Border variables

--crm-border is a Semantic variable used across multiple components for a consistent colour, style and width, which can then be replaced on a component-by-component basis.

Some border variable are designed so the Stream can define which side they appear on. This is done with separate variables for border colour/style variables and the width, which sets a value for each side — top, right, bottom, left — while '0' removes the border. For example:

/* In Walbrook, adds a border to the left of notification boxes */
--crm-notify-accent-border: 0 0 0 3px;

/* In Thames, adds a large border to the top of notifications */
--crm-notify-accent-border: 0.875rem 0 0 0;

/* Adds a border to the bottom of accordion headers */
--crm-accordion-header-border-width: 0 0 1px 0;

/* Removes the border from the top of accordion body to match the border with the header */
--crm-accordion-border-width: 0 1px 1px 1px;

/* Applies different colours to different sizes of the dialog header */
--crm-dialog-header-border-color: transparent transparent var(--crm-border-color) transparent

Background variables

There are multiple background variables, so to help decide which one(s) you want to tweak, their relationship is illustrated below – gradating darker in light mode and lighter in dark mode:

An illustration of the relationship between different background colours, explained in the text above

Tabs variables

--crm-tabs- defines the collection of tabs, and --crm-tab- defines the individual tab. Two patterns are supported: tabs in the 'pill' style in the middle of a background block, and traditional tabs flush to one side with the active overlapping (as seen on the Search Kit Builder layout, and Hackney Brook Contact Layout, and below). To achieve this flush tab type you need a combination of --crm-tabs-padding with 0 one side, --crm-tab-hang as the width of the --crm-tabs-border, and --crm-tab-border-width and --crm-tab-radius both setting to 0 the side that's flush to the edge.

An illustration of which variables apply to which parts of tabs

Contact Layout tabs position

Contact Layout has its own set of variables to define the tabs there and can do everything that regular tabs can do with flush or centred tabs. Furthermore, several of the --crm-contact variables can be used together to swap the contact layout view tabs from being at the top (as in Greenwich/Minetta) to being on the left (Walbrook/Hackney/Thames). These need to be changed together:

  • --crm-contact-direction choose 'flex' for tabs at top, or 'grid' for tabs at side.
  • --crm-side-tabs-width set a value for the width of the tabs if using grid for tabs at the side.
  • --crm-contact-tabs-flow, set 'row' for inline tabs at top, 'column' for stacked tabs on the side.