Skip to main content

Styling

All design system styling is built on top of "atoms". Each atom represents a single style rule and is usually mapped to a semantic value (e.g. an atomic value such as "large" might map to 24rem) to allow full portability of the design system. This system is similar in concept to Tailwind.

You can see the approach in use in this documentation by inspecting the page. The whole documentation site is built using the components provided by the design system.

It provides a number of benefits:

  • Reduces the need for specific naming. Because naming is hard...
  • Smaller CSS files. Because the available values are limited, consumers of the system won't bloat the stylesheet with similar rules which achieve the same thing
  • Full type safety. If an atom is expecting "sm", "md" or "lg" as its value, a TypeScript build error will be thrown if any other value is provided
  • Atoms are provided by the sprinkles package which builds on functionality provided by vanilla-extract so there is no runtime cost. Stylesheets are compiled at build time.

Atoms can be specified on every component via the atoms prop. Example usage:

import { Box } from '@elsevier/design-system';
export const MyComponent = () => <Box atoms={{ padding: '8px' }}>Some Content</span>;

Atom values can be responsive:

import { Box } from '@elsevier/design-system';
export const MyComponent = () => <Box atoms={{ padding: { mobile: '4px', tablet: '8px' }}}>Some Content</span>;

The styling options that the design system provides won't, and don't intend to, solve all styling problems you'll encounter. There will always be scenarios that sit outside of its capabilities. However, we do encourage you to lean in to it as much as possible. If something you're developing doesn't fit in to the constraints the design system provides consider whether there is another approach that could be taken which would fit more naturally — the more you're able to rely on its primitives the easier future upgrade paths will be.

Logical Properties

Logical properties detach values from a specific direction to open up support for languages which orient in different directions. By using "padding-left" we're explicitly saying that padding, for example, should sit on the left hand side of an element but that may not make sense in a right-to-left (e.g. Arabic) or vertical (Japanese) language. With logical properties we specify that our padding should sit on the "inline-start" (equivalent to left in English) and leave the browser to determine where that actually is based on the language in use.

import { Box } from '@elsevier/design-system';
// paddingLeft => paddingInlineStart
export const MyComponent = () => <Box atoms={{ paddingInlineStart: "8px" }}>Some Content</span>;

See this great introductory article for a full cheatsheet of logical vs direction-relative properties.