C3 AI Documentation Home

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 .css for general-purpose styles and .scss for global or shared styles
  • Use .module.scss to 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:

SCSS
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:

Text
<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:

SCSS
/* StylesA.scss */
.card {
  background-color: blue;
}
SCSS
/* 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 the src/ 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:

TypeScript
import '@c3/ui/CustomCardStyles.scss';

For .module.scss, import the style as an object and apply styles using styles['class-name']:

TypeScript
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:

Type
// {package}/src/ui/components/WindTurbineSummaryCard.c3typ

@typeScript
type WindTurbineSummaryCard mixes ReactFunction, UiSdlComponent<UiSdlNoData> {
  title: string
  render: ~ tsx-client
}
TypeScript
// {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;
SCSS
// {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.

SCSS
// {package}/src/ui/WindTurbineStatus.module.scss

.status-banner {
  background-color: #333;
  color: #fff;
  padding: 12px;
  border-radius: 4px;
}
TypeScript
// {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'] or styles.className in JSX.
  • The component doesn't apply these styles unless it imports the styles object.
  • Only className and id support 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.

SCSS
// chartBase.scss
$chart-font-size: 16px;

.chart-subtitle {
  color: black;
  font-size: $chart-font-size;
}
SCSS
// 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:

SCSS
/* webpackIgnore: true */
background-image: url("/assets/images/logo.png");
Was this page helpful?