Overview

This page will guide you through styling components in Nova.

Included,

  • Explanations on how CSS is organized
  • Common patterns

Prerequisites

ℹ️

To be truly successful writing styles in Nova, you should read Every Layout (link (opens in a new tab)) and our documentation on Styling/CSS Framework.

Understanding Nova Framework styles vs brand styles

It's important to make a distinction between styles that load everywhere and are part of the Nova Framework, versus styles that only load for a specific brand. This can get a little confusing because there's also a Nova "brand".

  • Styles in the Nova Framework will load everywhere.
  • Styles for the Nova brand will only load for Nova, not specific brands.

This distinction allows us to style the Nova brand as an example for others to follow, but without requiring other brands to unset values.

ℹ️

Protip: When in the style guide, use b as the "brand" hotkey to enable/disable brand styles, quickly toggling allows you to visualize how the Nova Framework vs. brand styles are being applied.

Nova Framework

Styles for the Nova Framework are expected to load everywhere and serve as the base layout for all brands.

Globally/Plain SCSS For global styles you want to load everywhere, see /styles/nova/index.scss.

Components/CSS Modules For component styles you want to load everywhere, use the /styles.module.scss file in each component.

Brands

Styles for specific brands load conditionally and sit on top of the Nova Framework, extending the base for brand needs.

Globally/Plain SCSS The styles/{brand-name}/index.scss can be used as an entry point for styles that should always load and aren't tied to a specific component.

This is good for setting up typography.

Components/CSS Modules Edit or create pmc-nova/style-guide/components/{component-name}/brands/{brand-name}.module.scss.

These values will load for every brand.

Patterns

Data attributes

Components often use data attributes to target styles instead of class names. This allows us to more easily target components/elements outside of our immediate localized scope and helps reduce spaghetti CSS code where it's unclear how and why styles are being applied.

Alias

Hover styles

We use the container-queries.hover() mixin to only apply hover styles to devices that support them.

Any use of the :hover pseduo-class selector should be wrapped in this mixin.

Z-Indexes

Organization

To create the clearest hierarchy of z-indexes, all uses of z-index should be set to CSS variables and organized in /styles/brands/nova/z-indexes.scss (ref (opens in a new tab)).

Common Tasks

How do I style elements that aren't localized?

[Answer in draft form]

One of the tricky bits of CSS modules, is how to target components that aren't within the current scope.

For example, if I wanted to change the color of an icon from within a button context, we are unable to use any of the icon classes, which are dynamically created and namespaced.

We get around this with the data-alias="component-name__component-area syntax.

For example, we may use a <Text /> component inside of a button,

const Button = () => {
	<button>
		<Text { ...text } />
	</button>
}

But we can't access any of the classes used in <Text /> from within our button component, or components higher up.

.button {
	[data-component="text"][data-alias="button__text"] {
		// Target the right element.
	}
}

We use BEM naming conventions.