CSS
S-expression CSS with nesting, themes, and media queries.
(import (sigil css))Basic Rules
The css macro creates CSS rules. Properties are written as (property-name value) where the property name is captured literally (not evaluated).
(css->string
(css ".button"
(background "#007bff")
(color "white")
(padding "0.5rem 1rem")
(border-radius "4px")))Output:
.button {
background: #007bff;
color: white;
padding: 0.5rem 1rem;
border-radius: 4px;
}Nested Selectors
Use & to create nested rules, similar to Sass/SCSS. The suffix is appended directly to the parent selector.
(css->string
(css ".card"
(padding "1rem")
(border "1px solid #ddd")
(& ":hover"
(box-shadow "0 2px 8px rgba(0,0,0,0.15)"))
(& " .title"
(font-weight "bold")
(font-size "1.25rem"))))Output:
.card {
padding: 1rem;
border: 1px solid #ddd;
}
.card:hover {
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
.card .title {
font-weight: bold;
font-size: 1.25rem;
}Nested css forms create child selectors (space-separated):
(css ".nav"
(display "flex")
(css ".item"
(padding "0.5rem")))css->string
Render any number of CSS fragments (rules, variables, media queries, keyframes) into a single CSS string.
(css->string
(css-vars (--primary "#007bff"))
(css ".btn" (background "var(--primary)"))
(css ".btn-lg" (padding "1rem 2rem")))CSS Variables
Define CSS custom properties with css-vars. Creates a :root block.
(css->string
(css-vars
(--bg "#0a0a0a")
(--fg "#e0e0e0")
(--accent "#f0c040"))
(css "body"
(background "var(--bg)")
(color "var(--fg)")))Media Queries
Wrap rules in a @media block with css-media.
(css->string
(css ".sidebar" (width "250px"))
(css-media "(max-width: 768px)"
(css ".sidebar" (display "none"))
(css ".content" (width "100%"))))Keyframes
Define CSS animations with css-keyframes. Step names are symbols (from, to, or percentage symbols).
(css->string
(css-keyframes "fade-in"
(from (opacity "0"))
(to (opacity "1")))
(css ".fade" (animation "fade-in 0.3s ease-in")))Themes
Create reusable theme definitions and convert them to CSS custom properties.
(define dark-theme
(make-theme
'(bg "#0a0a0a")
'(fg "#e0e0e0")
'(accent "#f0c040")))
;; Look up a theme value
(theme-ref dark-theme 'bg) ; => "#0a0a0a"
;; Reference as CSS variable
(theme-var 'bg) ; => "var(--bg)"
;; Convert to :root CSS variables
(css->string
(theme->css-vars dark-theme)
(css "body"
(background (theme-var 'bg))
(color (theme-var 'fg))))Unit and Color Helpers
Helpers for common CSS units and color functions.
| Helper | Example | Result |
|---|---|---|
px | (px 16) | "16px" |
em | (em 1.5) | "1.5em" |
rem | (rem 2) | "2rem" |
% | (% 50) | "50%" |
rgb | (rgb 255 128 0) | "rgb(255, 128, 0)" |
rgba | (rgba 0 0 0 0.5) | "rgba(0, 0, 0, 0.5)" |
hsl | (hsl 200 50 60) | "hsl(200, 50%, 60%)" |
important | (important "red") | "red !important" |
(css->string
(css ".box"
(width (% 100))
(padding (rem 1))
(font-size (px 14))
(color (important "red"))))Additional Utilities
css-import
Add @import rules for external stylesheets or fonts.
(css->string
(css-import "https://fonts.googleapis.com/css2?family=Inter")
(css "body" (font-family "Inter, sans-serif")))css-raw
Insert raw CSS strings for edge cases not covered by the DSL.
(css->string
(css-raw "/* Browser-specific hack */")
(css ".main" (display "grid")))css-combine
Group CSS fragments into a list for modular organization.
(define button-styles
(css-combine
(css ".btn" (padding "0.5rem 1rem") (border "none"))
(css ".btn-primary" (background "blue") (color "white"))
(css ".btn-danger" (background "red") (color "white"))))
(css->string button-styles)Common Patterns
Component Styles
(import (sigil css))
(define card-styles
(css-combine
(css ".card"
(border "1px solid #e0e0e0")
(border-radius "8px")
(padding "1.5rem")
(& ":hover"
(box-shadow "0 4px 12px rgba(0,0,0,0.1)"))
(& " .card-title"
(font-size "1.25rem")
(margin-bottom "0.5rem"))
(& " .card-body"
(color "#666")))))Responsive Design
(css->string
(css ".grid"
(display "grid")
(grid-template-columns "repeat(3, 1fr)")
(gap (rem 1)))
(css-media "(max-width: 768px)"
(css ".grid"
(grid-template-columns "1fr"))))Themed Application
(import (sigil css)
(sigil sxml))
(define theme
(make-theme
'(bg "#ffffff")
'(fg "#1a1a1a")
'(primary "#007bff")))
(define app-css
(css->string
(theme->css-vars theme)
(css "body"
(background (theme-var 'bg))
(color (theme-var 'fg)))
(css ".btn-primary"
(background (theme-var 'primary))
(color "white"))))
(sxml->html `(style (*raw* ,app-css)))