This example demonstrates how cssgen handles various CSS selector types. It shows which selectors generate Go constants and which are documented in other ways (like pseudo-states in comments).
File: input/advanced.css
A comprehensive CSS file showing:
- Simple class selectors
- Pseudo-classes (:hover, :focus, :active)
- Pseudo-elements (::before, ::after)
- Combinators (descendant, child, sibling)
- Attribute selectors
- Complex combinations
- Media queries
- Special cases
CSS:
.button { padding: 0.5rem 1rem; }Generated:
const Button = "button"Result: Direct 1:1 mapping.
CSS:
.link { color: #3b82f6; }
.link:hover { color: #2563eb; }
.link:focus { outline: 2px solid #3b82f6; }Generated:
// **Visual:**
// - color: `#3b82f6`
// - text-decoration: `none`
//
// **Interactions:**
// - `:hover`: Changes color to `#2563eb`, text-decoration to `underline`
// - `:focus`: Changes outline to `2px solid #3b82f6`, outline-offset to `2px`
const Link = "link"Result: Base class extracted, pseudo-states documented in comments.
CSS:
.quote { padding-left: 1.5rem; }
.quote::before { content: '"'; }
.quote::after { content: '"'; }Generated:
// **Layout:**
// - padding-left: `1.5rem`
// - position: `relative`
//
// Note: Uses ::before and ::after pseudo-elements
const Quote = "quote"Result: Base class extracted, pseudo-elements mentioned.
CSS:
.card .card__header .card__title {
font-size: 1.25rem;
}Generated:
const Card = "card"
const CardHeader = "card__header"
const CardTitle = "card__title"Result: All class parts extracted separately. Combinator relationship preserved in BEM naming.
CSS:
.menu > .menu__item {
margin-bottom: 0.5rem;
}Generated:
const Menu = "menu"
const MenuItem = "menu__item"Result: Both classes extracted independently.
CSS:
.label + .input {
margin-top: 0.25rem;
}Generated:
const Label = "label"
const Input = "input"Result: Both classes extracted separately.
CSS:
.responsive { display: block; }
@media (min-width: 768px) {
.responsive { display: flex; }
}Generated:
// **Layout:**
// - display: `block`
//
// Note: Has responsive styles in media queries
const Responsive = "responsive"Result: Class extracted once, media query noted.
CSS:
[data-theme="dark"] { background-color: #111827; }
input[type="text"] { border: 1px solid #d1d5db; }Result: No constants generated. Attribute selectors are not class-based.
CSS:
body { margin: 0; }
h1 { font-size: 2rem; }Result: No constants. cssgen only extracts class selectors.
CSS:
#header { height: 4rem; }Result: Not extracted. IDs are discouraged in favor of classes.
CSS:
* { box-sizing: border-box; }Result: No constant. Universal selector has no specific name.
File: output/styles.gen.go
cssgen extracts class selectors and documents their context:
- Simple classes → Direct constants
- Pseudo-classes → Documented in "Interactions" section
- Pseudo-elements → Noted in comments
- Combined selectors → Class parts extracted individually
- Media queries → Noted as "responsive styles"
- BEM patterns → Relationships documented in "Base" and "Context"
- Class-Only Extraction - cssgen only generates constants for class selectors
- Pseudo-State Documentation - :hover, :focus, etc. documented in generated comments
- Combinator Handling - Class parts from complex selectors extracted separately
- Context Preservation - BEM relationships and usage hints included
- Focused Scope - No constants for elements, IDs, or attributes
templ Button() {
<button class={ ui.Button }>Click</button>
}templ Link(href string) {
// :hover and :focus handled automatically by CSS
<a class={ ui.Link } href={ href }>Link</a>
}templ Card() {
<div class={ ui.Card }>
<div class={ ui.CardHeader }>
<h3 class={ ui.CardTitle }>Title</h3>
</div>
</div>
}templ Dropdown(open bool) {
<div class={ ui.Dropdown, templ.KV("is-open", open) }>
<div class={ ui.DropdownMenu }>Items</div>
</div>
}
// Note: State classes like "is-open" may not have constants
// if they're only used in combinators// Classes starting with _ are marked as internal
// They generate constants but are documented as internal-use
templ Component() {
<div class={ ui.Internal }>Hidden utility</div>
}- ✅
.classname- Simple class selector - ✅
.class1, .class2- Multiple selectors - ✅
.parent .child- Descendant (both classes) - ✅
.parent > .child- Child combinator (both classes) - ✅
.prev + .next- Adjacent sibling (both classes)
- 📝
:hover,:focus,:active- Pseudo-classes - 📝
::before,::after- Pseudo-elements - 📝
@mediaqueries - Responsive styles
- ❌
[attribute]- Attribute selectors - ❌
element- Element selectors - ❌
#id- ID selectors - ❌
*- Universal selector
- Use Classes - Prefer class selectors for all styled elements
- Avoid IDs - Use classes instead of IDs for styling
- BEM Naming - Use BEM for component relationships
- State Classes - Use explicit state classes (
.is-open,.is-active) - Trust CSS - Pseudo-states work automatically, no special handling needed
# 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/06-complex-selectors/input \
--output-dir ./examples/06-complex-selectors/output \
--package ui --include "**/*.css"- 01-basic - Return to simple patterns
- 02-bem-methodology - Deep dive into BEM
- examples/README.md - Overview of all examples