Globals

Each global has its SCSS file and targets a specific style aspect, from spacing rules to typography settings.

Both the framework (globals) and the components use the BEM naming convention.

Guide content:

  1. Global Editors
  2. How to use the CSS Variable with the CodyHouse Framework

Global Editors #

The Global Editors are web design tools that allows you to design typography elements, color themes, spacing rules, buttons, forms elements in the browser, and export them as SCSS compatible with the CodyHouse Framework.

Explore the Global Editors

CSS Variables #

We use CSS variables as opposed to SASS variables because there are cases where we update the variables at specific media queries (e.g., to make typography responsive), or to create color themes.

To provide a fallback for browsers that don't support CSS variables, we use a modified version of the postcss-css-variables gulp plugin. When you use a CSS variable in your SCSS, the plugin generates a copy of the property replacing the variable with its value (the fallback).

For example, if in your SCSS you write this:

.container--lg {
    max-width: var(--container-width-lg);
}

In your CSS file you have:

.container--lg {
    max-width: 80rem;
    max-width: var(--container-width-lg);
}

There are some limitations though when working with CSS Variables in combo with this plugin: in some cases (listed below), the plugin can't provide a fallback (or it may throw an undefined value). It's important to be aware of these limitations, to avoid potential issues in your code.

Case 1: Local scope

If you define a CSS variable within a selector and then update it in one of its child elements, the plugin generates proper fallbacks.

SCSS:

.text-component {
    --text-vspace-multiplier: 1;

    hr {
        --text-vspace-multiplier: 2;
        margin: calc(var(--space-lg) * var(--text-vspace-multiplier)) auto;
    }
}

CSS generated:

.text-component {
    --text-vspace-multiplier: 1;
  }

.text-component hr {
    --text-vspace-multiplier: 2;
    margin: calc(2em * 2) auto;
    margin: calc(var(--space-lg) * var(--text-vspace-multiplier)) auto;
}

However, if you create a class modifier and update the variable in the modifier, the plugin does not generate a fallback for the children of the modifier, unless their properties are defined in the modifier too.

For example, if we consider this code:

.text-component {
    --component-body-line-height: calc(var(--body-line-height) * var(--line-height-multiplier));
    --component-heading-line-height: calc(var(--heading-line-height) * var(--line-height-multiplier));
    --line-height-multiplier: 1;

    h1, h2, h3, h4 {
        line-height: var(--component-heading-line-height);
    }

    p, blockquote, ul li, ol li {
        line-height: var(--component-body-line-height);
    }
}

.article.text-component { 
    --line-height-multiplier: 1.13;
}

In this case, in browsers that support CSS Variables the children inherit the new variable value of the modifier, while in old browsers you won't see changes. This is handy if the modifiers are "enhancements" (e.g. a color theme that does not convey a meaning other than aesthetic embellishment).

Important: if you create a scoped variable, you should use it within the scope (selector) where it's defined.

Case 2: Global scope

If you update a global variable at a specific media query, the plugin generates a proper fallback, but that means that it creates a media query for each property where the variable has been used, which could result in a lot of unexpected CSS code. This is why global changes (e.g., using a media query) should target the <body> element and not the :root.

:root, body {
    --text-base-size: 1em;
    --text-scale-ratio: 1.2;
}

@include breakpoint(md) {
    body {
        --text-base-size: 1.25em;
        --text-scale-ratio: 1.25;
    }
}

By doing so, the plugin won't generate media queries for all the elements where the variable has been used, thus limiting the variable update to the browsers that natively support CSS Variables (where the new value is propagated anyway). Once again, this works as long as the variable updates can be considered "progressive enhancements". A good example is our responsive typography system.

Case 3: skip the fallback using @support

If you don't want the plugin to generate a fallback, you have the option to wrap your code using the @supports(--css: variables) rule.

@supports(--css: variables) {
    @include breakpoint(md) {
        body {
            --text-base-size: 1.25em;
            --text-scale-ratio: 1.25;
        }
    }
}

A good example is our system for generating color themes, where we define the default theme in the global scope, while the new themes include the @supports(--css: variables) feature query.

In doing so, the themes are visible only in browsers that support CSS Variables, and the plugin does not generate any fallback. If you let the plugin run through a theme, the fallback generated is not correct, and it could result in issues in older browsers.

The takeaway being: use the @supports(--css: variables) if you want to prevent the plugin from generating a fallback because the changes you made won't compromise the user experience in older browsers.

Get started

Explore more about what each global can do in its specific documentation page.

Get started with Alignment 👉