Mathias Polligkeit
  • Dev
  • Impro
  • Sheet Music
  • Contact
Nov 18, 2021 (last updated: Dec 7, 2021)

Design Systems, Pt. 1: The Base

This document outlines properties and naming conventions for design systems that can be implemented in SASS/SCSS or in vanilla CSS.

For each item, several properties are listed:

  • Key: The theme configuration is assigned to a $theme variable. The key is the map key under which the value is found.
  • Function: The function name for accessing values from map variables. It is preferred to define accessor functions for maps, since this allows us to return error messages that list the valid values in case a key does not exist.
  • Naming: The format of the base name for custom properties and class names.
  • Custom properties: The format of the custom property, using the base name. If SASS is used, the custom properties are generated from the SASS variables.
  • Examples: These are examples for the base name.

While the document lists SASS variables and function names, the naming conventions can be used for class names and custom properties without SASS.

All variable names and values use kebab case (e.g. my-variable). The naming should be consistent across all design documents and in the code base.

Colors

  • Key: colors (map)
  • Function: color($name)
  • Naming: [(bg|border|text)-]<name>[-(<modifier>|<shade>)]
  • Custom properties: --color-<name>

Semantic color names are preferred over concrete color names to support multiple themes. For neutral tones, background and foreground can be used instead of black and white, unless there are other background and foreground colors. shade can be used for shades of gray. The base name should not consist of more than two segments.

Color names can be prefixed by an identifier for the designation (bg for background, border and text).

Color names can be suffixed by a modifier (e.g. -hover, -disabled).

A color schema can include color variations. If color variations are included, the base color is suffixed with -500. Lighter versions of the color are suffixed with 600, 700, 800, 900, while darker versions are suffixed with 400, 300, 200, 100.

A modifier and a shade should not be combined.

Examples: foundation, foreground, background, primary, secondary, tertiary, success, info, warning, error, link, border-primary, bg-primary, bg-primary-600, text-primary, link-hover, primary-500, shade-700

Example definition

As an example, you would define the $colors variable in SASS like this:

$theme: (
  colors: (
    foundation: #09080d,
    primary: #62a1d9,
    secondary: #363859,
    warning: #d9b343,
    error: #bf3636
  )
);

Which translates to these custom properties:

--color-foundation: #09080d;
--color-primary: #62a1d9;
--color-secondary: #363859;
--color-warning: #d9b343;
--color-error: #bf3636;
--color-shade-500: #666666;

You would access a color value in SASS with: color(primary) (after defining the function).

Font families

  • Key: font-families (map)
  • Function: font-family($name)
  • Naming: <name>
  • Custom properties: --font-family-<name>

Examples: main, serif, monospace

Font sizes

Base size

  • Key: base-size (length, default: 100%)
  • Custom property: --base-size

Serves as the body font size and as the base for generated type scales and line heights.

Font sizes can either be defined manually or generated from a modular scale.

Manually defined font sizes

  • Key: sizes (map)
  • Function: size($name)
  • Naming: <size-in-px> | <clothing-size>
  • Custom properties: --size-<name>

Define a fixed set of allowed font size.

Either use the pixel sizes as identifiers for sizes, or use clothing sizes (xs, s, m, l, xl etc.).

If you use clothing sizes, ensure that the font styles in the graphic software consistently use the same names. If that is not possible, it is preferred to use pixel sizes as names, since this makes it easier to transfer font sizes from the mock-up to the code base.

Examples: 12, 14, 16, 14 or xxs, xs, s, m, l, xl, xxl

Generated font sizes based on a modular scale

  • Variables: $modular-scale (number), $larger-sizes (number), $smaller-sizes (number)

$modular-scale defines the ratio for the modular type scale (e.g. 1.25, 1.333).

$larger-sizes defines how many font sizes should be generated larger than the base size.

$smaller-sizes defines how many font sizes should be generated smaller than the base size.

Example

$base-size: 100%; // 16px
$modular-scale: 1.25;
$larger-sizes: 3;
$smaller-sizes: 2;

This generates the following font size variables:

  • size-xs: 0.64rem = 10.24px
  • size-s: 0.8rem = 12.8px
  • size-m: 1rem = 16px (size-m always matches the base size)
  • size-l: 1.25rem = 20px
  • size-xl: 1.563rem = 25px
  • size-xxl: 1.953rem = 31.25px

If more font sizes are generated, more x’s will be added.

Line heights

  • Key: base-line-height (number)
  • Custom property: --base-line-height

$base-line-height defines the base line height related to the font size in em.

Line heights can either be defined manually or generated from a list of factors.

In order to keep a vertical rhythm, it is recommended to only use the defined line heights for vertical spacing.

Manually defined line heights

  • Key: lines (map)
  • Function: lines($factor)
  • Naming: <factor>
  • Custom properties: --lines-<name>

Lines are defined as multiples of the base line height. Fractions in property and variable names are written with an underscore.

Examples: 1_2, 1, 3_2, 2

Generated line heights

  • Key: line-heights (list)
  • Function: lines($factor)
  • Custom properties: --lines-<name>

$line-heights defines the multiples of the base line height to be used.

Example

$base-size: 16px;
$base-line-height: 1.5;
$line-heights: (0.5, 1, 1.5, 2, 3);

This results in the following properties (fractions in property names are written with an underscore):

  • --lines-1_2: 16px * 1.5 * 0.5 = 12px
  • --lines-1: 16px * 1.5 * 1 = 24px
  • --lines-3_2: 16px * 1.5 * 1.5 = 36px
  • --lines-2: 16px * 1.5 * 2 = 48px
  • --lines-3: 16px * 1.5 * 3 = 72px
  • Variable: $line-heights (list)

Letter spacing

  • Key: letter-spacings (map)
  • Function: letter-spacing($name)
  • Naming: <name>
  • Custom properties: --letter-spacing-<name>

Examples: narrow, normal, medium, wide

Font weights

  • Key: weights (map)
  • Function: weight($name)
  • Naming: <name>
  • Custom properties: --weight-<name>

Examples: normal, medium, bold

Radius

  • Key: radii (map)
  • Function: radius($name)
  • Naming: <name>
  • Custom properties: --radius-<name>

Examples: small, medium, large, full

Spacers

Spacers are mainly for horizontal margins and paddings. For vertical margins and paddings, lines should be used if possible.

Spacers can either be defined manually or generated from a list of factors.

Manually defined spacers

  • Key: spacers (map)
  • Function: spacer($name)
  • Naming: <integer>
  • Custom properties: --spacer-<name>

Examples: 1, 2, 3, 4

Generated spacers

  • Keys: spacer-base (length), spacer-factors (list)
  • Function: spacer($factor)
  • Custom properties: --spacer-<n>

$spacer-base defines the smallest spacing unit (e.g. 4px or 0.25rem).

Spacers are defined as multiples of the spacer base.

$spacer-factors defines for which factors classes and custom properties will be generated. The variable does not affect the spacer function.

Border widths

  • Key: border-widths (map)
  • Function: border-width($name)
  • Naming: <name>
  • Custom properties: --border-width-<name>

Examples: border-width-small, border-width-medium, border-width-large

Prose width

  • Key: measure (length, default: 60ch)
  • Custom property: --measure

The maximum width for paragraphs.

Gutter

  • Key: gutter (length)
  • Custom property: --gutter

The size of the space between columns.

Breakpoints for media queries

  • Key: breakpoints (map)
  • Function: breakpoint($name)
  • Naming: <device>
  • Custom properties: --breakpoint-<name>

The names for breakpoints should be derived from devices.

Examples: mobile, tablet, desktop, widescreen

Example theme

This is the base theme for this blog:

@use "sass:string";

$theme: (
  colors: (
    text: #202c31,
    primary: #71819c,
    selection: #b15e5e,
    shade-primary: #a0a0a0,
    shade-secondary: #6b7380,
    light-primary: #eaeaea,
    light-secondary: #fafafa,
    light-tertiary: #b0b0b0,
    background: #fff
  ),
  font-families: (
    main: "Lato, sans-serif",
    alt: "Montserrat,  sans-serif",
    mono: string.unquote('"Source Code Pro", monospace')
  ),
  base-size: 100%,
  sizes: (),
  modular-scale: 1.149,
  smaller-sizes: 2,
  larger-sizes: 6,
  base-line-height: 1.7411,
  lines: (),
  line-heights: (
    0.25,
    0.5,
    0.75,
    1,
    1.5,
    2
  ),
  letter-spacings: (),
  weights: (
    normal: 400,
    code: 500,
    header-bold: 600,
    bold: 700
  ),
  radii: (),
  spacer-base: 0.25rem; border-widths:
    (
      small: 1px,
      medium: 3px,
      large: 6px
    ),
  gutter: 1.5rem,
  measure: 75ch,
  breakpoints: ()
);

Which is translated into these custom properties:

:root {
  --color-text: #202c31;
  --color-primary: #71819c;
  --color-selection: #b15e5e;
  --color-shade-primary: #a0a0a0;
  --color-shade-secondary: #6b7380;
  --color-light-primary: #eaeaea;
  --color-light-secondary: #fafafa;
  --color-light-tertiary: #b0b0b0;
  --color-background: #fff;
  --font-family-main: Lato, sans-serif;
  --font-family-alt: Montserrat, sans-serif;
  --font-family-mono: "Source Code Pro", monospace;
  --size-xs: 0.757460417rem;
  --size-s: 0.8703220191rem;
  --size-m: 1rem;
  --size-l: 1.149rem;
  --size-xl: 1.320201rem;
  --size-xxl: 1.516910949rem;
  --size-xxxl: 1.7429306804rem;
  --size-xxxxl: 2.0026273518rem;
  --size-xxxxxl: 2.3010188272rem;
  --lines-1_4: 0.435275rem;
  --lines-1_2: 0.87055rem;
  --lines-3_4: 1.305825rem;
  --lines-1: 1.7411rem;
  --lines-3_2: 2.61165rem;
  --lines-2: 3.4822rem;
  --weight-normal: 400;
  --weight-code: 500;
  --weight-header-bold: 600;
  --weight-bold: 700;
  --border-width-small: 1px;
  --border-width-medium: 3px;
  --border-width-large: 6px;
  --measure: 75ch;
  --gutter: 1.5rem;
}

Next part: Design Systems, Pt. 2: Generating Sizes, Line Heights and Spacers

  • design-systems
  • sass

See Also

  • Design Systems, Pt. 9: Conclusion
  • Design Systems, Pt. 8: Layout Rules
  • Design Systems, Pt. 7: Project Structure
  • Design Systems, Pt. 6: Variable Export
  • Design Systems, Pt. 5: Themes
  • privacy policy