Skip to content

CSS Custom Properties Styleguide

Yvette Nikolov edited this page Jan 15, 2026 · 2 revisions

An initial draft of a styleguide. This is not set in stone and can be changed.

1. Naming conventions

  1. This follows a fixed pattern. The property represents the full CSS property, except for bg-color and radius.
  2. No prefixes, so no wp-block- or yard-. Potential clashes with external CSS variables are resolved through cascading.

The fixed pattern:

--{component}-{property}-{modifier}

Examples:

/* Button */
--button-radius
--button-bg-color
--button-bg-color-active
--button-font-weight

/* Card */
--card-label-padding

❌ Do not use:

--btn-pad
--icon-bg
--button-hover-bg-color
--wp-block-collapse-color

2. Order

  1. Base order is alphabetical (= predictable, no discussion, easy to automate)
  2. Media queries come after that
--button-bg-color
--button-bg-color-active
--button-bg-color-hover
--button-color
--button-padding
@variant lg {
  --button-color
  --button-padding
}

3. Predictability

3.1 Always use shorthand

--button-padding: 0.75rem 1.25rem;
--card-margin: 0 0 1.5rem 0;

Only split when there is a real necessity:

--button-padding-x: 1.25rem;
--button-padding-y: 1.25rem;

Exception: border cannot be used as shorthand in combination with Tailwind. These must be written out explicitly.

:root {
  --input-border-color: var(--color-gray-400);
  --input-border-width: 1px;
}

input {
  @apply border-(length:--input-border-width) border-(--input-border-color);
}

3.2 Allowed states

Only use the following suffixes:

-hover
-hocus
-focus
-active
-disabled
-expanded

3.3 Semantic naming over implementation

Properties must describe the intent or meaning of a value, not how it is technically implemented. So:

--collapse-button-icon: '\f078';

❌ Do not use:

--collapse-button-after-content: '\f078';

Pragmatic note on global component variables

All our variables live at the :root level. In an ideal design system, component variables would be scoped to the component itself and only design tokens would live at :root level.

However, Brave operates in the reality of WordPress and third party UI (Gutenberg, Gravity Forms, cookie modals, plugins we do not control, etcetera). In many cases we need to style or align UI elements from the outside, without access to a component root or implementation layer.

For that reason component variables (such as --button-*) are intentionally defined globally. This allows interaction behaviour across first-party and third-party UI, while remaining predictable and override-friendly.

This is a conscious, pragmatic trade off, not a lack of understanding of component encapsulation.

Clone this wiki locally