Understanding Theme UI: 4 - Scales
- JavaScript
- React
- Theme UI
In this post i’m going to explain how Theme UI’s Theme Scales work. If you’re new to Theme UI i’d suggest having a read of the first three posts in this series to bring you up to speed
Before we dive in i’m going to pull a statement from the Theme UI homepage and try and draw some comparisons between Theme UI and what we already understand about CSS.
Build themeable design systems based on constraint-based design principles
The bit i’d like to hone in on is where it says “constraint-based”. For some having a CSS framework that comes with constraints might be a bad thing, personally for me, it’s a really powerful thing.
Theme UI works by “mapping” certain CSS properties to a targeted object within the main theme object, and encourages you to only use values defined in the corresponding scale.
For example using any of the above methods, (Jsx Pragma, Styled or Components) you’ll likely need to apply padding to a HTML element. Here’s an example.
Src 👇
<Box
sx={{
padding: 4
}}
>
I'm a Box
</Box>
Theme 👇
// path-to-theme/index.js
export default {
...
space: [
'0px',
'4px',
'8px',
'16px',
'32px',
'48px',
'64px'
]
}
You’ll see in the above “src” that the <Box />
has a CSS property of padding
which is assigned a value of 4, but
what is 4?
Here’s some things it’s not
- 4px
- 4em
- 4rem
What 4 relates to is the index in the space
array defined in the theme. In this case 4 is “32px” ,
and the reason this value is stored in the space
array is because one of Theme UI’s constraints is to map padding
to
space
. The longhand for what this might look like in Object Oriented Programming is theme.space[4]
You can see the full set of scales in the docs which explain where each CSS property looks in the theme to find it’s value.
Array Syntax
I’ve gleaned from various discussions about Theme UI that the array syntax for space
can be a little confusing so to
throw an alternative method in to the mix, space
can also be an object. I suspect Theme UI don’t mention this in the
docs is because using an object syntax requires you give each key a name… and namings things is hard.
Src 👇
<Box
sx={{
padding: 'lg'
}}
>
I'm a Box
</Box>
Theme 👇
// path-to-theme/index.js
export default {
...
space: {
none: '0px',
xs: '4px',
sm: '8px',
md: '16px',
lg: '32px',
xl: '48px',
xxl: '64px',
}
}
Object Syntax
In this example padding
is given a “string” value of “lg” and if you look in the space
object you’ll see the lg
key has a value of “32px”. The longhand for this would be theme.space.lg
The space
key names could be anything you want, here’s another example (i’m not suggesting you do this by the way)
Src 👇
<Box
sx={{
padding: 'jaguar'
}}
>
I'm a Box
</Box>
Theme 👇
// path-to-theme/index.js
export default {
...
space: {
none: '0px',
kitten: '4px',
cat: '8px',
cougar: '16px',
jaguar: '32px',
lion: '48px',
tiger: '64px',
}
}
Alt Syntax
As per the previous example padding
is given a “string” value of “jaguar” and if you look in the space
object you’ll
see the jaguar
key has a value of “32px”
Any value mentioned in the space
scale will work in this way, eg, padding-top
, margin
, grid-gap
etc
Moreover any value named in the scales will work in this way. For
instance if you wanted to define a background-color
for the box you could use backgroundColor: "primary"
. The CSS
property for background-color
is mapped to the colors object in the theme, or the longhand would be
theme.colors.primary
.
These constraints may seem foreign at first when working with Theme UI but in theory CSS is by it’s very nature
providing you with a set of constraints. For example when you use the display
property in CSS you are only able to use
values from a constrained set as defined in the CSS spec e.g:
inline
block
flex
grid
… and so on.
Theme UI’s scales are way to limit or restrict values to a certain set or predetermined values, and why would you
need a constrained set of values I hear your cry… well, you don’t it’s entirely possible to give padding:
any value
you like, e.g padding: "100px"
but the point behind the constraints is to limit the amount of low level thinking you
need to do.
If you define a set of values for use around your site or application you’ll only ever need to pick from a handful or
possibilities. If you don’t have these constraints you may find yourself digging around the codebase to find a similar
component and try to match whatever hardcoded px
value was used, or worse… you’ll have to speak with the design
team.
So in my opinion constraints are a good thing.
Not every CSS property is mapped by Theme UI to a scale in the theme object, as mentioned display
can be any value
defined in the CSS spec.
In the next post I’ll be covering how to use breakpoints so sit tight and i’ll be back with examples and explanations for how to make your styles responsive in Theme UI