How Styles are Parsed

This guide assumes you're familiar with Style Utils, which you can read about in here.

The last argument of every Style Utils function receives a list of style arguments (rest parameter). Style arguments have the following definition:

type GetStyles = (...args: Styles[]) => StyleObject;

As we saw in Styling guide, the getStyle function takes rest parameter Style arguments, and returns a StyleObject. StyleObject is simply a type representation of CSS in JS.

Let's see some examples and their outputs for getStyle style util to understand how styles are applied:

Using Utility Classes

You can use utility classes that translate to JSS:

getStyle('m-4')
// => { margin: '0.25rem' } // equals 4px with html.fontSize 16px
IMPORTANT:

We strongly suggest to use utility classes as much as you can, as this requires you to write the least amount of code and increases the chances of reusing an already cached CSS rule.

Using Style Object

If a utility class is not available with your style rules, you can use JSS as an argument:

getStyle({
marginTop: '6px',
});
// => {
// marginTop: '6px',
// }

Sure, using just a single StyleObject is an over-kill since the output is the same in most cases, but not always. Always use one of the Style Utils, as we do some optimizations to the style arguments and/or cache previously used rules.

Using a Style-Callback Function

Sometimes you need access to the current theme, language direction, and any utility function. In that case, you can pass a function as an argument:

getStyle(({ theme, px2rem }) => {
backgroundColor: theme.spr.ui01,
minWidth: px2rem(28),
}));
// => {
// backgroundColor: '#FFFFFF',
// minWidth: '1.75rem' // equals 28px with html.fontSize 16px
// }

You can also access to theme and other Style Utils from useStyle hook:

import classNames from 'classNames';
...
render() ReactElement {
const { direction, getStyle, theme } = useStyle();
...
return (
<>
...
<p style={getStyle(classNames({
'pr-3': direction === 'ltr',
'pl-3': direction === 'rtl',
}))}>
{text}
<p>
...
</>
)
}

Combining Multiple Argument Types

Here's where Style Utils really shows its usefulness. Again, we start with the approach that we should use utility-classes as much as possible. If there's a class for it, we should use it, instead of writing our own JSS.

Here's an example with multiple argument types:

getStyle(
'm-4',
'mt-0',
{
minWidth: `12.5rem`
},
({ theme }) => ({
backgroundColor: theme.spr.ui01,
})
);
// => {
// margin: '1rem', // equals 16px with html.fontSize 16px
// marginTop: '0',
// minWidth: '12.5rem', // equals 200px with html.fontSize 16px
// backgroundColor: '#FFFFFF',
// }

Important Considerations

Argument Precedence

Arguments are applied from left to right, meaning that the argument to the right overrides the resulting JSS from the argument to its left.

The following code is a good example of argument precedence:

getStyle(
{ margin: 0 },
'm-1',
({ theme }) => ({ margin: theme.margin['4'] }),
);
// => {
// margin: '1rem', // equals 16px with html.fontSize 16px;
// }

Avoid Short-Hand Properties

Shorthand properties are CSS properties that let you set the values of multiple other CSS properties simultaneously. Using a shorthand property, you can write more concise (and often more readable) style sheets, saving time and energy.

While that is fine with CSS, it is not a valid approach for JSS since it produces inconsistent styles.

This problem is caused because JavaScript object is an unordered collection of properties each of which contains a primitive value, object, or function (see https://www.styletron.org/concepts/#shorthand-and-longhand-properties).

Because of this, please avoid using shorthand properties.

Example:

// Instead of:
{ border: '1px solid black' }
// Instead use:
{
borderWidth: '1px',
borderStyle: 'solid',
borderColor: 'black',
}

The margin property is also a common use case where we mix shorthand to reset all margins and then a long-hand to set one side of the box-model with a different value:

{
margin: '0',
marginBottom: '1rem',
}

This also can produce inconsistent results since we cannot ensure the order in which the above rules get applied. Since each one of them will be converted to atomic CSS classes.