Understanding and unlocking the power of tailwind.config.js file
The tailwind.config.js file customizes and extends Tailwind CSS, unlocking its full potential for tailored styling.
Introduction.
Tailwind CSS is a popular utility-first CSS framework that enables developers to build custom designs without leaving their HTML. One of the key features that make Tailwind CSS highly flexible and customizable is its configuration file, tailwind.config.js. This file allows developers to tailor the framework to their specific needs, extending or modifying the default settings provided by Tailwind.
What is the Tailwind Config File?
The tailwind.config.js file is a JavaScript file where you can define custom configurations for your Tailwind setup. By default, Tailwind CSS comes with a set of pre-defined utility classes. However, the configuration file allows you to configure your base style according to your project requirements.
Table of contents
- Extend the Default Theme: Add new values or override existing values for colors, spacing, fonts, and more.
- Add Plugins: Extend Tailwind's functionality with plugins.
Pre-requisite
Have tailwind installed. To know how to install tailwind in a basic html project check tailwind documents or check how to install in your preferred framework.
So now let's start with the configuration.
Extend the Default Theme
One of the most powerful features of the Tailwind config file is the ability to extend the default theme. This allows you to add custom colors, spacing, fonts, and other design tokens.
You can use functions for top-level theme keys and access colors, breakpoints by destructuring. It can be used to apply default values mentioned in your tailwind config file.
module.exports = {
theme: {
extend: {
backgroundImage: ({ colors, breakpoints }) => ({
"green-gradient-border": `linear-gradient(135deg,#00ff85 0%,#004a4a 23.5%,#251743 39%,#251743 48.5%,#251743 53.5%,#004a4a 78%,#00ff85 100%)`,
}),
boxShadow: () => ({
"green-shadow": "0px 0px 12px 0px #00ff8566",
}),
colors: {
background: "#ffffff",
foreground: "#070708",
primary: {
DEFAULT: "#18181b",
foreground: "#fafafa",
},
secondary: {
DEFAULT: "#f2f2f3",
foreground: "#18181b",
},
},
fontSize: {
xs: ".75rem",
sm: ".875rem",
base: "1rem",
lg: "1.125rem",
xl: "1.25rem",
"2xl": "1.5rem",
"3xl": "1.875rem",
"4xl": "2.25rem",
"5xl": "3rem",
},
spacing: {
72: "18rem",
84: "21rem",
96: "24rem",
},
fontFamily: {
sans: ["Inter", "sans-serif"],
serif: ["Merriweather", "serif"],
},
},
},
}Add plugins
Tailwind allows you to extend its functionality with plugins. You can add community plugins or write your own.
Plugins can be added to your project by installing them via npm, then adding them to your `tailwind.config.js` file:
Some of the official plugins developed by tailwind team are:
`@tailwindcss/typography``@tailwindcss/forms``@tailwindcss/aspect-ratio``@tailwindcss/container-queries`
To create custom plugin import `plugin` from `tailwindcss/plugin` then inside the plugin array you can call the `plugin` function.
Listed below are all the functions provided by the plugin function.
- Use
`addUtilities()`, to create new static utility styles. - Use
`matchUtilities()`, to create new dynamic utility styles. - Use
`addComponents()`, to create new static component styles. - Use
`matchComponents()`, to create new dynamic component styles. - Use
`addVariant()`, to create new dynamic variant styles. - Use
`matchVariant()`, to create new dynamic variant styles. - Use
`addBase()`, to add base styles globally, it allows you to add or override these base styles. - Use
`theme()`, for looking up values in the theme configuration. - Use
`config()`, to access custom config values. - Use
`e()`, to escape special characters in class names. - Use
`corePlugins()`, to check the status of core plugins and add custom utilities accordingly.
`addUtilities()`
- With
`addUtilities()`we can create custom utility classes. These utility classes can be added directly to your HTML to apply specific styles. This method allows you to extend Tailwind's default set of utilities with your own custom ones.
const plugin = require("tailwindcss/plugin")
module.exports = {
// ...
plugins: [
require("tailwindcss-animate"),
require("@tailwindcss/typography"),
plugin(function ({ addUtilities }) {
addUtilities({
".clip-polygon": {
clipPath: "polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)",
},
".clip-circle": {
clipPath: "circle(50%)",
},
})
}),
],
}`matchUtilities()`
- With
`matchUtilities()`we can create dynamic utility styles. Since there is no clamp class in tailwind you can create it with a custom plugin. With this you can either give default tailwind sizes like`sm`,`md`... etc or direct values like`16px`or`1rem`. EG:`clamp-[base-10vw-6rem]`.
const plugin = require("tailwindcss/plugin")
module.exports = {
// ...
plugins: [
plugin(function ({ matchUtilities, theme }) {
matchUtilities({
clamp(value) {
const sizes = theme("fontSize")
const split = value
.split("-")
.map((v) => (sizes[v] ? sizes[v]["0"] : v))
return {
fontSize: `clamp(${split[0]}, ${split[1]}, ${split[2]})`,
}
},
})
}),
],
}`addComponents()`
- With
`addComponents()`we can create static component styles. It's very helpful to create style which are re-used every where like Buttons, Badges, Cards, Alerts etc.
const plugin = require("tailwindcss/plugin")
module.exports = {
// ...
plugins: [
plugin(function ({ addComponents, theme }) {
addComponents({
".btn": {
padding: "10px 15px",
width: "max-content",
borderRadius: "8px",
},
".btn-outline": {
border: "1px solid grey",
color: theme("colors.white"),
},
".btn-destructive": {
background: theme("colors.red.500"),
color: theme("colors.white"),
"&:hover": {
backgroundColor: theme("colors.red.700"),
},
},
})
}),
],
}`matchComponents()`
- With
`matchComponents()`we can create dynamic component styles. This allows you to define a set of rules that generate classes dynamically, similar to how Tailwind generates utility classes.
const plugin = require("tailwindcss/plugin")
module.exports = {
// ...
plugins: [
plugin(function ({ matchComponents, theme, e }) {
const colors = theme("colors")
const flattenedColors = Object.fromEntries(
Object.entries(colors).flatMap(([key, value]) =>
typeof value === "string"
? [[key, value]]
: Object.entries(value).map(([shade, color]) => [
`${key}-${shade}`,
color,
])
)
)
matchComponents(
{
scrollbar: (color) => ({
overflow: "scroll",
"scrollbar-width": "thin", // Customize as needed
"scrollbar-color": `${color} transparent`, // Thumb color and track color
}),
},
{
values: flattenedColors,
className: (name) => e(`scrollbar-${name}`),
}
)
}),
],
}`addVariant()`
- With
`addVariant()`we can create custom variants. Variants allow you to conditionally apply utility classes based on different states or contexts, such as hover, focus, active, etc.
const plugin = require("tailwindcss/plugin")
module.exports = {
// ...
plugins: [
plugin(({ addVariant, e }) => {
addVariant("children", ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `.${e(`children${separator}${className}`)} > *`
})
})
}),
],
}`matchVariant()`
- With
`matchVariant()`we can create custom dynamic variants. Adding on the above example we can make the child selector dynamic with`matchVariant()`. We can use other pseudo classes with the child selector eg:- children-[p:hover]:text-red-500.
const plugin = require("tailwindcss/plugin")
module.exports = {
// ...
plugins: [
plugin(({ matchVariant }) => {
matchVariant("children", (value) => {
return `& > ${value}`
})
}),
],
}`addBase()`
- Use
`addBase()`to add base styles globally, it allows you to add or override these base styles directly from your Tailwind CSS configuration.
const plugin = require("tailwindcss/plugin")
module.exports = {
// ...
plugins: [
plugin(({ addBase }) => {
addBase({
h1: { fontSize: "2.25rem", fontWeight: "700" },
h2: { fontSize: "1.5rem", fontWeight: "700" },
p: { fontSize: "1rem", lineHeight: "1.5" },
})
}),
],
}`theme()`
- Use
`theme()`to access values defined in your theme configuration within your plugins or custom styles. This function is useful for ensuring consistency and leveraging the predefined design tokens (colors, spacing, fonts, etc.) that you've set up in your tailwind.config.js file.
const plugin = require("tailwindcss/plugin")
module.exports = {
// ...
plugins: [
plugin(({ addBase, theme }) => {
addBase({
h1: {
fontSize: theme("fontSize.4xl"),
fontWeight: theme("fontWeight.extra-bold"),
},
h2: {
fontSize: theme("fontWeight.extra-bold"),
fontWeight: theme("fontWeight.extra-bold"),
},
p: {
fontSize: theme("fontSize.base"),
lineHeight: theme("lineHeight.5"),
},
})
}),
],
}`config()`
- Use
`config()`to access values from the Tailwind configuration file`tailwind.config.js`within custom plugins. This function allows you to retrieve configuration options, including theme settings, variants, plugins, and other custom settings that you have defined.
const plugin = require("tailwindcss/plugin")
module.exports = {
theme: {
extend: {
colors: {
brand: {
light: "#3ab7bf",
DEFAULT: "#2697a1",
dark: "#1e7d84",
},
},
},
},
plugins: [
plugin(({ addUtilities, config }) => {
const brandColors = config("theme.colors.brand")
addUtilities({
".text-brand": {
color: brandColors.DEFAULT,
},
".bg-brand-light": {
backgroundColor: brandColors.light,
},
".bg-brand-dark": {
backgroundColor: brandColors.dark,
},
})
}),
],
}While both `config()` and `theme()` in Tailwind CSS are used to access values
defined in your `tailwind.config.js` file, they serve slightly different
purposes and have different scopes of access.
`theme()` | `config()` |
|---|---|
Purpose: The `theme()` function is specifically designed to access values within the theme section of your Tailwind configuration. | Purpose: The `config()` function is designed to access any value within the `tailwind.config.js` file, not just those within the `theme` section. |
Scope: Limited to the theme section of `tailwind.config.js`. | Scope: Can access the entire Tailwind configuration file, including custom configurations, variants, plugins, and other settings. |
| Usage: Primarily used to access design tokens like colors, spacing, fonts, etc., that are defined within the theme object. | Usage: Used to retrieve configuration values that may not be strictly related to the theme, such as custom settings, variant configurations, or other top-level configuration options. |
| Context: Commonly used within custom utilities and variants to ensure consistent design tokens. | Context: Useful when you need to access more than just the theme values, such as custom plugin settings or variant definitions. |
`e()`
- Use
`e()`to escape special characters in class names. This function ensures that class names are valid CSS selectors, which is crucial when dynamically generating class names that might include characters with special meanings in CSS, such as :, /, or .
Eg: To create a custom utility class that includes a slash (/), such as w/3 for a width of 33.333%. You need to escape the slash to make it a valid CSS class name.
const plugin = require("tailwindcss/plugin")
module.exports = {
plugins: [
plugin(function ({ addUtilities, e }) {
addUtilities({
[`.${e("w/3")}`]: {
width: "33.333%",
},
})
}),
],
}The generated classname looks like
.w\/3 {
width: 33.333%;
}`corePlugins()`
- Use
`corePlugins()`to create a custom configuration for core plugins. Customize and extend core plugin functionality based on specific conditions.
const plugin = require("tailwindcss/plugin")
module.exports = {
corePlugins: {
float: false, // Can be disabled
borderRadius: true, // Default is true
},
plugins: [
plugin(function ({ corePlugins, addUtilities }) {
if (corePlugins("borderRadius")) {
addUtilities({
".rounded-custom": {
borderRadius: "12px",
},
})
}
}),
],
}We can modularize the plugins to different files and then import it into main
`tailwind.config.js` file to make it more readable.
Modularize
function customPlugin({ addComponents, theme }) {
addComponents({
".btn": {
padding: theme("spacing.4"),
borderRadius: theme("borderRadius.md"),
backgroundColor: theme("colors.primary"),
color: theme("colors.white"),
"&:hover": {
backgroundColor: theme("colors.secondary"),
},
},
})
}
module.exports = customPluginconst customPlugin = require("./plugins/customPlugin")
module.exports = {
theme: {
extend: {
colors: {
primary: "#004cff",
secondary: "#ffe600",
},
},
},
plugins: [customPlugin],
}Conclusion
The tailwind.config.js file is a powerful tool for creating a comprehensive design system. By customizing the theme, creating custom utilities, adding variants, and leveraging plugins, you can build a scalable and maintainable design system that ensures consistency across your projects. Mastering this file will not only improve your workflow but also enhance the quality and coherence of your designs.