- Source: GitHub
Tailwind CSS
Overview
Introduction
- Tailwind CSS is a utility-first CSS framework
- It provides thousands of pre-defined classes, no longer need to maintain custom CSS
- Promotes consistency, efficiency and scalability
- Used by many large companies such as Netflix and OpenAI (ChatGPT)
- Easy to also append custom CSS for edge cases
History
- Created by Adam Wathan in 2017, motivated by the unmaintainability of writing traditional CSS
- Tailwind v2.1 introduced JIT compiler with the ability to purge unused CSS for minification
- Currently in v3.4.13, purge is removed since it only generates the minimum CSS
- In the future, v4.0 will release with Oxide (new engine), faster parsing, build times with a unified tool chain
Inspiration
-
As we know, styles are applied by adding class tags to the class attribute in HTML elements
-
Class names typically reflect the appearance of the component
<div class='profile-card' />
- However, we might want to reuse card looking components throughout a project
- Instead, use general classes that can be reusable
<div class='card' />
- However, we might want to reuse card looking components throughout a project
-
Issue: Each use case of a general class may be slightly different
- Ex. one place might want a box-shadow, another place might want a border radius
-
Solution: Extract non-common CSS properties into their own class
<div class='card card-rounded card-shadow'/>
.card-rounded { border-radius: 30px; }
-
Notice how the extracted class only does one thing
-
Tailwind applies the concept of atomic CSS, creating small, single-purpose classes
<div class='flex p-2 font-sans shadow-md rounded-xl' />
Pitfalls
- Learn Tailwind syntax
- Bloats the HTML structure with class tags, affecting readability
- Hard to migrate to another CSS framework since your current CSS will be Tailwind-specific
Benefits
- No new functional logic, simply add styles to class attributes
- Rapid prototyping since Tailwind provides all the styling already
- Consistent and maintainable
- No overhead of additional CSS files
- Minified build size by only generating used classes
- Tailwind already attempts to normalise the experience between browsers through its base styles
Configuration
-
Optional tailwind.config.js at the root to apply customisations
-
To generate a template: npx tailwindcss init
/** @type {import('tailwindcss').Config} */ module.exports = { content: ["./src/**/*.{html,js}"], theme: { extend: {}, }, plugins: [], }
Generating classes
-
content specifies the location of source files to search for Tailwind class names so it can dynamically generate styles
-
Not limited to only searching the class attribute, you can toggle classes with JavaScript
<p class="py-2 text-gray-600" Hello everyone /> // Below is the list of strings that Tailwind will consider when scanning this file // p, class, py-2, text-gray-600, Hello, everyone
const element = document.getElementById('p') element.classList.toggle('hidden')
-
When scanning files, Tailwind does not parse or execute code
-
Full class name must exist somewhere within the source file, it does not resolve partial strings
// Wrong <div class="text-{{ error ? 'red' : 'green' }}-600"> // Correct <div class="{{ error ? 'text-red-600' : 'text-green-600' }}">
<p> It will find the class text-red-600 even in the content section. </p>
-
Referencing the previous code snippet, text-red-600 is not used in the context of styling but it will still be generated
-
blocklist property in the configuration can prevent these types of styles from generating
<p> Do you want a container? </p> <p> I might collapse from exhaustion. </p>
module.exports = { content: ["./src/**/*.{html,js}"], blocklist: ['container', 'collapse'] }
Prefix option
-
prefix: Add a custom prefix to Tailwind's generated utility classes
-
ONLY added to Tailwind classes
-
Useful for separating CSS systems and custom CSS from Tailwind
// tailwind.config.js module.exports = { prefix: 'tw-', ... }
// index.html <h1 class="tw-text-blue-500 hover:tw-text-red-500" > </h1>
Themes option
-
themes: Extend / configure overridable values for pre-defined utility classes
theme: { screens: { 'sm': '700px', // Default: 640px }, colors: { white: '#fff', gray: { 100: '#f7fafc', // ... 900: '#1a202c' } } }
-
Here's a scenario where a project's colour palette can be configured for easy application using the extend property
theme: { extend: { colors: { 'custom-1': '#ADD8E6', 'custom-2': '#A2A8D3', 'custom-3': '#38598B', 'custom-4': '#113F67' } } }
Plugin option
-
Register new styles using JavaScript
-
plugin is imported from tailwindcss/plugin and provides an object containing helper functions to your callback function (custom plugin)
// tailwind.config.js import plugin from 'tailwindcss/plugin' module.exports = { plugins: [ plugin((objectWithUtils) => {}) ] ... }
Static utilities example
plugins: [
plugin(function ({ addUtilities }) {
const newUtilities = {
'.text-shadow': {
textShadow: '2px 2px rgba(0, 0, 0, 0.5)',
},
'.text-shadow-lg': {
textShadow: '4px 4px rgba(0, 0, 0, 0.7)',
},
};
addUtilities(newUtilities);
})
]
Dynamic utilities example
-
Generated classes:
- margin-1: 0.25 rem
- margin-2: 0.5 rem
- margin-3: 0.75 rem
- margin-4: 1 rem
theme: { extend: { spacing: { '1': '0.25rem', '2': '0.5rem', '3': '0.75rem', '4': '1rem', }, }, }
plugins: [ plugin(function({ matchUtilities, theme }) { matchUtilities( { 'margin': (value) => ({ margin: value, }), }, { values: theme('spacing'), } ) }), ]
Directives
-
base: Resets styles to ensure consistency between browser engines
-
components: Inject Tailwind component classes or components registered by plugins
-
utilities: Adds utility classes for styling your HTML
-
layer: Tells Tailwind which "layer" a set of custom styles belong to (base, components, utilities)
-
apply: Allows you to inline Tailwind utility classes into custom CSS
@tailwind base; @tailwind components; @tailwind utilities; @layer components { .custom-btn-blue { @apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded; } }
Generate final stylesheet
- Input file contains directives and custom CSS
- Output file contains generated CSS styles used by your project
- npx tailwindcss -i [input.css] -o [output.css]
Tools
VSCode extension
- Tailwind CSS IntelliSense
- Adds quality of life features: autocomplete, syntax highlighting, linting
Prettier plugin
-
npm install prettier prettier-plugin-tailwindcss
-
Sorts class tags into related groups
-
Headwind is an alternative vscode extension that performs the same thing
// .prettierrc { "plugins": ["prettier-plugin-tailwindcss"] }
-
Example of classes being sorted on save
<button class="text-white px-4 sm:px-8 py-2 sm:py-3 bg-sky-700 hover:bg-sky-800" > </button>
<button class="bg-sky-700 px-4 py-2 text-white hover:bg-sky-800 sm:px-8 sm:py-3" > </button>