Repository navigation
Theme
This document outlines the theming approach for the Government of the Province of British Columbia's digital products, leveraging the Carbon Design System and Sass for customization.
Sass (Syntactically Awesome Style Sheets) is a powerful CSS preprocessor that enables developers to write more maintainable and flexible stylesheets. With features like variables, mixins, and nesting, Sass makes it easy to customize and extend design systems such as Carbon. In this project, we use Sass to override Carbon's default styles and apply the BC government branding.
To override Carbon styles, you typically create a high-level Sass file (such as _overrides-bcgov.scss) where you set new values for variables, redefine mixins, or add custom styles. For example, you might change the primary color, update button styles, or adjust spacing to better align with BC government guidelines. Comparing _overrides-bcgov.scss with a minimal override file like _overrides-min.scss reveals the extent of these customizations—ranging from color palette changes to typography and component-specific tweaks.
- Variables: Allow you to store values (like colors, spacing, or font sizes) and reuse them throughout your stylesheets. Overriding Carbon variables is the primary method for customizing the theme.
- Mixins: Enable you to define reusable chunks of styles. You can override or extend Carbon mixins to adjust component behavior or appearance.
-
Use vs. Import: The
@userule loads Sass modules and ensures that styles are only included once, promoting modularity and preventing duplication.@importis legacy and can lead to issues with repeated imports. Carbon recommends using@usefor all new projects.
Sass variables allow you to store values such as colors, font sizes, or spacing, and reuse them throughout your stylesheets. This makes it easy to maintain consistency and update your theme in one place. Variables are defined using the $ symbol. For more details, see the Sass documentation on variables.
Example:
$primary-color: #003366;
$spacing-unit: 1rem;
.button {
background: $primary-color;
margin: $spacing-unit;
}Mixins in Sass are reusable blocks of styles that can be included in any selector. They help avoid code duplication and make it easy to apply complex styles across multiple components. Mixins can also accept arguments, allowing for dynamic styling. For more information, see the Sass documentation on mixins.
Mixins are especially useful for theming, as you can define a set of styles for buttons, cards, or other UI elements and reuse them throughout your project. You can also override or extend Carbon's mixins to customize component behavior.
Example:
@mixin bcgov-button {
background: $primary-color;
color: #fff;
border-radius: 4px;
}
.button {
@include bcgov-button;
}Mixins can take parameters to make them more flexible:
@mixin spacing($size) {
margin: $size;
padding: $size;
}
.card {
@include spacing(2rem);
}You can also use mixins to apply vendor prefixes or complex logic:
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
.container {
@include flex-center;
}Sass extends CSS with powerful features for writing style rules. Nesting allows you to write selectors inside other selectors, mirroring the HTML structure. Selector lists and combinators help target multiple elements or relationships. Property declarators let you set multiple properties at once, and placeholders (%) allow you to define styles that can be extended but not output directly. See the Sass documentation on style rules.
Nesting Example:
.nav {
ul {
list-style: none;
li {
display: inline-block;
}
}
}Selector List Example:
h1, h2, h3 {
font-family: 'BCSans', Arial, sans-serif;
}Combinator Example:
.card > .title {
font-weight: bold;
}Property Declarator Example:
.box {
border: 1px solid #ccc;
border-radius: 8px;
}Placeholder Example:
%error {
color: red;
font-weight: bold;
}
.error-message {
@extend %error;
}Sass provides the & parent selector, which refers to the current selector and is useful for creating state-based or modifier classes. This makes it easy to write maintainable styles for components with multiple states. See the Sass documentation on parent selectors.
For example, you can style hover states or BEM-style modifiers:
.button {
color: #fff;
background: $primary-color;
&:hover {
background: darken($primary-color, 10%);
}
&--secondary {
background: #f2f2f2;
color: $primary-color;
}
}Nested selectors also help organize styles for components with complex structures, reducing repetition and improving readability.
Sass interpolation (#{}) allows you to dynamically construct selectors, property names, or values using variables or expressions. This is useful for generating utility classes or theme-based styles. See the Sass documentation on interpolation.
Example:
$theme: 'bcgov';
.button-#{$theme} {
background: $primary-color;
}
$property: 'margin';
.box {
#{ $property }: 2rem;
}Sass supports several at-rules, such as @mixin, @include, @function, @if, @for, @each, and @use, which add logic and modularity to your stylesheets. At-rules allow you to write conditional styles, loops, and reusable functions, making your theme more dynamic and maintainable. See the Sass documentation on at-rules.
For example, you can use @if for conditional styling:
$is-dark-theme: true;
.header {
@if $is-dark-theme {
background: #222;
color: #fff;
} @else {
background: #fff;
color: #222;
}
}Loops with @for and @each help generate repetitive styles:
@for $i from 1 through 3 {
.col-#{$i} {
width: 100px * $i;
}
}
$colors: (primary: #003366, secondary: #f2f2f2);
@each $name, $color in $colors {
.bg-#{$name} {
background: $color;
}
}The @use rule is recommended for importing modules, ensuring styles are only included once and promoting modularity:
@use 'carbon-components/scss/colors';
.header {
color: colors.$text-primary;
}You can also define custom functions with @function:
@function rem($px) {
@return $px / 16 * 1rem;
}
.container {
padding: rem(32);
}At-rules make it possible to write highly flexible and maintainable themes, adapting to different requirements and environments.
When using a design system with Sass, it's important to understand how Sass modules behave like singletons. This means that once a module is configured using @use ... with (...), that configuration is shared across your entire project — even in files that import the module without the with clause.
Sass modules are only loaded once per compilation. If you configure a module (e.g., override tokens or theme values), that configuration is cached and reused everywhere the module is imported.
In your global override file:
// _override.scss
@use "@bcgov-nr/nr-theme/design-tokens/type-family.scss" as types;
@use "@carbon/type/scss/font-family.scss" with (
$font-families: types.$type-family,
$font-weights: types.$font-weights
);This sets the font family tokens to your custom values (e.g., Comic Sans).
In a component’s Sass file:
// MyComponent.scss
@use "@carbon/type/scss/font-family.scss";
.my-component {
@include font-family(); // Uses Comic Sans from global override
}Even though this file doesn’t use with (...), it still gets the overridden values from _override.scss.
- Sass modules are singleton-style: loaded once, shared everywhere.
- The
@use ... with (...)configuration is global for that module. - Any file that
@uses the same module gets the configured version.
To avoid confusion and ensure consistency, create a shared theme entry point:
// _theme.scss
@use "@carbon/type/scss/font-family.scss" with (
$font-families: types.$type-family,
$font-weights: types.$font-weights
);
@use "@carbon/react/scss/theme" with (
$theme: themes.$g10
);Then in components:
@use "../path/to/theme.scss";This guarantees all components use the same configuration without repeating logic. For more information, see the Sass Modules Documentation and Carbon Type Tokens.
A design system is a comprehensive set of guidelines, components, and tools that help teams build consistent, scalable, and accessible user interfaces. It typically includes:
- ✏️ Design tokens (colors, typography, spacing)
- 🧩 Reusable UI components
- 📚 Documentation and usage guidelines
- 🛠️ Tooling for implementation (e.g., Sass, React, Figma)
Design systems promote visual consistency, developer efficiency, and design-to-code alignment across products and teams.
Carbon is IBM’s open-source design system for building digital experiences. It provides a robust set of design assets and implementation tools for web and product teams.
- Developed by IBM to unify design across its vast product ecosystem.
- Originally focused on vanilla HTML/CSS components.
- Evolved to support React, Vue, and Web Components.
- Now includes tooling for accessibility, theming, and responsive design.
Carbon is maintained by IBM and the open-source community, and it powers products across IBM and beyond.
While Carbon for React provides prebuilt components, the styling layer is powered by Sass, giving developers full control over theming and customization.
Carbon’s Sass is modular and token-driven. Key modules include:
@carbon/colors@carbon/type@carbon/layout@carbon/themes
These modules expose design tokens and mixins that can be used to style custom components or override Carbon defaults.
You can override Carbon’s default styles using Sass’s @use ... with (...) syntax. For example:
@use "@carbon/react/scss/theme" with (
$theme: $custom-theme
);
@use "@carbon/type/scss/font-family" with (
$font-families: $my-fonts
);Once configured, these overrides apply globally due to Sass’s singleton module behavior.
Carbon provides mixins and variables for consistent styling:
@use "@carbon/type/scss/font-family";
@use "@carbon/colors";
.my-button {
@include font-family.body();
background-color: colors.$interactive-01;
color: colors.$text-on-color;
}This ensures your custom components match Carbon’s design language.
This wiki documents NR Waste Plus for users and developers. Verify security and deployment guidance against the current application configuration before applying it elsewhere.
- Report an issue or ask a question in the GitHub repository.
- Follow the Contributing Guidelines to propose an update.
- Read the Code of Conduct.
Collection indexes support human browsing and machine retrieval. Keep both current when adding or moving wiki pages.
NR Waste Plus Wiki | GitHub Repository