CSS utilities for using and managing FreeAgent design properties
CSS
Permalink
Failed to load latest commit information.
utilities
.gitignore
.npmignore
LICENSE
README.md
_normalize.scss
_project-aliases.scss
_utilities.scss
_utility-aliases.scss
_utility-values.scss
bower.json
package.json

README.md

FreeAgent CSS utilities

These CSS utilities are our ‘one true source’ of design properties at FreeAgent, as used in our CSS framework Origin. They comprise:

  • Universal scales and aliases for: font-size, font-family, line-height, color, background-color, margin, padding, border-radius, and more
  • Library of colours for text and block-level elements
  • Mixins and .u- utility classes for 40+ CSS properties

This means our properties are managed and versioned in a single place, and we have a universal language for using them across our projects and platforms.

For guidance on how we write HTML & CSS at FreeAgent, visit the Origin docs

Install

It’s possible to integrate the utilities into a project of your own, but our CSS framework Origin already uses them. So if you’re developing at FreeAgent, install Origin and you're good to go.

The utilities are implemented in Origin via npm, though it’s available via Bower too:

Overview

Global values and aliases. Global utility values are defined in _utility-values. Utilities font-size, line-height, padding, margin, etc have scales of values, as well as aliases. All aliases live in _utility-aliases.scss. Aliases provide a finite scale (x-small, default, xx-large, etc) to make authoring easier and more meaningful.

Local aliases. You can assign local, project-specific aliases to global values by adding rules to _project-aliases. This way you aren’t continually declaring something like @include line-height(x-loose) for your project’s default line-height. You can just assign x-loose to default for your project.

Turning utility classes on/off. Utility classes mirror the behaviour of our mixins but can be applied to HTML elements directly. Rendering all of them naturally adds a lot of weight a .css file, so they can be individually turned on/off in _utility-settings.scss. Utility classes have !important because utilities exist to do one thing no matter what.

Optional !important. !important can be added to any mixin declaration, e.g.: @include padding(large, !important);. This is especially useful for refactoring; !important allows us a way to turn existing UI patterns that rely on the cascade into completely self-contained components — without breaking lots of stuff. Once a component has been created and rolled out, any !important arguments can just be removed.

Examples

Most utilities can be applied two ways: using mixins in a .scss file, or directly to HTML elements as utility classes. Using mixins is preferred as you get all of the utility functionality without any extra weight being added to the output CSS file, and it encourages the idea of a component-based system.

Using mixins in .scss files

.MyComponent {
  @include background-color(gray-13);
  @include font-family(default);
  @include font-size(large);
  @include line-height(tight);
  @include text-color(fa-blue);
}

.MyOtherComponent {
  @include flexbox(flex);
  @include flex-direction(row-reverse);
  @include flex-justify-content(center);
  @include flex-grow(2);
  @include flex-shrink(0);
  @include margin-top(large);
}

Using utility classes in HTML

Utility classes are useful for prototyping ideas, but use them with care and treat them as stop-gaps (remember they apply !important). Components should handle their own states and variants, so there should be relatively few utility classes being used in production.

You might start with this…

<div class="u-margin--0 u-padding--0 u-text-align--center u-border-radius--default u-border--thin--solid--fa-blue u-line-height--tight u-flexbox u-flex-align-items--stretch u-flex-direction--row">
  <button class="u-background--none u-display--inline-block u-margin--0 u-border-right--thin--solid--blue u-padding--x-small--small u-text-color--x-light u-flex-grow--1 u-text-truncate">Payment</button>
  <button class="u-background--none u-display--inline-block u-margin--0 u-padding--x-small--small u-text-color--x-light u-flex-grow--1 u-text-truncate">Refund</button>
</div>

…but you should end up with:

<div class="SegmentedControl">
  <button class="SegmentedControl-segment">Payment</button>
  <button class="SegmentedControl-segment">Refund</button>
</div>
.SegmentedControl {
  margin: 0;
  padding: 0;
  text-align: center;
  @include border-radius(default);
  @include border(thin, solid, fa-blue);
  @include flexbox(flex);
  @include flex-align-items(stretch);
  @include flex-direction(row);
  @include line-height(tight);

.SegmentedControl-segment {
  background: none;
  display: inline-block;
  margin: 0;
  @include border-right(thin, solid, fa-blue);
  @include flex-grow(1);
  @include padding(x-small, small)
  @include text-color(x-light);
  @include text-truncate;
}

Syntax

.u-<utility>[-descendent][--value]

We write our utilities in lower case as they tend to serve as direct representations of actual CSS properties (as opposed to our components which are written in upper camel case). Keeping the syntax closer to actual CSS not only makes utilties more predictable, it also helps to create a further distinction between components and utilities.

Contributing

All team members should be contributing back to this repo in order to improve it. The process:

Branch off, make changes, create a PR

  1. Make sure you're up to date with the master branch (git checkout master; git fetch; git pull origin master)
  2. Branch off master (git checkout -b <your-branch-name>)
  3. Make your changes
  4. Increment the version numbers in package.json and bower.json. Generally: backwards-compatible fixes and smaller amendments to existing code are patches, new components and breaking changes count as minor releases, and full rewrites are major releases. See semver.org for detailed guidance.
  5. Push up your changes (git push origin <your-branch-name>) and write a helpful pull request describing your changes

Get your PR reviewed, merge to master, create new release

  1. Ask a fellow designer to review your changes. Make any required changes, then merge your branch into master: git checkout master; git merge --no-ff <your-branch-name>
  2. Push up the new version of master (git push origin master).
  3. Create a new release with a useful description. Your original PR is probably a good starting point. If you’re making breaking changes, provide guidance in the release notes about what people will have to change in their projects
  4. Publish the npm package (npm publish) with a new version number. If you don't yet have access to update the npm package, have someone in the design team add as a contributor. There's no need to manually update the Bower package, as Bower relies solely on git tags for package version information.

Let people know, consider upgrading other projects

If this a major or minor release, let people in the #design and/or #dev Slack channels know by linking to the release. Consider bringing other projects up to date with your new release, especially Origin.

How to…

Add a new colour

To create a new colour variable, add it to the Colors section in _utility-values.scss. Your new colour should be defined using the rgb(0, 0, 0) format, and should follow the standard naming syntax: $color--fa-colour-name--variant, e.g. $color--fa-blue--dark.

NB: New colours should only be added to the utilities after you have decided on the exact value, so be sure to test them locally beforehand.

Acknowledgements