Skip to main content

Style sheets

Styles within Aesthetic are managed through style sheets and are divided into the following 2 categories.

Style sheets are created with either the createElementStyles(), createComponentStyles(), or createThemeStyles() methods respectively. All methods require a function that returns a style object (also known as a factory function).

import { createComponentStyles } from '@aesthetic/<integration>';
const styleSheet = createComponentStyles(() => ({
button: {
appearance: 'none',
backgroundColor: 'transparent',
border: 0,
cursor: 'pointer',
display: 'inline-flex',
fontSize: 'inherit',
margin: 0,
padding: '6px 8px',
textAlign: 'center',
textDecoration: 'none',
userSelect: 'auto',
verticalAlign: 'middle',
},
}));

Utilities#

Manually writing style objects over and over can be tiresome, especially when you need to reuse consistent values (font sizes, spacing, etc) across many components. Aesthetic solves this through its robust design system, which is a hard requirement as it powers all reusability. To make use of this, the design system must be compiled into JavaScript/TypeScript based design tokens.

A few design token based utility methods are passed to the 1st argument within the style sheet factory function. We like to name this object css, as demonstrated within the examples below.

Variables#

Variables are consistent and reusable values that are derived from settings within a design system's language and themes. A variable can be accessed with the var(name: string) method, which requires a fully qualified name based on the token object structure.

Let's now update our example to not use hard-coded padding values, while also using expanded properties.

const styleSheet = createComponentStyles((css) => ({
button: {
appearance: 'none',
backgroundColor: 'transparent',
border: 0,
cursor: 'pointer',
display: 'inline-flex',
fontSize: 'inherit',
margin: 0,
padding: {
topBottom: css.var('spacing-df'), // Default padding
leftRight: css.var('spacing-md'), // Medium padding
},
textAlign: 'center',
textDecoration: 'none',
userSelect: 'auto',
verticalAlign: 'middle',
},
}));

Variables utilize CSS variables under the hood for dynamic styling and reduced output size.

Mixins#

Mixins also provide reusability, but instead of providing a single value, they provide a collection of pre-styled CSS properties that can be merged into your own style objects via the mixin(name: string, styles?: object) method.

Continuing our example even further, let's easily reset our button. You'll notice that we removed most of the properties. That's because they are provided by the mixin and we no longer have to define them manually!

const styleSheet = createComponentStyles((css) => ({
button: css.mixin('reset-button', {
padding: {
topBottom: css.var('spacing-df'),
leftRight: css.var('spacing-md'),
},
textAlign: 'center',
}),
}));

Units#

If you ever need a rem unit based on the design system's spacing type, use the unit(...sizes: number[]) method, which requires any number of multipliers.

Let's say our root text size is 16px and our spacing unit is 8px, we would generate the following rem values.

const styleSheet = createComponentStyles((css) => ({
button: {
// All edges
padding: css.unit(1), // .5rem
// Top/bottom, left/right
padding: css.unit(1, 2), // .5rem 1rem
// Top, right, bottom, left
padding: css.unit(1, 2, 3, 4), // .5rem 1rem 1.5 2rem
// ...
},
}));

Using explicit units is frowned upon as it deviates from the design system's strict spacing guidelines. It also increases the CSS output size as it generates additional class names. Use sparingly.