Style your custom component with SCSS
You can style your custom components using .css, .scss, or .module.scss files. Each format has a different scoping behavior:
- Use
.cssfor general-purpose styles and.scssfor global or shared styles - Use
.module.scssto scope styles to a single component
Scoping your styles
You can style your custom components using .css, .scss, or .module.scss. Each format controls how the platform applies and scopes your styles.
When you create a style file and import it into a React component, the platform loads that file into the DOM when the component mounts. The styles take effect immediately and stay active for the rest of the session. The platform does not remove the styles when the component unmounts.
From an import perspective, all styles are reusable. You can create a single stylesheet and import it into as many components as you want. However, the platform handles .css and .scss files differently than .module.scss files.
When you use .css or .scss, the platform inserts those rules into the DOM without modifying them. If you define a low-specificity selector, such as:
p {
color: #eaeaea;
}the browser applies that style to every matching element in the DOM, including paragraphs created by other components. You can use this pattern to override platform styles or to enforce consistent formatting, but you must write your selectors carefully. Avoid overly generic rules, or you risk unintentionally affecting unrelated parts of the UI.
Since the platform does not remove styles when a component unmounts, you may see lingering style effects if you rely on global selectors. This behavior makes .css and .scss powerful tools, but they require discipline. Always add enough context and specificity to your selectors to avoid conflicts.
When you use .module.scss, you write selectors the same way, but the platform rewrites each class name into a locally scoped identifier. This transformation guarantees that your styles apply only to the elements that import them. Other components cannot inherit or override those styles unless they explicitly import the same file.
Choose .module.scss when you want predictable styling, isolated layout behavior, and no side effects. Choose .scss or .css when you want global influence or to style multiple components with shared rules.
How mounting order affects the cascade
The platform appends stylesheets to the DOM when each component mounts. This behavior affects how styles cascade and which ones take precedence. If ComponentA imports StylesA.scss and mounts first, and ComponentB later mounts with its own StylesB.scss, the browser loads the styles in this order:
<head>
<style> /* StylesA */ </style>
<style> /* StylesB */ </style>
</head>CSS rules follow cascading behavior—rules with the same specificity take effect in the order they appear. The browser gives precedence to the last defined rule.
For example:
/* StylesA.scss */
.card {
background-color: blue;
}/* StylesB.scss */
.card {
background-color: red;
}If ComponentA mounts first and ComponentB mounts second, then the DOM loads StylesB.scss after StylesA.scss. As a result, any element using the card class will appear red, because that rule appears later and both rules have equal specificity.
This detail becomes important when two components target the same selectors. You must control specificity or use module-scoped styles if you want predictable, isolated behavior. When two styles conflict and rely only on cascade order, the mounting sequence determines the final result.
Use semantic class names, increase specificity deliberately, or use .module.scss to avoid unintended overrides.
Store and import your stylesheets
Store your stylesheets in one of the src/ui/styling/ directory:
The platform uses the following conventions to determine which SCSS files to load automatically:
- If the SCSS file matches the name of a custom Type (for example,
WindTurbineSummaryCard.scss) and lives anywhere in thesrc/directory, the platform automatically includes it at runtime. - If the SCSS file is not backed by a Type, place it in
src/ui/styling/. This location is intended for reusable and global styles.
To apply a stylesheet in your component, import it using the @c3/ui path alias:
import '@c3/ui/CustomCardStyles.scss';For .module.scss, import the style as an object and apply styles using styles['class-name']:
import styles from '@c3/ui/MyComponent.module.scss';Use regular .scss for shared or global styles
Use .scss when you want multiple components to share the same styles or when you need to style a component defined by a .c3typ Type. If the file uses the same name and lives in the same folder as the Type, at build time, the platform links the file automatically.
For example:
// {package}/src/ui/components/WindTurbineSummaryCard.c3typ
@typeScript
type WindTurbineSummaryCard mixes ReactFunction, UiSdlComponent<UiSdlNoData> {
title: string
render: ~ tsx-client
}// {package}/src/ui/components/WindTurbineSummaryCard.tsx
import * as React from 'react';
const WindTurbineSummaryCard = ({ title }: WindTurbineSummaryCard) => {
return <div className="summary-card">{title}</div>;
};
export default WindTurbineSummaryCard;// {package}/src/ui/components/WindTurbineSummaryCard.scss
.summary-card {
font-size: var(--c3-style-fontSizeBody);
padding: var(--c3-style-mediumSizePadding);
background-color: var(--c3-style-componentBackgroundColor);
}You don’t need to import the SCSS file in the .tsx file. The platform applies the styles automatically.
Use .scss when:
- You want styles to apply globally
- You are styling a component Type that follows naming conventions
- You want to reuse styles across components
Use .module.scss to scope styles to a single component
Create a .module.scss file when a component needs isolated styles that should not affect or be affected by anything else. The platform rewrites each class name during build to guarantee isolation.
// {package}/src/ui/WindTurbineStatus.module.scss
.status-banner {
background-color: #333;
color: #fff;
padding: 12px;
border-radius: 4px;
}// {package}/src/ui/c3/src/customInstances/WindTurbine.Status.tsx
import * as React from 'react';
import styles from '@c3/ui/WindTurbineStatus.module.scss';
const WindTurbineStatus = () => {
return (
<div className={styles['status-banner']}>
This turbine is currently operating within expected parameters.
</div>
);
};
export default WindTurbineStatus;This ensures that .status-banner styles don’t leak outside of WindTurbineStatus.
Use .module.scss when:
- You want styles to affect only a single React component
- You need predictable behavior across shared UIs
- You want to isolate layout or visual tweaks
Understand the limitations of .module.scss
- The build process transforms class names into unique identifiers.
- You must use
styles['class-name']orstyles.classNamein JSX. - The component doesn't apply these styles unless it imports the
stylesobject. - Only
classNameandidsupport module-based styling.
Create reusable styles with Sass variables and @use
To share variables or styles across multiple SCSS files, define them in a base file and import using @use.
// chartBase.scss
$chart-font-size: 16px;
.chart-subtitle {
color: black;
font-size: $chart-font-size;
}// timeseriesChart.scss
@use 'chartBase';
.chart-timeseries-time {
font-size: chartBase.$chart-font-size;
}Reference static assets in SCSS
To use images or icons in SCSS files, reference their paths using the url() CSS function.
Assets in ui/content/
Use the webpackIgnore comment to prevent asset path rewriting:
/* webpackIgnore: true */
background-image: url("/assets/images/logo.png");