Skip to content

Svala generates your CSS utility classes and design tokens. It is built with Sass, not JavaScript.

License

Notifications You must be signed in to change notification settings

polarbirke/svala

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Svala

Svala is a tool to quickly generate CSS utility classes.

  • No JavaScript. Svala is written in Sass (SCSS), not JavaScript. While you need a pipeline to compile Sass to CSS, configuration is done in Sass.
  • Highly customisable. Svala is designed to adapt to your way of working, not the other way around. You can generate verbose classes like .margin-left or use shorthand like .ml, define prefixes (or "namespaces") like .yolo-flex and .u-hidden or use hierarchical scales to get output like .grey-100, .grey-200, .grey-300, ….
  • Responsive. Svala can take your breakpoints and generate classes for responsive use. You can pick your breakpoint names, choose if you want them in a trailing (e.g. .hidden@desktop) or leading position (e.g. .lg:hidden) and pick their separator (e.g. @ or :).
  • Small footprint. There is no default output – Svala generates what you configure. Grow your utility classes with the requirements of your project and keep your CSS lean and clean.

If you have not heard of utility classes before, there are plenty of fantastic articles about them online – use your search engine of choice!

Here are two recommendations:

Installation

Get Svala from npm by running

npm install svala

in your terminal. Use yarn add svala if you prefer Yarn.

Requirements

Svala is written in Sass, which means you need a way to compile it to CSS. Furthermore, Svala requires Dart Sass because it makes use of its module system with @use and @forward It doesn't matter if you love Gulp, use node-sass on the command line or if Webpack is your jam. Anything that can compile Sass to CSS will work. Here's a tutorial for one way to do it.

Usage

Overview

If you're thinking about utility classes, you're probably familiar with CSS ruleset terminology. Svala uses well-defined terms like selector, property and value, as well as a few others:

  • base selector (or token): The base name for your selector. Typically, you will use the CSS property you want to control for this, e.g. margin or border.
  • axis: Svala introduces a concept called axes (plural, long 'e' 😉). An axis can be used to enhance a base selector with directional input, e.g. margin-left or border-right.
  • value: Values are the bread and butter of utility classes. Svala allows you to define a list or map of values to iterate over, e.g. a size scale for visual hierarchy or a set of different values like auto, hidden, scroll. Value names are appended to the base selector (or axis, if applicable).
  • state: If you need to factor pseudo-classes into your utilities, Svala has you covered. Use states to generate class variants for :hover, :focus, :checked and others.
  • breakpoint: All your classes can be scoped to your project's breakpoints and cater to your responsive needs.
  • prefix and postfix: You can add extra bits to the beginning and/or end of your selectors by using prefixes and postfixes. Use this to namespace your utility classes with .u-, for example.

Let's look at a practical example:

.margin-left-300@tablet { … }

"margin" is the base selector, which is enhanced with "left" as an axis and "300" as the value from a size scale. It should apply to the breakpoint named "tablet".

The configuration for this single class could look like this:

$example1-config: (
    'margin': (
        'property': 'margin',
        'axes': left,
        'values': (
            '300': '0.75rem' 
        )
    )
);

Here is a second example:

.u-overflow-x-hidden { … }

This selector uses a prefix ".u-", the base selector "overflow" and was extended with the axis "x" and the value "hidden".

// Please refer to the section about "Output settings" to
// learn how to configure prefixes!

$example2-config: (
    'overflow': (
        'property': 'overflow',
        'axes': x,
        'values': hidden
    )
);

Output settings

The first thing you'll want to do with Svala is to adjust the output to your liking. There are a few options at your disposal:

Option Value Default Description
breakpoints map null Your project's breakpoints. Configure them as a map with ('name': 'media query') pairs like ('tablet': 'min-width: 768px'). The name will be added to your class selector.
prefix string 'u-' An optional prefix for all your utility classes. Use it to avoid collisions ("namespace") with third-party CSS or distinguish utility classes from "regular" ones. You can also reset it by setting it to an empty string: ''.
postfix string '' An optional postfix for all your utility classes. Use it for the same reasons as you would a prefix, or leave it empty.
axis-modifier-divider string '-' The character joining your base selector and any axis, e.g. .u-margin-left or .u-float-right. Any valid characters are allowed, as is ''.
value-modifier-divider string '-' The character joining your selector and any values, e.g. .u-overflow-hidden for a named value or .u-grey-200 for a scale item. Any valid characters are allowed, as is ''.
state-modifier-divider string '\@' The character joining your selector and any state, e.g. .u-border@hover. Note that special characters like : or @ that are commonly used for this purpose have to be escaped with a double backslash.
breakpoint-modifier-divider string '\@' The character joining your selector and any breakpoint name, e.g. .u-hidden@desktop.
stateful-mode 'leading' or 'trailing' 'trailing' Define where states (e.g. 'hover' or 'visited') are added to selectors: prepended before the selector (but after both prefix and breakpoint, if applicable) or appended after axis and values.
responsive-mode 'leading' or 'trailing' 'trailing' Define where breakpoint names (e.g. 'tablet' or 'medium') are added to selectors: prepended before the selector (but after the prefix, if applicable) or appended after axis, values and state.

Create a variable called $svala-options and use a map to set your preferences and merge those with Svala's defaults:

$breakpoints-map: (
    'md': 'min-width: 768px',
    'lg': 'min-width: 1280px'
);

$my-options: (
    'breakpoints': $breakpoints-map,
    'breakpoint-modifier-divider': '\\:',
    'state-modifier-divider': '\\:',
    'responsive-mode': 'leading',
    'stateful-mode': 'leading',
    'prefix': ''
);

$svala-options: map-merge($svala-default-options, $my-options);

Here we're adding a set of breakpoints and tell Svala to output classes without a prefix, but with leading breakpoint and state information (a style popularized by Tailwind CSS) like .lg:border or even .lg:hover:border-bottom.

Generate your utility classes

Svala uses nested Sass maps and lists for configuration. The following parameters can be configured:

Parameter Type Default Description
property string none Required. Must be a valid CSS property.
values string or map or list null The value that should be applied to the property. Can be a single value passed as string, a list of named values or a map with key,value pairs.
axes map or list null A list of axes. Must be valid CSS directions or axes.
states list null A list of pseudo-classes. Must be included in the supported pseudo-classes.
responsive boolean false Determines whether to generate responsive class variants. Svala will use the breakpoints from the global config.
important boolean false Determines whether !important should be added. Use with care.

Start with importing the generator from the package:

// This is an exmaple, your path to Svala may need to  
// be different, depending on your folder structure 
@import "node_modules/svala/scss/generator";

You can pass a config map to the Svala generator directly or create a variable and pass that. Here we're doing the latter:

$config: (
    'border': (
        'property': 'border',
        'value': '1px solid black'
    )
);

This assigns a map to $config. The key of the only map entry, 'border', is your base selector and its value – a nested map – holds the rest of the settings for this particular class.

Now all that is left to do is to call the generator mixin with your config:

@include generator($config);

If you didn't change Svala's default options, this will create the following CSS output:

.u-border {
    border: 1px solid black;
}

Let's look at a second example and pass the config directly this time:

@include generator((
    'position-absolute': (
        'property': 'position',
        'value': 'absolute'
    )
));

With Svala's default options, this will result in:

.u-position-absolute {
    position: absolute;
}

Axes

There are many CSS properties that can affect a specific direction. This includes the -top, -right, -bottom, -left modifiers for properties like margin, padding or border as well as -x and -y modifiers for overflow or overscroll-behavior. Finally, there are the newer CSS Logical Properties like block-start or inline-end that enable us to create layouts that adhere to any writing mode and not just left-to-right / top-to-bottom. In Svala, these modifiers are called axes.

Let's look at an example:

@include generator((
    'border': (
        'property': 'border',
        'axes': top right bottom left,
        'value': '1px solid black'
    )
));

With Svala's default options, this will result in:

.u-border {
    border: 1px solid black;
}

.u-border-top {
    border-top: 1px solid black;
}

.u-border-right {
    border-right: 1px solid black;
}

.u-border-bottom {
    border-bottom: 1px solid black;
}

.u-border-left {
    border-left: 1px solid black;
}

You can also customize the axes output to your liking. The example above defines a Sass list as the value for the axes key. If you switch to a Sass map, you can change the name of the axis (the part that ends up in the selector) and also pass multiple values per axis.

Here's an example with both advanced use cases:

@include generator((
    'property': 'margin',
    'value': '1rem',
    'axes': (
        't': 'top',
        'r': 'right',
        'b': 'bottom',
        'l': 'left',
        'h': ('right', 'left'),
        'v': ('top', 'bottom')
));

will generate (with default settings):

.u-margin {
    margin: 1rem;
}

.u-margin-t {
    margin-top: 1rem;
}

.u-margin-r {
    margin-right: 1rem;
}

.u-margin-b {
    margin-bottom: 1rem;
}

.u-margin-l {
    margin-left: 1rem;
}

.u-margin-h {
    margin-right: 1rem;
    margin-left: 1rem;
}

.u-margin-v {
    margin-top: 1rem;
    margin-bottom: 1rem;
}

Values

States

Svala supports a subset of all possible pseudo-classes for use as states:

'active', 'checked', 'disabled', 'empty', 'first', 'first-child', 'first-of-type', 'focus', 'focus-visible', 'focus-within', 'hover', 'invalid', 'last-child', 'last-of-type', 'link', 'only-child', 'only-of-type', 'optional', 'required', 'target', 'target-within', 'valid', 'visited'

About

Svala generates your CSS utility classes and design tokens. It is built with Sass, not JavaScript.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published