attr()
Baseline Widely available *
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
* Some parts of this feature may have varying levels of support.
Note:
The attr()
function can be used with any CSS property, but support for properties other than content
is experimental.
The attr()
CSS function is used to retrieve the value of an attribute of the selected element and use it in a property value, similar to how the var()
function substitutes a custom property value. It can also be used with pseudo-elements, in which case the attribute's value on the pseudo-element's originating element is returned.
Try it
blockquote {
margin: 1em 0;
}
blockquote::after {
display: block;
content: " (source: " attr(cite) ") ";
color: hotpink;
}
Mozilla makes browsers, apps, code and tools that put people before profit.
Google believes in an open, accessible, private, and secure web.
Syntax
/* Basic usage */
attr(data-count)
attr(href)
/* With type */
attr(data-width px)
attr(data-size rem)
attr(data-name raw-string)
attr(id type())
attr(data-count type())
attr(data-size type( | ))
/* With fallback */
attr(data-count type(), 0)
attr(data-width px, inherit)
attr(data-something, "default")
Parameters
The attr()
function's syntax is as follows:
attr(? , ?)
The parameters are:
-
The attribute name whose value should be retrieved from the selected HTML element(s).
-
Specifies how the attribute value is parsed into a CSS value. This can be the
raw-string
keyword, atype()
function, or a CSS dimension unit (specified using an
identifier). When omitted, it defaults toraw-string
.-
The
raw-string
keyword causes the attribute's literal value to be treated as the value of a CSS string, with no CSS parsing performed (including CSS escapes, whitespace removal, comments, etc). The
is only used if the attribute is omitted; specifying an empty value doesn't trigger the fallback.cssattr(data-name raw-string, "stranger")
Note: This keyword was originally named and supported in Chromium browsers as
string
. Both keywords will be supported briefly, for backwards compatibility purposes. -
The
type()
function takes a
as its argument that specifies what data type to parse the value into. The
can be
,
,
,
,
,
,
,
,
,
,
,,
, or a combination thereof.cssattr(id type(
), none) attr(data-count type( ), 0) To accept multiple types, list all allowed
es in thetype()
function, separated by a|
.cssattr(data-size type(
| ), 0px) Note: For security reasons
is not allowed as a
.To accept any data type, use
*
as the type. This still triggers CSS parsing but with no requirements placed on it beyond that it parses validly and substitutes the result of that parsing directly as tokens, rather than as a
value.cssattr(data-content type(*))
-
The
identifier specifies the unit a numeric value should have (if any). It can be the%
character (percentage) or a CSS distance unit such aspx
,rem
,deg
,s
, etc.cssattr(data-size rem) attr(data-width px, inherit) attr(data-rotation deg)
-
-
The value to be used if the specified attribute is missing or contains an invalid value.
Return value
The return value of attr()
is the value of the HTML attribute whose name is
parsed as the given
or parsed as a CSS string.
When an
is set, attr()
will try to parse the attribute into that specified
and return it. If the attribute cannot be parsed into the given
, the
will be returned instead. When no
is set, the attribute will be parsed into a CSS string.
If no
is set, the return value will default to an empty string when no
is set or the guaranteed-invalid value when an
is set.
Description
Limitations and security
The attr()
function can reference attributes that were never intended by the page author to be used for styling and might contain sensitive information (for example, a security token used by scripts on the page). In general, this is fine, but it can become a security threat when used in URLs. Therefore, you can't use attr()
to dynamically construct URLs.
help
span[data-icon] {
background-image: url(attr(data-icon));
}
Values that use attr()
get marked as attr()
-tainted. Using an attr()
-tainted value as or in a
makes a declaration become "invalid at computed value time" or IACVT for short.
Backwards compatibility
Generally speaking, the modern attr()
syntax is backward-compatible because the old way of using it — without specifying an
— behaves the same as before. Having attr(data-attr)
in your code is the same as writing attr(data-attr type(
or the simpler attr(data-attr string))
.
However, there are two edge cases where the modern attr()
syntax behaves differently from the old syntax.
In the following snippet, browsers that don't support the modern attr()
syntax will discard the second declaration because they cannot parse it. The result in those browsers is "Hello World"
.
div::before {
content: attr(text) " World";
}
div::before {
content: attr(text) 1px;
}
In browsers with support for the modern syntax, the output will be … nothing. Those browsers will successfully parse the second declaration, but because it is invalid content for the content
property, the declaration becomes "invalid at computed value time" or IACVT for short.
To prevent this kind of situation, feature detection is recommended.
A second edge case is the following:
#parent {
--x: attr(data-attr);
}
#child::before {
content: var(--x);
}
Browsers without support for modern syntax display the text "foo"
. In browsers with modern attr()
support there is no output.
This is because attr()
— similar to custom properties that use the var()
function — get substituted at computed value time. With the modern behavior, --x
first tries to read the data-attr
attribute from the #parent
element, which results in an empty string because there is no such attribute on #parent
. That empty string then gets inherited by the #child
element, resulting in a content: ;
declaration being set.
To prevent this sort of situation, don't pass inherited attr()
values onto children unless you explicitly want to.
Feature detection
You can feature detect support for modern attr()
syntax using the @supports
at-rule. In the test, try to assign advanced attr()
to a (non-custom) CSS property.
For example:
@supports (x: attr(x type(*))) {
/* Browser has modern attr() support */
}
@supports not (x: attr(x type(*))) {
/* Browser does not have modern attr() support */
}
We can perform the same check in JavaScript with CSS.supports()
:
if (CSS.supports("x: attr(x type(*))")) {
/* Browser has modern attr() support */
}
if (!CSS.supports("x: attr(x type(*))")) {
/* Browser does not have modern attr() support */
}
Formal syntax
Examples
content property
In this example, we prepend the value of the data-foo
data-*
global attribute to the contents of the element.
HTML
world
CSS
[data-foo]::before {
content: attr(data-foo) " ";
}
Result
Using a fallback value
Experimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.
In this example, we append the value of data-browser
data-*
global attribute to the element. If the
data-browser
attribute is missing from the element, we append the fallback value of "Unknown".
HTML
My favorite browser is:
Your favorite browser is:
CSS
p::after {
content: " " attr(data-browser, "Unknown");
color: tomato;
}
Result
color value
Experimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.
In this example, we set the CSS value of Experimental: This is an experimental technology In this example the Experimental: This is an experimental technology In this example, the values for the The resulting values for The HTML contains four cards with different The cards are laid out in a flex container: On each card, the When the To animate each card to its new position, View Transitions are used. This is done by wrapping the background-color
to the value of the data-background
data-*
global attribute assigned to the HTML
CSS
.background {
background-color: red;
}
.background[data-background] {
background-color: attr(data-background type(
Result
Using dimension units
Check the Browser compatibility table carefully before using this in production.data-rotation
attribute is parsed into a deg
unit, which specifies the element's rotation.HTML
CSS
div {
width: fit-content;
transform-origin: 50% 50%;
rotate: attr(data-rotation deg, 1.5deg);
}
Result
Parsing
attr()
values as
s
Check the Browser compatibility table carefully before using this in production.view-transition-name
property are derived from the id
attribute of the element. The attribute gets parsed into a
, which is what view-transition-name
accepts as a value.view-transition-name
are card-1
, card-2
, card-3
, etc.HTML
id
attributes and a "Shuffle cards" , which shuffles the cards.
CSS
.cards {
display: flex;
flex-direction: row;
gap: 1em;
padding: 1em;
}
attr()
function gets the id
attribute and parses it into a
, which is used as the value for the view-transition-name
property. When there is no id
set on a card, the fallback value none
is used instead..card {
view-transition-name: attr(id type(
JavaScript
is pressed the cards are shuffled. This is done by randomizing the order of an array containing references to all the cards and then updating the
order
property of each card to its new array index position.order
update in a call to document.startViewTransition
.const shuffle = (array) => {
for (let i = array.length - 1; i >= 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
};
document.querySelector("button").addEventListener("click", (e) => {
const $cards = Array.from(document.querySelectorAll(".card"));
shuffle($cards);
document.startViewTransition(() => {
$cards.forEach(($card, i) => {
$card.style.setProperty("order", i);
});
});
});
Result
Specifications
Specification CSS Values and Units Module Level 5
# attr-notationBrowser compatibility
See also