Tailwind CSS - Newbie to Pro Guide
September 23, 2024
This article assumes you have some prior knowledge of CSS. If you have yet to learn about Cascading Style Sheets, come back to this guide at a later time. Most web projects on this site make use of React so, for vanilla HTML & CSS Tailwind configurations, please visit the official docs.
The guide below is meant to be a lightweight version of the official documentation and an easy access (don't forget to bookmark it!) cheat sheet. This should include some of the most commonly used features available through Tailwind so that you can be a pro in no time. For more advanced cases not covered here, the official docs will be your best friend. Happy coding!
Getting started
Install Tailwind CSS
1npm install -D tailwindcss postcss autoprefixer
2npx tailwindcss init -p
Understanding the commands above:
- Install tailwindcss and its peer dependencies via npm
- Initialize tailwind by creating your tailwind.config.js and postcss.config.js file
Configure the template paths in the tailwind.config.js file
In order for Tailwind to work properly, it needs to be aware of which files it should look at in your project. We can provide this information to Tailwind by providing the 'content' property in the tailwind.config.js file. This property takes in an array of file paths:
1import type { Config } from 'tailwindcss';
2
3const config: Config = {
4 content: [
5 // Update this with the file paths that apply to you
6 "./index.html",
7 "./src/**/*.{js,ts,jsx,tsx}"
8 ],
9 theme: {
10 extend: {}
11 },
12 plugins: []
13}
Add the Tailwind directives to your CSS
These directives span each of Tailwind's layers. Add them to your main .css file so that Tailwind styling can properly take effect across your entire project.
1@tailwind base;
2@tailwind components;
3@tailwind utilities;
You should be all good to go! Now let's see what features are available to us through Tailwind!
Pseudo-classes
CSS pseudo-classes can be applied in Tailwind by prefixing your tailwind classes with the modifier name followed by a colon ' : '
Tailwind pseudo-class list
Tailwind Modifier | CSS Equivalent |
---|---|
hover: | &:hover |
focus: | &:focus |
active: | &:active |
first: | &:first-child |
last: | &:last-child |
only: | &:only-child |
odd: | &:nth-child(odd) |
even: | &:nth-child(even) |
first-of-type: | &:first-of-type |
last-of-type: | &:last-of-type |
only-of-type: | &:only-of-type |
disabled: | &:disabled |
checked: | &:checked |
required: | &:required |
read-only: | &:read-only |
before: | &::before |
after: | &::after |
placeholder: | &::placeholder |
1<button className="bg-violet-500 text-white hover:bg-violet-600 active:bg-violet-700 focus:outline-none focus:ring focus:ring-violet-300">
2 Styled Button
3</button>
Media Queries
Much like the pseudo-classes above, media queries can be applied in Tailwind by prefixing your tailwind classes with the modifier name followed by a colon ' : '
Tailwind has a set of default breakpoints which you can see below. By default, Tailwind uses a mobile-first breakpoint system, meaning that unprefixed modifiers such as 'border-black' apply to all screen sizes whereas 'md:border-black' applies only at the specified breakpoint and above.
Default breakpoints
Tailwind Modifier | CSS Equivalent |
---|---|
sm: | @media (min-width: 640px) |
md: | @media (min-width: 768px) |
lg: | @media (min-width: 1024px) |
xl: | @media (min-width: 1280px) |
2xl: | @media (min-width: 1536px) |
max-sm: | @media not all and (min-width: 640px) |
max-md: | @media not all and (min-width: 768px) |
max-lg: | @media not all and (min-width: 1024px) |
max-xl: | @media not all and (min-width: 1280px) |
max-2xl: | @media not all and (min-width: 1536px) |
Breakpoint ranges
By default, styles applied by breakpoint modifiers apply at the specified breakpoint and remain at larger breakpoints.
If you'd like to contain some styling to a specific breakpoint range, stack responsive modifiers such as 'md:' and 'max-*'.
1<div className="md:max-lg:flex">
2 <!-- ... -->
3</div>
You can also extend this behavior by creating your own breakpoints in your tailwind.config.{ts | js} file
1import type { Config } from 'tailwindcss';
2
3const config: Config = {
4 theme: {
5 extend: {
6 screens: {
7 customTabletBreakpoint: '768px',
8 customDesktopBreakpoints: '1280px'
9 }
10 }
11 }
12};
13
14export default config;
1<button className="bg-violet-500 px-4 py-2 text-sm w-full sm:w-fit customTabletBreakpoint:text-base">
2 Styled Button
3</button>
Some additional and common modifiers can be found below:
Additional Media Query Modifiers
Tailwind Modifier | CSS Equivalent |
---|---|
portrait: | @media (orientation: portrait) |
landscape: | @media (orientation: landscape) |
motion-safe: | @media (prefers-reduced-motion: no-preference) |
motion-reduce: | @media (prefers-reduced-motion: reduce) |
constrast-more: | @media (prefers-contrast: more) |
contrast-less: | @media (prefers-contrast: less) |
dark: | @media (prefers-color-scheme: dark) |
ARIA Selectors
Some common ARIA (Accessible Rich Internet Applications) selectors are also available through Tailwind, making it easier to target ARIA states specifically:
ARIA Tailwind Modifiers
Tailwind Modifier | CSS Equivalent |
---|---|
aria-checked: | &[aria-checked="true"] |
aria-disabled: | &[aria-disabled="true"] |
aria-expanded: | &[aria-expanded="true"] |
aria-hidden: | &[aria-hidden="true"] |
aria-readonly: | &[aria-readonly="true"] |
aria-required: | &[aria-required="true"] |
aria-selected: | &[aria-selected="true"] |
aria-pressed: | &[aria-pressed="true"] |
Custom Styling
As mentioned prior, you can add your own breakpoints by modifying the tailwind.config.js file however, this is just a small subset of the styling you can extend. Especially for projects with an established branding, configuring your theme in the tailwind config will help ensure consistency and structure throughout your entire project.
For establishing project-wide colors, spacing, typography, and breakpoints, the tailwind config file will be your best friend!
1import type { Config } from 'tailwindcss';
2
3const config: Config = {
4 theme: {
5 screens: {
6 sm: '480px',
7 md: '768px',
8 lg: '976px',
9 xl: '1440px',
10 },
11 colors: {
12 'blue': '#1fb6ff',
13 'pink': '#ff49db',
14 'orange': '#ff7849',
15 'green': '#13ce66',
16 'gray-dark': '#273444',
17 'gray': '#8492a6',
18 'gray-light': '#d3dce6',
19 },
20 fontFamily: {
21 sans: ['Graphik', 'sans-serif'],
22 serif: ['Merriweather', 'serif'],
23 },
24 extend: {
25 spacing: {
26 '128': '32rem',
27 '144': '36rem',
28 },
29 borderRadius: {
30 '4xl': '2rem',
31 }
32 }
33 }
34};
35
36export default config;
For advanced tips, you can view Tailwind's Theme Configuration documentation.
Going beyond with arbitrary values
As a constrained design system, Tailwind does a great job in covering most major use cases however, there are time where we need a specificity which Tailwind does not provide out of the box.
Instead of implementing inline styling or reverting back to normal css to cover such cases, you can make use of Tailwind's square bracket notation to generate classes on the fly.
1<div className="top-[117px]">
2 <!-- ... -->
3</div>
This functions much in the same way as inline styles with the added benefit of being able to combine it with interactive modifiers like hover: and responsive modifiers like lg:
1<div className="top-[117px] lg:top-[344px]">
2 <!-- ... --->
3</div>
In cases where you need to reference a CSS variable, you can simply provide the variable name inside brackets, without the need for specifying var(...)
1<div className="bg-[--my-background-color]">
2 <!-- ... --->
3</div>
Handling whitespace
When one of your arbitrary values needs to contain a space, use an underscore (`_`). Tailwind automatically converts it to a space at build-time
1<div className="grid grid-cols-[1fr_500px_2fr]">
2 <!-- ... -->
3</div>
In places where underscores are common but spaces are invalid, Tailwind will preserve the underscore, for example in URLs.
1<div className="bg-[url('/sample_album_cover.png')]">
2 <!-- ... -->
3</div>
In places where an underscore is ambiguous (where both an underscore and a space are valid) but you actually need the underscore, you may escape the underscore with a backslash and Tailwind will not convert it to a space. NOTE - If you are using something like JSX where the backslash is stripped from the rendered HTML, use String.raw() so that the backslash isn't treated as a JavaScript escape character:
1// Normal HTML
2<div class="before:content-['hello\_world']">
3 <!-- ... -->
4</div>
1// JSX equivalent
2<div className={String.raw`before:content-['hello\_world']`}>
3 <!-- ... -->
4</div>
5
Additional Goodies
There are two other simple features that I would like to note in order to save you some research time: negatives and !important.
Negatives
By default, all Tailwind classes have positive values; in example, take the declaration left-4 into consideration. This style class will position the element 1 rem to the right of the closest relative parent container's left most point. What if you wanted this value to be -1 rem though?
One approach is to use the bracket notation and make this declaration explicit: left-[-1rem].
A simpler solution however, is to simply prefix your class declaration with a dash '-'. Doing so transforms the rendered style value into its negative equivalent
1// transforms the z-index to -50
2<div className="-z-50">
3 <!-- ... -->
4</div>
Important modifier
There may be rare situations where you need to increase the specificity because you're facing conflicts with styles you don't control. To circumvent these conficts, one generally uses the !important CSS property.
In Tailwind, you can specify this same property to your class declarations by prefixing the class with the exclamation mark '!'. This will mark the rendered style with the !important property.
1<p className="!font-medium font-bold">
2 This will be medium even though bold comes later in the CSS.
3</p>
Final Thoughts
A final resource I would like to leave you with is this handy cheat sheet. This will help you more easily identify the Tailwind equivalents to the CSS transformations you are hoping to make. All of this just scratches the surface of what Tailwind can do, however with this short guide, plus the linked cheat sheet, you should be able to tackle any projects without major issues. Thank you for taking the time to read this guide. Happy coding!