11# CSS style management
22
3- ## HTML class attribute
3+ ## HTML class and style attributes
44
5- The standard HTML ` class ` attribute can be added to components to set class names .
5+ The standard HTML ` class ` and ` style ` attributes can be added to components. Note the use of standard quotes to denote a static value .
66
77``` templ
88templ button(text string) {
9- <button class="button is-primary">{ text }</button>
9+ <button class="button is-primary" style="background-color: red" >{ text }</button>
1010}
1111```
1212
1313``` html title="Output"
14- <button class =" button is-primary" >
14+ <button class =" button is-primary" style = " background-color : red " >
1515 Click me
1616</button >
1717```
1818
19- ## Class expression
19+ ## Style attribute
20+
21+ To use a variable in the style attribute, use braces to denote the Go expression.
22+
23+ ``` templ
24+ templ button(style, text string) {
25+ <button style={ style }>{ text }</button>
26+ }
27+ ```
28+
29+ You can pass multiple values to the ` style ` attribute. The results are all added to the output.
30+
31+ ``` templ
32+ templ button(style1, style2 string, text string) {
33+ <button style={ style1, style2 }>{ text }</button>
34+ }
35+ ```
36+
37+ The style attribute supports use of the following types:
38+
39+ * ` string ` - A string containing CSS properties, e.g. ` background-color: red ` .
40+ * ` templ.SafeCSS ` - A value containing CSS properties and values that will not be sanitized, e.g. ` background-color: red; text-decoration: underline `
41+ * ` map[string]string ` - A map of string keys to string values, e.g. ` map[string]string{"color": "red"} `
42+ * ` map[string]templ.SafeCSSProperty ` - A map of string keys to values, where the values will not be sanitized.
43+ * ` templ.KeyValue[string, string] ` - A single CSS key/value.
44+ * ` templ.KeyValue[string, templ.SafeCSSProperty ` - A CSS key/value, but the value will not be sanitized.
45+ * ` templ.KeyValue[string, bool] ` - A map where the CSS in the key is only included in the output if the boolean value is true.
46+ * ` templ.KeyValue[templ.SafeCSS, bool] ` - A map where the CSS in the key is only included if the boolean value is true.
47+
48+ Finally, a function value that returns any of the above types can be used.
49+
50+ Go syntax allows you to pass a single function that returns a value and an error.
51+
52+ ``` templ
53+ templ Page(userType string) {
54+ <div style={ getStyle(userType) }>Styled</div>
55+ }
56+
57+ func getStyle(userType string) (string, error) {
58+ //TODO: Look up in something that might error.
59+ return "background-color: red", errors.New("failed")
60+ }
61+ ```
62+
63+ Or multiple functions and values that return a single type.
64+
65+ ``` templ
66+ templ Page(userType string) {
67+ <div style={ getStyle(userType), "color: blue" }>Styled</div>
68+ }
69+
70+ func getStyle(userType string) (string) {
71+ return "background-color: red"
72+ }
73+ ```
74+
75+ ### Style attribute examples
76+
77+ #### Maps
78+
79+ Maps are useful when styles need to be dynamically computed based on component state or external inputs.
80+
81+ ``` templ
82+ func getProgressStyle(percent int) map[string]string {
83+ return map[string]string{
84+ "width": fmt.Sprintf("%d%%", percent),
85+ "transition": "width 0.3s ease",
86+ }
87+ }
88+
89+ templ ProgressBar(percent int) {
90+ <div style={ getProgressStyle(percent) } class="progress-bar">
91+ <div class="progress-fill"></div>
92+ </div>
93+ }
94+ ```
95+
96+ ``` html title="Output (percent=75)"
97+ <div style =" transition :width 0.3s ease ;width :75% ;" class =" progress-bar" >
98+ <div class =" progress-fill" ></div >
99+ </div >
100+ ```
101+
102+ #### KeyValue pattern
103+
104+ The ` templ.KV ` helper provides conditional style application in a more compact syntax.
105+
106+ ``` templ
107+ templ TextInput(value string, hasError bool) {
108+ <input
109+ type="text"
110+ value={ value }
111+ style={
112+ templ.KV("border-color: #ff3860", hasError),
113+ templ.KV("background-color: #fff5f7", hasError),
114+ "padding: 0.5em 1em;",
115+ }
116+ >
117+ }
118+ ```
119+
120+ ``` html title="Output (hasError=true)"
121+ <input
122+ type =" text"
123+ value =" "
124+ style =" border-color : #ff3860 ; background-color : #fff5f7 ; padding : 0.5em 1em ;" >
125+ ```
126+
127+ #### Bypassing sanitization
128+
129+ By default, dynamic CSS values are sanitized to protect against dangerous CSS values that might introduce vulnerabilities into your application.
130+
131+ However, if you're sure, you can bypass sanitization by marking your content as safe with the ` templ.SafeCSS ` and ` templ.SafeCSSProperty ` types.
132+
133+ ``` templ
134+ func calculatePositionStyles(x, y int) templ.SafeCSS {
135+ return templ.SafeCSS(fmt.Sprintf(
136+ "transform: translate(%dpx, %dpx);",
137+ x*2, // Example calculation
138+ y*2,
139+ ))
140+ }
141+
142+ templ DraggableElement(x, y int) {
143+ <div style={ calculatePositionStyles(x, y) }>
144+ Drag me
145+ </div>
146+ }
147+ ```
148+
149+ ``` html title="Output (x=10, y=20)"
150+ <div style =" transform : translate (20px , 40px );" >
151+ Drag me
152+ </div >
153+ ```
154+
155+ ### Pattern use cases
156+
157+ | Pattern | Best For | Example Use Case |
158+ | ---------| ----------| ------------------|
159+ | ** Maps** | Dynamic style sets requiring multiple computed values | Progress indicators, theme switching |
160+ | ** KeyValue** | Conditional style toggling | Form validation, interactive states |
161+ | ** Functions** | Complex style generation | Animations, data visualizations |
162+ | ** Direct Strings** | Simple static styles | Basic formatting, utility classes |
163+
164+ ### Sanitization behaviour
165+
166+ By default, dynamic CSS values are sanitized to protect against dangerous CSS values that might introduce vulnerabilities into your application.
167+
168+ ``` templ
169+ templ UnsafeExample() {
170+ <div style={ "background-image: url('javascript:alert(1)')" }>
171+ Dangerous content
172+ </div>
173+ }
174+ ```
175+
176+ ``` html title="Output"
177+ <div style =" background-image :zTemplUnsafeCSSPropertyValue;" >
178+ Dangerous content
179+ </div >
180+ ```
181+
182+ These protections can be bypassed with the ` templ.SafeCSS ` and ` templ.SafeCSSProperty ` types.
183+
184+ ``` templ
185+ templ SafeEmbed() {
186+ <div style={ templ.SafeCSS("background-image: url(/safe.png);") }>
187+ Trusted content
188+ </div>
189+ }
190+ ```
191+
192+ ``` html title="Output"
193+ <div style =" background-image : url (/safe.png );" >
194+ Trusted content
195+ </div >
196+ ```
197+
198+ ::: note
199+ HTML attribute escaping is not bypassed, so ` < ` , ` > ` , ` & ` and quotes will always appear as HTML entities (` < ` etc.) in attributes - this is good practice, and doesn't affect how browsers use the CSS.
200+ :::
201+
202+ ### Error Handling
203+
204+ Invalid values are automatically sanitized:
205+
206+ ``` templ
207+ templ InvalidButton() {
208+ <button style={
209+ map[string]string{
210+ "": "invalid-property",
211+ "color": "</style>",
212+ }
213+ }>Click me</button>
214+ }
215+ ```
216+
217+ ``` html title="Output"
218+ <button style =" zTemplUnsafeCSSPropertyName :zTemplUnsafeCSSPropertyValue;color :zTemplUnsafeCSSPropertyValue;" >
219+ Click me
220+ </button >
221+ ```
222+
223+ Go's type system doesn't support union types, so it's not possible to limit the inputs to the style attribute to just the supported types.
224+
225+ As such, the attribute takes ` any ` , and executes type checks at runtime. Any invalid types will produce the CSS value ` zTemplUnsupportedStyleAttributeValue:Invalid; ` .
226+
227+ ## Class attributes
20228
21229To use a variable as the name of a CSS class, use a CSS expression.
22230
@@ -42,6 +250,7 @@ templ button(text string, className string) {
42250
43251Toggle addition of CSS classes to an element based on a boolean value by passing:
44252
253+ * A ` string ` containing the name of a class to apply.
45254* 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.
46255 * ` templ.KV("is-primary", true) `
47256 * ` templ.KV("hover:red", true) `
0 commit comments