Chapter 4: Advanced Features
Haiyue
13min
Chapter 4: Advanced Features
Learning Objectives
- Master the usage and best practices of the @apply directive
- Learn to create custom utilities and extract components
- Understand JIT mode and on-demand generation mechanism
- Master new features and improvements in Tailwind CSS 4.1
@apply Directive
Basic Usage
The @apply directive allows you to apply Tailwind utilities in custom CSS:
/* styles.css */
.btn-primary {
@apply bg-blue-500 text-white font-semibold py-2 px-4 rounded-lg;
@apply hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500;
@apply transition-colors duration-200;
}
.card {
@apply bg-white rounded-lg shadow-md p-6;
}
.form-input {
@apply block w-full px-3 py-2 border border-gray-300 rounded-md;
@apply focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500;
}
<!-- Using custom component classes -->
<button class="btn-primary">Primary Button</button>
<div class="card">Card content</div>
<input type="text" class="form-input" placeholder="Enter...">
Best Practices
/* Recommended: Component-level extraction */
.btn {
@apply font-semibold py-2 px-4 rounded-lg transition-colors duration-200;
@apply focus:outline-none focus:ring-2 focus:ring-offset-2;
}
.btn-primary {
@apply btn bg-blue-500 text-white;
@apply hover:bg-blue-600 focus:ring-blue-500;
}
.btn-secondary {
@apply btn bg-gray-200 text-gray-900;
@apply hover:bg-gray-300 focus:ring-gray-500;
}
/* Avoid: Over-extracting basic utilities */
.text-large {
@apply text-lg; /* Not recommended, using text-lg directly is better */
}
Conditional Application
/* Using @apply for complex states */
.nav-link {
@apply block px-3 py-2 text-gray-700 font-medium;
@apply hover:text-blue-600 hover:bg-blue-50;
@apply transition-all duration-200;
}
.nav-link.active {
@apply text-blue-600 bg-blue-50 border-r-2 border-blue-600;
}
/* Responsive @apply */
.responsive-card {
@apply p-4 bg-white rounded-lg shadow;
}
@screen md {
.responsive-card {
@apply p-6 shadow-lg;
}
}
Custom Utilities
Adding Custom Utilities
// tailwind.config.js
module.exports = {
theme: {
extend: {
spacing: {
'18': '4.5rem',
'88': '22rem',
},
fontSize: {
'xxs': '0.625rem',
},
colors: {
'brand': {
50: '#eff6ff',
500: '#3b82f6',
900: '#1e3a8a',
}
}
}
},
plugins: [
// Add custom utility plugin
function({ addUtilities }) {
const newUtilities = {
'.text-shadow': {
textShadow: '2px 2px 4px rgba(0,0,0,0.1)',
},
'.text-shadow-lg': {
textShadow: '4px 4px 8px rgba(0,0,0,0.2)',
},
'.backface-hidden': {
'backface-visibility': 'hidden',
},
'.perspective': {
perspective: '1000px',
}
}
addUtilities(newUtilities, ['responsive', 'hover'])
}
]
}
Adding Components with Plugins
// tailwind.config.js
module.exports = {
plugins: [
function({ addComponents, theme }) {
const components = {
'.btn': {
padding: `${theme('spacing.2')} ${theme('spacing.4')}`,
borderRadius: theme('borderRadius.md'),
fontWeight: theme('fontWeight.semibold'),
transition: 'all 0.2s',
'&:focus': {
outline: 'none',
boxShadow: `0 0 0 2px ${theme('colors.blue.500')}`,
}
},
'.btn-primary': {
backgroundColor: theme('colors.blue.500'),
color: theme('colors.white'),
'&:hover': {
backgroundColor: theme('colors.blue.600'),
}
},
'.btn-secondary': {
backgroundColor: theme('colors.gray.200'),
color: theme('colors.gray.900'),
'&:hover': {
backgroundColor: theme('colors.gray.300'),
}
}
}
addComponents(components)
}
]
}
Custom Variants
// tailwind.config.js
module.exports = {
plugins: [
function({ addVariant }) {
// Add custom pseudo-class variants
addVariant('not-first', '&:not(:first-child)')
addVariant('not-last', '&:not(:last-child)')
addVariant('hocus', ['&:hover', '&:focus'])
// Add data attribute variants
addVariant('data-active', '&[data-active="true"]')
addVariant('data-loading', '&[data-loading="true"]')
}
]
}
<!-- Using custom variants -->
<div class="not-first:mt-4 not-last:mb-4">
<button class="hocus:bg-blue-600 data-active:bg-green-500" data-active="true">
Button
</button>
</div>
JIT Mode Deep Dive
What is JIT Mode
JIT (Just-In-Time) mode is Tailwind CSS’s on-demand compilation mode that scans your code in real-time and generates only the CSS that’s actually used.
JIT Mode Advantages:
- Smaller files during development
- Support for arbitrary values
- Faster build speeds
- Better hot-reload experience
Enabling JIT Mode
// tailwind.config.js
module.exports = {
mode: 'jit', // Enabled by default in Tailwind CSS 3.0+
purge: [
'./src/**/*.{html,js,ts,jsx,tsx,vue}',
'./public/index.html',
],
// Other configuration...
}
Arbitrary Value Support
JIT mode supports arbitrary values in square brackets:
<!-- Arbitrary color values -->
<div class="bg-[#1da1f2]">Twitter blue</div>
<div class="text-[rgb(255,0,0)]">Red text</div>
<!-- Arbitrary size values -->
<div class="w-[300px]">Fixed width 300px</div>
<div class="h-[50vh]">50% viewport height</div>
<div class="top-[117px]">Precise positioning</div>
<!-- Arbitrary spacing values -->
<div class="p-[1.7rem]">Custom padding</div>
<div class="m-[10px]">10px margin</div>
<!-- CSS variables -->
<div class="bg-[var(--main-color)]">Using CSS variable</div>
<!-- Complex values -->
<div class="bg-[url('/api/avatar')]">Dynamic background image</div>
<div class="before:content-['★']">Pseudo-element content</div>
Dynamic Class Name Generation
<!-- Dynamic colors -->
<div class="bg-[{{ userColor }}]">User-defined color</div>
<!-- Dynamic sizes -->
<div class="w-[{{ width }}px]">Dynamic width</div>
<!-- Responsive arbitrary values -->
<div class="lg:w-[calc(100%-2rem)]">Calculated width</div>
JIT Mode Considerations
JIT Mode Considerations
- String Concatenation: Avoid dynamically generating class name strings
- Whitelist: Ensure
contentconfiguration correctly scans all files - Cache: May need to restart during development to apply configuration changes
- Arbitrary Value Syntax: Must use correct CSS syntax
// Not recommended: Dynamic string concatenation
const color = 'blue'
className = `bg-${color}-500` // JIT may not detect this
// Recommended: Complete class names or safelist
className = 'bg-blue-500'
// Or add to safelist in tailwind.config.js
Tailwind CSS 4.1 New Features
Improved TypeScript Support
// Type-safe configuration
import type { Config } from 'tailwindcss'
const config: Config = {
content: [
'./src/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
500: '#3b82f6',
950: '#172554',
}
}
},
},
plugins: [],
}
export default config
New Utilities
<!-- New container query support -->
<div class="@container">
<div class="@lg:text-xl">Container query responsive</div>
</div>
<!-- Improved grid utilities -->
<div class="grid grid-cols-subgrid">
<div class="col-span-2">Subgrid support</div>
</div>
<!-- New logical properties -->
<div class="ms-4 me-4">Logical margins (RTL support)</div>
<div class="ps-4 pe-4">Logical padding</div>
Performance Improvements
// New optimization options
module.exports = {
future: {
hoverOnlyWhenSupported: true, // Only enable hover on devices that support it
},
experimental: {
optimizeUniversalDefaults: true, // Optimize defaults
}
}
New Plugin API
// Using new plugin API
const plugin = require('tailwindcss/plugin')
module.exports = {
plugins: [
plugin(function({ addUtilities, matchUtilities, theme }) {
// New matchUtilities supports dynamic values
matchUtilities(
{
'grid-area': (value) => ({
'grid-area': value,
}),
},
{ values: theme('gridArea') }
)
}),
],
}
Practical Applications
Building a Design System
/* components.css */
@layer components {
/* Button component system */
.btn {
@apply inline-flex items-center justify-center font-medium transition-all duration-200;
@apply focus:outline-none focus:ring-2 focus:ring-offset-2;
@apply disabled:opacity-50 disabled:cursor-not-allowed;
}
.btn-sm {
@apply text-sm px-3 py-1.5 rounded-md;
}
.btn-md {
@apply text-base px-4 py-2 rounded-lg;
}
.btn-lg {
@apply text-lg px-6 py-3 rounded-xl;
}
.btn-primary {
@apply btn bg-blue-600 text-white border-blue-600;
@apply hover:bg-blue-700 hover:border-blue-700;
@apply focus:ring-blue-500;
}
.btn-outline {
@apply btn bg-transparent border-2;
@apply text-blue-600 border-blue-600;
@apply hover:bg-blue-600 hover:text-white;
@apply focus:ring-blue-500;
}
/* Form components */
.form-group {
@apply space-y-2;
}
.form-label {
@apply block text-sm font-medium text-gray-700;
}
.form-input {
@apply block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm;
@apply focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500;
@apply disabled:bg-gray-50 disabled:text-gray-500;
}
.form-error {
@apply text-sm text-red-600;
}
/* Card components */
.card {
@apply bg-white rounded-lg border border-gray-200 shadow-sm;
}
.card-header {
@apply px-6 py-4 border-b border-gray-200;
}
.card-body {
@apply p-6;
}
.card-footer {
@apply px-6 py-4 bg-gray-50 border-t border-gray-200 rounded-b-lg;
}
}
Using the Design System
<!-- Form example -->
<form class="max-w-md mx-auto space-y-6">
<div class="form-group">
<label for="email" class="form-label">Email Address</label>
<input
type="email"
id="email"
class="form-input"
placeholder="Enter email"
>
<p class="form-error hidden">Please enter a valid email address</p>
</div>
<div class="form-group">
<label for="password" class="form-label">Password</label>
<input
type="password"
id="password"
class="form-input"
placeholder="Enter password"
>
</div>
<div class="flex space-x-4">
<button type="submit" class="btn btn-primary btn-md flex-1">
Login
</button>
<button type="button" class="btn btn-outline btn-md">
Register
</button>
</div>
</form>
<!-- Card example -->
<div class="card max-w-md mx-auto">
<div class="card-header">
<h3 class="text-lg font-semibold text-gray-900">User Information</h3>
</div>
<div class="card-body">
<p class="text-gray-600">This is the main content area of the card...</p>
</div>
<div class="card-footer">
<div class="flex justify-end space-x-3">
<button class="btn btn-outline btn-sm">Cancel</button>
<button class="btn btn-primary btn-sm">Confirm</button>
</div>
</div>
</div>
Summary
Through this chapter, you should have mastered:
- @apply Directive: Reusing Tailwind utilities in custom CSS
- Custom Utilities: Extending Tailwind’s functionality for specific needs
- JIT Mode: On-demand compilation and arbitrary value support
- Design System: Building a consistent component library with Tailwind
- New Features: Improvements and optimizations in Tailwind CSS 4.1
These advanced features enable you to better organize code, improve development efficiency, and build maintainable design systems.