Design System Foundations Using Tailwind
The foundation part of the design system comprises all basic styling necessities for a project.
We will go through them one by one and create them using tailwind css.
Colors
We can either extend or completely reset the colors. Let's reset the colors. The brand Color of epicgames.com is #007dfc
. HSL is easy to understand. The brand color translates to ‘hsl(210, 100%, 49%)’
in HSL.
- Hue: 210
- Saturation: 100%
- Lightness: 49%
HSL is great for creating shades for a particular hue.
We can have the hue 210
and change the lightness to create the shades.
theme: {
colors: {
primary: {
50: 'hsl(210, 100%, 97%)',
100: 'hsl(210, 100%, 91%)',
200: 'hsl(210, 100%, 80%)',
300: 'hsl(210, 100%, 70%)',
400: 'hsl(210, 100%, 60%)',
500: 'hsl(210, 100%, 49%)',
600: 'hsl(210, 100%, 39%)',
700: 'hsl(210, 100%, 28%)',
800: 'hsl(210, 100%, 16%)',
900: 'hsl(210, 100%, 10%)',
},
},
extend: {},
},
The range of lightness I came up with is purely using the eyes. We can simply divide them uniformly but I wanted the primary-50
to be almost white and primary-900
to be almost black.
It is gray. But “primarily” tinted!
The primary color is for cueing the user about the most important thing to notice on a page. But gray is the most used color in any application.
A plain gray won’t break the user experience but if we tint it with the primary color, it gives a good mood.
Using HSL format helps us easily come up with related colors with great precision.
Gray can be achieved by reducing the saturation to 0% at any hue. But we generate our gray like below to match our primary color.
- Retain
Hue
as210
. - Reduce
saturation
from100%
to around12%
.
gray: {
50: 'hsl(210, 12%, 97%)',
100: 'hsl(210, 12%, 91%)',
200: 'hsl(210, 12%, 80%)',
300: 'hsl(210, 12%, 70%)',
400: 'hsl(210, 12%, 60%)',
500: 'hsl(210, 12%, 49%)',
600: 'hsl(210, 12%, 39%)',
700: 'hsl(210, 12%, 28%)',
800: 'hsl(210, 12%, 16%)',
900: 'hsl(210, 12%, 10%)',
}
How does our tinted GRAY
(12% saturated)
look compared to the GRAY-PLAIN (0% saturated)
?
You can increase or decrease the 12%
which I found to be a sweet spot to tint.
Imagine doing this in HEX
code? HSL
makes it simple to masterfully come up with colors.
Let's use the same technique to create two more colors.
- Red:
#f73131
orhsl(0, 93%, 58%)
- Green:
#00CC66
orhsl(150, 100%, 40%)
That's it for the colors. We can revisit later if we want more colors or modify the shades as needed. This tailwind configuration we create here will be propagated throughout the project instantly.
Remember:
- We have completely replaced the colors that come with tailwind with these four colors.
Typography
Font size
We reset the tailwind’s type scale with the below.
fontSize: {
// Body copy
'xs': ['.75rem', '1rem'],
'sm': ['.875rem', '1rem'],
'base': ['1rem', '1.5rem'],
'lg': ['1.125rem', '1.5rem'], // Headings
'xl': ['1.5rem', '2rem'],
'2xl': ['2rem', '2.5rem'], // Display
'3xl': ['5rem', '6rem'],
'4xl': ['10rem', '10rem'],
},
We can not discuss font size without line-height. The second item in each array is line-height.
A thing to notice is, we try to achieve an 8px
grid as much as possible. All the line heights above are divisible by 8 and hence they fit in 8px grids nicely.
This is how our type scale looks.
Body copy
text-xs
is mostly used for badges. If we go with full uppercase with relaxed letter spacing, anxs
looks good compared tosm
orbase
.text-sm
is helpful for the text in product cards.text-base
is the base size that applies by default. We picked16px
as the base for this e-commerce product. But remember the body text you are currently reading is21px
(in desktop mode).text-lg
can be used for callouts, descriptions, etc. This can be used as a heading too with enough font-weight usingh3
.
Headings
text-xl
is ourh2
.text-2xl
is ourh1
.
Display Headings
text-3xl
andtext-4xl
are used in rare situations where we need obnoxiously huge texts.
Font weight
The text size does not have to dictate hierarchy. Our limited headings text-xl
and text-2xl
can be emphasized by providing a thicker font-weight.
Letter Spacing
The bigger the text is, the tighter the letter-spacing should be.
Line height
Line height can be fixed or relative. We have already given suitable line heights for each text size.
Relative line heights work like percentages. I reset the tailwind config to include only the relative line-heights.
lineHeight: {
'no-gap': '.8',
'extra-tight': '.9',
'none': ' 1',
'tight': ' 1.25',
'snug': ' 1.375',
'normal': ' 1.5',
'relaxed': ' 1.625',
'loose': ' 2',
}
The smaller the text is the larger the line height should be.
Shadows
Tailwind CSS comes with a good range of shadows with the classes shadow-sm -> shadow-2xl
. Let’s use them as it is.
Light source
The light source is assumed to be behind the top of the user’s head making the shadows fall below the object.
Foreground color
Making the default background color a shade darker will get de-emphasized automatically.
Dark mode
In dark mode, the shadows almost won't work. The difference in lightness between the foreground vs background gives a sense that the lighter items are closer to the user.
The lighter items look closer.
Also, notice how the darker card shadow-inner
looks like a punched-out hole even though the inner shadow is almost nonexistent.
Spacing
In the text size section, we did a deliberate effort to make the line-heights divisible by 8px
.
Spacing is another thing that we have to focus on making them adaptable to the 8px
grid. But it is not very practical to have the smallest size as 8px
. So, we include 0.125 (2px)
and .25 (4px)
for a little nudge here and there. After that, they are all 8px
divisible.
spacing: {
0: '0rem',
0.5: '0.125rem',
1: '.25rem',
2: '.5rem',
3: '1rem',
4: '1.5rem',
5: '2rem',
6: '3rem',
7: '4rem',
8: '5rem',
9: '6rem',
10: '8rem',
11: '10rem',
12: '12rem',
13: '16rem',
14: '20rem',
15: '24rem',
16: '32rem',
},
Icons
I copied the necessary SVGs from hero icons. I exported them from an index.
Keeping a separate library instead of relying on a third-party library is debatable. But I believe any software product can do fine with a handful of icons.
Cons:
- This way is slow when the developers need additional icons.
- Icons can become inconsistent if we start copying SVGs from multiple sources.
zIndex
Tailwind comes with zIndex classes for values 0,10,20,30,40,and 50
. I prefer having one value behind 0
.
So, let's extend zIndex to have -10
.
extend: {
zIndex: {
'-10': -10,
},
}
Flexbox and Grid
The utility classes tailwind provides for flexbox and grid are going to be responsible for our layout design throughout our application.
It is important to have small how-to-approach demos for layout designs. But currently, I leave this in the flexbox and grid page in our design system. We can develop this later if we want.
Addons
Let's add line clamp and aspect ratio as add-ons.
// Install
npm i @tailwindcss/aspect-ratio @tailwindcss/line-clamp// Import in tailwind.config.js
const lineClamp = require('@tailwindcss/line-clamp')
const aspectRatio = require('@tailwindcss/aspect-ratio')// Add this in module.exports.
plugins: [lineClamp, aspectRatio]
JIT
TailwindCSS JIT brings immense benefits to the developer experience. Have look at the official documentation for details.
- Add
mode: ‘jit’
in the tailwind.config.js. - Add
TAILWIND_MODE=watch
in the start scripts.
"start": "TAILWIND_MODE=watch craco start",
"storybook": "TAILWIND_MODE=watch start-storybook -p 6006 -s public",
The config file
After all the work, taliwind.config.js will become like below.
Conclusion
We have created the foundation for our design system. Next up we will be creating base components like accordions, avatars, buttons etc.
That’s it.
Thank you. See you next time.