CSS At-Rules for Theming with Tailwind
Understanding CSS At-Rules for Theming
CSS at-rules (prefixed with
@) provide powerful mechanisms for organizing and applying themes. Here's how to leverage them effectively:@layer
The
@layer directive is part of the CSS Cascade Layers specification, which allows you to control the cascade and specificity of your styles: css
@layer structure, theme, components, mode;
@import "./structure.css" layer(structure);
@import "./lossless-theme.css" layer(theme);
@import "./components.css" layer(components);
@import "./mode.css" layer(mode); This defines the order of precedence for your CSS layers, with later layers having higher priority. Styles in the
mode layer will override conflicting styles in the theme layer, which will override styles in the structure layer.@apply
In Tailwind, the
@apply directive lets you extract common patterns into custom CSS classes by applying Tailwind's utility classes directly in your CSS: css
.btn-primary {
@apply bg-primary text-white py-2 px-4 rounded hover:bg-primary-dark;
} This is useful for creating reusable components while still leveraging Tailwind's utility classes.
theme() Function
When Tailwind refers to
@theme, they're typically talking about accessing theme values from your tailwind.config.js file within CSS using the theme() function: css
.custom-element {
color: theme('colors.primary');
padding: theme('spacing.4');
} This allows you to access your Tailwind theme configuration directly in your CSS, ensuring consistency between your utility classes and custom CSS.
Best Practices for Using These Features
1. Organize with @layer
css
/* Define your layers */
@layer base, components, utilities, themes;
/* Base styles */
@layer base {
:root {
--sys-color-primary: #4a6cf7;
}
}
/* Component styles */
@layer components {
.btn {
@apply py-2 px-4 rounded;
background-color: var(--sys-color-primary);
}
}
/* Theme overrides */
@layer themes {
[data-theme="client1"] {
--sys-color-primary: #e63946;
}
} 2. Use theme() for consistency
css
.custom-element {
/* Access your Tailwind theme values */
margin: theme('spacing.4');
color: theme('colors.primary');
/* For responsive designs */
@screen md {
margin: theme('spacing.6');
}
} 3. Combine with CSS variables for theming
css
@layer base {
:root {
--color-primary: theme('colors.blue.500');
}
[data-theme="dark"] {
--color-primary: theme('colors.blue.300');
}
}
@layer components {
.btn-primary {
@apply bg-primary text-white;
/* You can also use CSS variables directly */
border-color: var(--color-primary);
}
} 4. Extend your Tailwind config for custom themes
javascript
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: 'var(--sys-color-primary)',
// You can also use opacity modifiers with CSS variables
'primary-50': 'color-mix(in srgb, var(--sys-color-primary) 50%, transparent)',
},
},
},
} Integration with Existing Theme System
When working with our existing theme system, these at-rules can be integrated with our current approach of using CSS variables for theming. The key is to maintain a consistent naming convention and layer structure across all projects.
Our current system uses a layered approach with structure, theme, components, and mode layers, which aligns perfectly with the cascade layers specification. By leveraging
@layer and the theme() function, we can enhance our existing system while maintaining backward compatibility.