12 KiB
Attribute, class, and style bindings
The template syntax provides specialized one-way bindings for scenarios less well-suited to property binding.
See the for a working example containing the code snippets in this guide.
Attribute binding
Set the value of an attribute directly with an attribute binding. This is the only exception to the rule that a binding sets a target property and the only binding that creates and sets an attribute.
Usually, setting an element property with a property binding is preferable to setting the attribute with a string. However, sometimes there is no element property to bind, so attribute binding is the solution.
Consider the ARIA and SVG. They are purely attributes, don't correspond to element properties, and don't set element properties. In these cases, there are no property targets to bind to.
Attribute binding syntax resembles property binding, but
instead of an element property between brackets, start with the prefix attr
,
followed by a dot (.
), and the name of the attribute.
You then set the attribute value, using an expression that resolves to a string,
or remove the attribute when the expression resolves to null
.
One of the primary use cases for attribute binding is to set ARIA attributes, as in this example:
{@a colspan}
colspan
and colSpan
Notice the difference between the colspan
attribute and the colSpan
property.
If you wrote something like this:
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>You'd get this error:
Template parse errors: Can't bind to 'colspan' since it isn't a known native propertyAs the message says, the <td>
element does not have a colspan
property. This is true
because colspan
is an attribute—colSpan
, with a capital S
, is the
corresponding property. Interpolation and property binding can set only properties, not attributes.
Instead, you'd use property binding and write it like this:
{@a class-binding}
Class binding
Here's how to set the class
attribute without a binding in plain HTML:
<!-- standard class attribute setting -->
<div class="foo bar">Some text</div>
You can also add and remove CSS class names from an element's class
attribute with a class binding.
To create a single class binding, start with the prefix class
followed by a dot (.
) and the name of the CSS class (for example, [class.foo]="hasFoo"
).
Angular adds the class when the bound expression is truthy, and it removes the class when the expression is falsy (with the exception of undefined
, see styling delegation).
To create a binding to multiple classes, use a generic [class]
binding without the dot (for example, [class]="classExpr"
).
The expression can be a space-delimited string of class names, or you can format it as an object with class names as the keys and truthy/falsy expressions as the values.
With object format, Angular will add a class only if its associated value is truthy.
It's important to note that with any object-like expression (object
, Array
, Map
, Set
, etc), the identity of the object must change for the class list to be updated.
Updating the property without changing object identity will have no effect.
If there are multiple bindings to the same class name, conflicts are resolved using styling precedence.
Binding Type | Syntax | Input Type | Example Input Values |
---|---|---|---|
Single class binding | [class.foo]="hasFoo" |
boolean | undefined | null |
true , false |
Multi-class binding | [class]="classExpr" |
string |
"my-class-1 my-class-2 my-class-3" |
{[key: string]: boolean | undefined | null} |
{foo: true, bar: false} |
||
Array <string > |
['foo', 'bar'] |
The NgClass directive can be used as an alternative to direct [class]
bindings.
However, using the above class binding syntax without NgClass
is preferred because due to improvements in class binding in Angular, NgClass
no longer provides significant value, and might eventually be removed in the future.
Style binding
Here's how to set the style
attribute without a binding in plain HTML:
<!-- standard style attribute setting -->
<div style="color: blue">Some text</div>
You can also set styles dynamically with a style binding.
To create a single style binding, start with the prefix style
followed by a dot (.
) and the name of the CSS style property (for example, [style.width]="width"
).
The property will be set to the value of the bound expression, which is normally a string.
Optionally, you can add a unit extension like em
or %
, which requires a number type.
Note that a style property name can be written in either
dash-case, as shown above, or
camelCase, such as fontSize
.
If there are multiple styles you'd like to toggle, you can bind to the [style]
property directly without the dot (for example, [style]="styleExpr"
).
The expression attached to the [style]
binding is most often a string list of styles like "width: 100px; height: 100px;"
.
You can also format the expression as an object with style names as the keys and style values as the values, like {width: '100px', height: '100px'}
.
It's important to note that with any object-like expression (object
, Array
, Map
, Set
, etc), the identity of the object must change for the class list to be updated.
Updating the property without changing object identity will have no effect.
If there are multiple bindings to the same style property, conflicts are resolved using styling precedence rules.
Binding Type | Syntax | Input Type | Example Input Values |
---|---|---|---|
Single style binding | [style.width]="width" |
string | undefined | null |
"100px" |
Single style binding with units | [style.width.px]="width" |
number | undefined | null |
100 |
Multi-style binding | [style]="styleExpr" |
string |
"width: 100px; height: 100px" |
{[key: string]: string | undefined | null} |
{width: '100px', height: '100px'} |
||
Array <string > |
['width', '100px'] |
The NgStyle directive can be used as an alternative to direct [style]
bindings.
However, using the above style binding syntax without NgStyle
is preferred because due to improvements in style binding in Angular, NgStyle
no longer provides significant value, and might eventually be removed in the future.
{@a styling-precedence}
Styling Precedence
A single HTML element can have its CSS class list and style values bound to multiple sources (for example, host bindings from multiple directives).
When there are multiple bindings to the same class name or style property, Angular uses a set of precedence rules to resolve conflicts and determine which classes or styles are ultimately applied to the element.
Styling precedence (highest to lowest)
- Template bindings
- Property binding (for example,
<div [class.foo]="hasFoo">
or<div [style.color]="color">
) - Map binding (for example,
<div [class]="classExpr">
or<div [style]="styleExpr">
) - Static value (for example,
<div class="foo">
or<div style="color: blue">
)
- Property binding (for example,
- Directive host bindings
- Property binding (for example,
host: {'[class.foo]': 'hasFoo'}
orhost: {'[style.color]': 'color'}
) - Map binding (for example,
host: {'[class]': 'classExpr'}
orhost: {'[style]': 'styleExpr'}
) - Static value (for example,
host: {'class': 'foo'}
orhost: {'style': 'color: blue'}
)
- Property binding (for example,
- Component host bindings
- Property binding (for example,
host: {'[class.foo]': 'hasFoo'}
orhost: {'[style.color]': 'color'}
) - Map binding (for example,
host: {'[class]': 'classExpr'}
orhost: {'[style]': 'styleExpr'}
) - Static value (for example,
host: {'class': 'foo'}
orhost: {'style': 'color: blue'}
)
- Property binding (for example,
The more specific a class or style binding is, the higher its precedence.
A binding to a specific class (for example, [class.foo]
) will take precedence over a generic [class]
binding, and a binding to a specific style (for example, [style.bar]
) will take precedence over a generic [style]
binding.
Specificity rules also apply when it comes to bindings that originate from different sources. It's possible for an element to have bindings in the template where it's declared, from host bindings on matched directives, and from host bindings on matched components.
Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence.
Directive host bindings are considered less specific because directives can be used in multiple locations, so they have a lower precedence than template bindings.
Directives often augment component behavior, so host bindings from components have the lowest precedence.
In addition, bindings take precedence over static attributes.
In the following case, class
and [class]
have similar specificity, but the [class]
binding will take precedence because it is dynamic.
{@a styling-delegation}
Delegating to styles with lower precedence
It is possible for higher precedence styles to "delegate" to lower precedence styles using undefined
values.
Whereas setting a style property to null
ensures the style is removed, setting it to undefined
will cause Angular to fall back to the next-highest precedence binding to that style.
For example, consider the following template:
Imagine that the dirWithHostBinding
directive and the comp-with-host-binding
component both have a [style.width]
host binding.
In that case, if dirWithHostBinding
sets its binding to undefined
, the width
property will fall back to the value of the comp-with-host-binding
host binding.
However, if dirWithHostBinding
sets its binding to null
, the width
property will be removed entirely.