This example demonstrates modern CSS @layer directive usage and how cssgen handles it. CSS cascade layers provide explicit control over the cascade, allowing you to organize styles by purpose and control specificity.
Files:
input/base.css-@layer base- Resets and foundational stylesinput/components.css-@layer components- UI component stylesinput/utilities.css-@layer utilities- Utility classesinput/theme.css- CSS custom properties (design tokens)
CSS Cascade Layers (@layer) allow explicit ordering of CSS by purpose, not source order:
@layer base {
.btn { /* base button styles */ }
}
@layer utilities {
.hidden { display: none !important; }
}Layer Priority (lowest to highest):
@layer base- Resets, defaults@layer components- Component styles@layer utilities- Utility overrides- Unlayered styles - Highest priority
Benefits:
- Predictable Cascade - Explicit specificity control
- No !important Needed - Layers handle priority
- Better Organization - Styles grouped by purpose
- Safer Overrides - Utilities always win
.reset- Box model reset.text-base- Default typography.container- Content wrapper.link- Default link styles
.btn-primary- Primary button.card,.card__title,.card__content- Card component.input,.input--error- Form input
- Spacing:
.mt-*,.mb-* - Display:
.hidden,.flex,.grid - Typography:
.text-center,.font-bold - Colors:
.text-gray-*,.text-blue-* - Width:
.w-full,.w-auto
- Color palette (
--color-*) - Spacing scale (
--spacing-*) - Border radius (
--radius-*) - Shadows (
--shadow-*) - Typography (
--font-*,--text-*) - Theme classes using custom properties
File: output/styles.gen.go
cssgen generates constants with @layer annotations in comments:
// @layer base
//
// **Layout:**
// - margin-left: `auto`
// - margin-right: `auto`
// - max-width: `72rem`
// ...
const Container = "container"
// @layer components
//
// **Visual:**
// - background-color: `#3b82f6`
// - color: `white`
// ...
const BtnPrimary = "btn-primary"
// @layer utilities
//
// **Layout:**
// - display: `none`
const Hidden = "hidden"The layer annotation helps developers understand cascade priority when combining classes.
- Layer Annotations - cssgen preserves
@layerinformation in generated comments - Cascade Control - Layers provide predictable style priority
- Design Tokens - CSS custom properties work alongside typed constants
- Organization - Layers help organize large stylesheets by purpose
- Modern CSS - cssgen supports contemporary CSS features
// Utility layer always overrides component layer
templ HiddenCard() {
// The .hidden utility will override .card display property
<div class={ ui.Card, ui.Hidden }>
Never shown
</div>
}
templ VisibleCard() {
<div class={ ui.Card }>
<h3 class={ ui.CardTitle }>Title</h3>
<p class={ ui.CardContent }>Content</p>
</div>
}templ Page() {
<div class={ ui.Container }>
<a class={ ui.Link } href="/home">Home</a>
<button class={ ui.BtnPrimary }>Click me</button>
</div>
}templ Form() {
<form>
<input class={ ui.Input, ui.WFull, ui.Mb4 } type="text"/>
<input class={ ui.Input, ui.InputError, ui.WFull, ui.Mb4 } type="email"/>
<button class={ ui.BtnPrimary, ui.WFull }>Submit</button>
</form>
}templ ThemedSection() {
<section class={ ui.ThemePrimary }>
<h2 class={ ui.TextCenter, ui.FontBold }>Primary Theme</h2>
<p class={ ui.TextCenter }>Uses var(--color-primary)</p>
</section>
}- Base Layer - Normalize, resets, element defaults
- Component Layer - Reusable UI components
- Utility Layer - Single-purpose helpers (highest priority)
- Unlayered - Third-party CSS, overrides
- Layers make specificity less important
- Utility layer classes always override component layer
- No need for
!importantwhen using layers properly
- Existing projects can adopt layers incrementally
- Start with utilities in
@layer utilities - Gradually move components to
@layer components - Keep unlayered styles until migrated
While cssgen generates constants for class names, CSS custom properties (variables) complement this approach:
Class constants → Type-safe class references
CSS variables → Dynamic theming, runtime changes
// Type-safe classes + CSS variables = powerful combination
templ DynamicCard(primary bool) {
<div class={
ui.Card,
templ.KV(ui.ThemePrimary, primary),
templ.KV(ui.ThemeSurface, !primary),
}>
Content adapts to theme via CSS variables
</div>
}# Using config file (from this directory — reads .cssgen.yaml automatically)
cssgen
# Using CLI flags (from this directory)
cssgen generate --source ./input --output-dir ./output --package ui --include "**/*.css"
# From the project root
cssgen generate --source ./examples/04-css-layers/input \
--output-dir ./examples/04-css-layers/output \
--package ui --include "**/*.css"- 05-utility-first - Comprehensive utility class patterns
- 06-complex-selectors - Advanced CSS selector handling