Styling Discourse with variables: Show & Tell

AI-generated summary

The discussion, titled ‘Styling Discourse with variables: Show & Tell,’ highlights recent updates to Discourse that introduce CSS variables to simplify theming and UI customization. jordan.vidrine explains that these variables reduce the need for targeting specific HTML elements, making styling more efficient. They demonstrate this by creating a custom theme using only variables, inspired by shadcn/ui’s theme editor, and share visual examples of the changes. The theme includes a simplified color palette and adjustments to sidebar, topic list, and typography styles, all achieved through variable modifications. tknospdr notes that these changes may have broken existing CSS overrides on their site, particularly affecting topic card background colors, and seeks help to resolve the issue.

We’ve recently added a lot of css variables to Discourse. These variables make theming and customizing aspects of the UI much easier. For many changes, you will no longer need to target super specific elements in the html, and instead only change a variable.

If you are curious about what variables are able to be changed, I suggest you look through the app using this regex → --([a-zA-Z0-9\-_]+):

If using a code editor and searching for all instances of the above regex, you should see something like:


I’ve been personally inspired by shadcn/ui lately and particularly the theme editor they have created → https://tweakcn.com/

Using their styles as an inspiration, I set out to see how much I could change in the UI using only variables. Here is an example of what I did:

This is a WIP and some areas would need more specific CSS target in order to work, but the gist is that it is now a lot easier to make changes like this with our new css variables.

This styling was possible only using variables. I separated into two files.

Simplified Color Palette

I wanted to see if I could eliminate some of the steps between primary - secondary. I also wanted to limit the amounts of tertiary available to simplify the overall palette.

:root {
  --color-1: #e2ece6;
  --base: oklch(from var(--color-1) l c h);
  --step: 0.15;

  /* Derived darker colors */
  --color-2: oklch(from var(--base) calc(l - var(--step) * 0.25) c h);
  --color-3: oklch(from var(--color-2) calc(l - var(--step) * 0.55) c h);
  --color-4: oklch(from var(--color-3) calc(l - var(--step)) c h);
  --color-5: oklch(from var(--color-4) calc(l - var(--step)) c h);
  /* stylelint-disable-next-line hue-degree-notation */
  --color-6: oklch(from var(--color-5) 0.35 c h);

  /* accent colors */
  // --accent-color-1: #0867f6;
  --accent-color-1: oklch(from var(--color-1));
  --accent-color-light: oklch(from var(--accent-color-1) calc(l * 1.25) c h);
  --accent-color-lighter: oklch(from var(--accent-color-1) calc(l * 1.5) c h);
  --accent-color-lightest: oklch(from var(--accent-color-1) calc(l * 1.75) c h);
  --accent-color-darker: oklch(from var(--accent-color-1) calc(l * 0.5) c h);

  /* Overwrite color mapping */
  --header_primary: var(--color-6);
  --header_background: var(--color-1);
  --primary-very-low: var(--color-6);
  --primary-low: var(--color-6);
  --header_primary-low: var(--color-6);
  --primary-low-mid: var(--color-6);
  --header_primary-low-mid: var(--color-4);
  --primary-medium: var(--color-6);
  --primary-med-or-secondary-high: var(--color-6);
  --primary-med-or-secondary-med: var(--color-6);
  --header_primary-medium: var(--color-6);
  --hljs-bg: var(--color-2);
  --primary-high-or-secondary-low: var(--color-6);
  --primary-high: var(--color-6);
  --header_primary-high: var(--color-6);
  --primary-very-high: var(--color-6);
  --header_primary-very-high: var(--color-6);
  --blend-primary-secondary-5: var(--color-2);
  --d-hover: var(--color-3);
  --mention-background-color: var(--color-4);
  --link-color: rgb(196, 101, 0);
  --primary-50: var(--color-6);
  --primary-100: var(--color-6);
  --primary-200: var(--color-6);
  --primary-300: var(--color-6);
  --primary-400: var(--color-6);
  --primary-500: var(--color-6);
  --primary-600: var(--color-6);
  --primary-700: var(--color-6);
  --primary-800: var(--color-6);
  --primary-900: var(--color-6);
  --primary: var(--color-6); /* Black */
  --secondary: var(--color-1); /* White */
  --secondary-rgb: var(--color-1);
  --tertiary: var(--accent-color-1); /* Blue */
  --tertiary-hover: var(--accent-color-darker);
  --tertiary-medium: var(--accent-color-light);
  --tertiary-med-or-tertiary: var(--accent-color-light);
  --tertiary-med-or-tertiary-low: var(--accent-color-lighter);
  --tertiary-very-low: var(--accent-color-lighter);
  --tertiary-low: var(--accent-color-lighter);
  --tertiary-25: var(--accent-color-lightest);
}


UX Styling

With these styles I utilized a lot of the available variables in core to get the theme you see above.

:root {
  --d-max-width: unset;
  --d-main-content-gap: 0;

  /* sidebar edits */
  --d-sidebar-background: var(--color-1);
  --d-sidebar-admin-background: var(--color-1);
  --d-sidebar-link-color: var(--color-6);
  --d-sidebar-link-icon-color: var(--color-6);
  --d-sidebar-header-color: var(--color-6);
  --d-sidebar-header-icon-color: var(--color-6);
  --d-sidebar-footer-fade: transparent;
  --d-sidebar-active-background: rgb(0, 0, 0, 0.06125);
  --d-sidebar-highlight-background: rgb(0, 0, 0, 0.06125);
  --d-sidebar-highlight-color: var(--color-6);
  --d-sidebar-width: 14rem;
  --d-sidebar-row-height: 1.85rem;
  --d-sidebar-row-horizontal-padding: 0.5rem;
  --sidebar-section-wrapper-padding: 1rem 0.75rem 0.75rem;
  --d-sidebar-border-color: var(--content-border-color);
  --d-sidebar-section-border-color: transparent;
  --d-sidebar-header-font-weight: 400;
  --d-sidebar-active-font-weight: 600;

  /* topic list */
  --d-topic-list-header-font-size: var(--font-down-1);
  --d-topic-list-header-text-color: var(--color-6);
  --d-topic-list-header-data-padding-x: var(--space-2);
  --d-topic-list-header-data-padding-y: var(--space-2);
  --d-topic-list-margin-y: var(--space-4);
  --title-color: var(--color-6);
  --title-color--read: var(--color-6);
  --d-table-border-top-height: 1px;
  --topic-list-item-background-color--visited: var(--color-2);
  --d-topic-list-avatar-size: 20px;
  --topic-title-font-weight: 700;
  --topic-title-font-weight--visited: 400;
  --d-topic-list-data-padding-x: var(--space-4);
  --d-topic-list-data-padding-y: var(--space-2);
  --d-topic-list-metadata-top-space: var(--space-1);
  --d-topic-list-data-padding-inline-start: var(--space-4);
  --d-topic-list-data-padding-inline-end: var(--space-4);
  --d-topic-list-likes-views-posts-width: 12%;
  --d-topic-list-data-font-size: var(--font-down-1-rem);

  /* nav */
  --d-nav-font-size: var(--font-down-1);
  --d-nav-bg-color--active: var(--color-6);
  --d-nav-bg-color--hover: var(--d-hover);
  --d-nav-color--active: var(--color-1);
  --d-nav-color--hover: var(--color-6);
  --d-nav-underline-height: 0;
  --nav-horizontal-padding: var(--space-4);
  --nav-space: 0;

  /* categories */
  --category-boxes-title-font-size: var(--font-up-3-rem);
  --category-boxes-text-alignment: left;
  --d-category-border-accent-width: 0px;
  --d-category-border-box-width: 0px;
  --d-category-box-background-color: var(--color-2);
  --category-badge-title-color: var(--color-6);
  --d-category-boxes-margin-top: var(--space-4);
  --d-category-boxes-gap: var(--space-4);
  --category-badge-size: var(--space-2);
  --category-badge-border-radius: 50%;
  --category-boxes-description-text-color: var(--color-6);
  --d-categories-list-title-margin-bottom: var(--space-2);

  /* tags */
  --d-tag-horizontal-padding: var(--space-2);
  --d-tag-border-radius: 4px;
  --d-tag-font-weight: 500;
  --d-tag-background-color: rgb(0, 0, 0, 0.1);
  --tag-text-color: var(--color-6);

  /* misc */
  --onebox-shadow-color: var(--color-2);
  --onebox-border-color: var(--content-border-color);
  --d-border-radius: 8px;
  --content-border-color: var(--color-3);
  --main-outlet-padding-top: var(--space-4);
  --base-font-size: 15px;
  --topic-timeline-border-color: var(--color-6);
  --d-header-padding-x: var(--space-4);
  --d-input-focused-color: var(--color-6);
  --d-button-default-text-color: var(--color-6);
  --d-button-default-icon-color: var(--color-6);
  --d-button-default-bg-color: transparent;
  --d-button-default-bg-color--hover: var(--d-hover);
  --d-button-default-text-color--hover: var(--color-6);
  --d-button-default-icon-color--hover: var(---color-6);
  --d-post-control-background--hover: var(--d-hover);
  --d-post-control-create-icon-color: var(--color-6);
  --d-button-primary-bg-color: var(--color-6);
  --font-family: "Inter";
  --list-container-padding-x: var(--space-4);
  --list-container-topiclist-padding-x: 0em;
  --badge-card-background-color: var(--color-2);

  /* chat */
  --d-chat-input-border-color: var(--content-border-color);
  --d-chat-input-focused-shadow: 0 0 1px 0 var(--tertiary);
}

.wrap {
  --d-wrap-padding-x: 0;
}

.navigation-container {
  #create-topic {
    --d-button-default-text-color: var(--color-1);
    --d-button-default-icon-color: var(--color-1);
    --d-button-default-bg-color: var(--color-6);
    --d-button-default-bg-color--hover: black;
  }
}

.new-main-title-data .topic-list-data:first-of-type,
.new-main-title-data .topic-list-data:last-of-type {
  --d-topic-list-data-padding-y: 0;
  --d-topic-list-data-padding-x: 0;
  --d-topic-list-data-padding-inline-start: 0;
}

Let’s use this topic to share examples & css variable code to showcase what’s possible :smiley:

This has apparently broken the CSS edits I made to my site to override background colors on Topic Cards.
I’m not a coder and don’t understand how I would go about fixing my issue. Can someone here give me some help putting things back to the way they were?

Resolved… I hope.