CSS style management
HTML class attribute
The standard HTML class
attribute can be added to components to set class names.
templ button(text string) {
<button class="button is-primary">{ text }</button>
}
<button class="button is-primary">
Click me
</button>
Class expression
To use a variable as the name of a CSS class, use a CSS expression.
package main
templ button(text string, className string) {
<button class={ className }>{ text }</button>
}
The class expression can take an array of values.
package main
templ button(text string, className string) {
<button class={ "button", className }>{ text }</button>
}
Dynamic class names
Toggle addition of CSS classes to an element based on a boolean value by passing:
- A
templ.KV
value containing the name of the class to add to the element, and a boolean that determines whether the class is added to the attribute at render time.templ.KV("is-primary", true)
templ.KV("hover:red", true)
- A map of string class names to a boolean that determines if the class is added to the class attribute value at render time:
map[string]bool
map[CSSClass]bool
package main
css red() {
background-color: #ff0000;
}
templ button(text string, isPrimary bool) {
<button class={ "button", templ.KV("is-primary", isPrimary), templ.KV(red(), isPrimary) }>{ text }</button>
}
package main
import (
"context"
"os"
)
func main() {
button("Click me", false).Render(context.Background(), os.Stdout)
}
<button class="button">
Click me
</button>
CSS elements
The standard <style>
element can be used within a template.
<style>
element contents are rendered to the output without any changes.
templ page() {
<style type="text/css">
p {
font-family: sans-serif;
}
.button {
background-color: black;
foreground-color: white;
}
</style>
<p>
Paragraph contents.
</p>
}
<style type="text/css">
p {
font-family: sans-serif;
}
.button {
background-color: black;
foreground-color: white;
}
</style>
<p>
Paragraph contents.
</p>
If you want to make sure that the CSS element is only output once, even if you use a template many times, use a CSS expression.
CSS components
When developing a component library, it may not be desirable to require that specific CSS classes are present when the HTML is rendered.
There may be CSS class name clashes, or developers may forget to include the required CSS.
To include CSS within a component library, use a CSS component.
CSS components can also be conditionally rendered.
package main
var red = "#ff0000"
var blue = "#0000ff"
css primaryClassName() {
background-color: #ffffff;
color: { red };
}
css className() {
background-color: #ffffff;
color: { blue };
}
templ button(text string, isPrimary bool) {
<button class={ "button", className(), templ.KV(primaryClassName(), isPrimary) }>{ text }</button>
}
<style type="text/css">
.className_f179{background-color:#ffffff;color:#ff0000;}
</style>
<button class="button className_f179">
Click me
</button>
The CSS class is given a unique name the first time it is used, and only rendered once per HTTP request to save bandwidth.
The class name is autogenerated, don't rely on it being consistent.
CSS component arguments
CSS components can also require function arguments.
package main
css loading(percent int) {
width: { fmt.Sprintf("%d%%", percent) };
}
templ index() {
<div class={ loading(50) }></div>
<div class={ loading(100) }></div>
}
<style type="text/css">
.loading_a3cc{width:50%;}
</style>
<div class="loading_a3cc"></div>
<style type="text/css">
.loading_9ccc{width:100%;}
</style>
<div class="loading_9ccc"></div>
CSS Sanitization
To prevent CSS injection attacks, templ automatically sanitizes dynamic CSS property names and values using the templ.SanitizeCSS
function. Internally, this uses a lightweight fork of Google's safehtml
package to sanitize the value.
If a property name or value has been sanitized, it will be replaced with zTemplUnsafeCSSPropertyName
for property names, or zTemplUnsafeCSSPropertyValue
for property values.
To bypass this sanitization, e.g. for URL values of background-image
, you can mark the value as safe using the templ.SafeCSSProperty
type.
css windVaneRotation(degrees float64) {
transform: { templ.SafeCSSProperty(fmt.Sprintf("rotate(%ddeg)", int(math.Round(degrees)))) };
}
templ Rotate(degrees float64) {
<div class={ windVaneRotation(degrees) }>Rotate</div>
}
CSS Middleware
The use of CSS templates means that <style>
elements containing the CSS are rendered on each HTTP request.
To save bandwidth, templ can provide a global stylesheet that includes the output of CSS templates instead of including <style>
tags in each HTTP request.
To provide a global stylesheet, use templ's CSS middleware, and register templ classes on application startup.
The middleware adds a HTTP route to the web server (/styles/templ.css
by default) that renders the text/css
classes that would otherwise be added to <style>
tags when components are rendered.
For example, to stop the className
CSS class from being added to the output, the HTTP middleware can be used.
c1 := className()
handler := NewCSSMiddleware(httpRoutes, c1)
http.ListenAndServe(":8000", handler)
Don't forget to add a <link rel="stylesheet" href="/styles/templ.css">
to your HTML to include the generated CSS class names!