attributes – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Tue, 15 Feb 2022 18:17:46 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 attributes – CSS-Tricks https://css-tricks.com 32 32 45537868 A Complete Guide to Data Attributes https://css-tricks.com/a-complete-guide-to-data-attributes/ https://css-tricks.com/a-complete-guide-to-data-attributes/#comments Tue, 18 Feb 2020 00:07:24 +0000 https://css-tricks.com/?p=302917 Everything you ever wanted to know about data attributes in HTML, CSS, and JavaScript.


A Complete Guide to Data Attributes originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>

Introduction

HTML elements can have attributes on them that are used for anything from accessibility information to stylistic control.

<!-- We can use the `class` for styling in CSS, and we've also make this into a landmark region -->
<div class="names" role="region" aria-label="Names"></div>

What is discouraged is making up your own attributes, or repurposing existing attributes for unrelated functionality.

<!-- `highlight` is not an HTML attribute -->
<div highlight="true"></div>

<!-- `large` is not a valid value of `width` -->
<div width="large">

There are a variety of reasons this is bad. Your HTML becomes invalid, which may not have any actual negative consequences, but robs you of that warm fuzzy valid HTML feeling. The most compelling reason is that HTML is a living language and just because attributes and values that don’t do anything today doesn’t mean they never will.

Good news though: you can make up your own attributes. You just need to prefix them with data-* and then you’re free to do what you please!

Syntax

It can be awfully handy to be able to make up your own HTML attributes and put your own information inside them. Fortunately, you can! That’s exactly what data attributes are. They are like this:

<!-- They don't need a value -->
<div data-foo></div>

<!-- ...but they can have a value -->
<div data-size="large"></div>

<!-- You're in HTML here, so careful to escape code if you need to do something like put more HTML inside -->
<li data-prefix="Careful with HTML in here."><li>

<!-- You can keep dashing if you like -->
<aside data-some-long-attribute-name><aside>

Data attributes are often referred to as data-* attributes, as they are always formatted like that. The word data, then a dash -, then other text you can make up.

Can you use the data attribute alone?

<div data=""></div>

It’s probably not going to hurt anything, but you won’t get the JavaScript API we’ll cover later in this guide. You’re essentially making up an attribute for yourself, which as I mentioned in the intro, is discouraged.

What not to do with data attributes

Store content that should be accessible. If the content should be seen or read on a page, don’t only put them in data attributes, but make sure that content is in the HTML content somewhere.

<!-- This isn't accessible content -->
<div data-name="Chris Coyier"></div>

<!-- If you need programmatic access to it but shouldn't be seen, there are other ways... -->
<div>
  <span class="visually-hidden">Chris Coyier</span>
</div>

Here’s more about hiding things.

Styling with data attributes

CSS can select HTML elements based on attributes and their values.

/* Select any element with this data attribute and value */
[data-size="large"] {
  padding: 2rem;
  font-size: 125%;
}

/* You can scope it to an element or class or anything else */
button[data-type="download"] { }
.card[data-pad="extra"] { }

This can be compelling. The predominant styling hooks in HTML/CSS are classes, and while classes are great (they have medium specificity and nice JavaScript methods via classList) an element either has it or it doesn’t (essentially on or off). With data-* attributes, you get that on/off ability plus the ability to select based on the value it has at the same specificity level.

/* Selects if the attribute is present at all */
[data-size] { }

/* Selects if the attribute has a particular value */
[data-state="open"],
[aria-expanded="true"] { }

/* "Starts with" selector, meaning this would match "3" or anything starting with 3, like "3.14" */
[data-version^="3"] { }

/* "Contains" meaning if the value has the string anywhere inside it */
[data-company*="google"] { }

The specificity of attribute selectors

It’s the exact same as a class. We often think of specificity as a four-part value:

inline style, IDs, classes/attributes, tags

So a single attribute selector alone is 0, 0, 1, 0. A selector like this:

div.card[data-foo="bar"] { }

…would be 0, 0, 2, 1. The 2 is because there is one class (.card) and one attribute ([data-foo="bar"]), and the 1 is because there is one tag (div).

Illustration of a CSS selector including a data attribute.

Attribute selectors have less specificity than an ID, more than an element/tag, and the same as a class.

Case-insensitive attribute values

In case you’re needing to correct for possible capitalization inconsistencies in your data attributes, the attribute selector has a case-insensitive variant for that.

/* Will match
<div data-state="open"></div>
<div data-state="Open"></div>
<div data-state="OPEN"></div>
<div data-state="oPeN"></div>
*/
[data-state="open" i] { }

It’s the little i within the bracketed selector.

Using data attributes visually

CSS allows you to yank out the data attribute value and display it if you need to.

/* <div data-emoji="✅"> */

[data-emoji]::before {
  content: attr(data-emoji); /* Returns '✅' */
  margin-right: 5px;
}

Example styling use-case

You could use data attributes to specify how many columns you want a grid container to have.

<div data-columns="2"></div>
<div data-columns="3"></div>
<div data-columns="4"></div>

Accessing data attributes in JavaScript

Like any other attribute, you can access the value with the generic method getAttribute.

let value = el.getAttribute("data-state");

// You can set the value as well.
// Returns data-state="collapsed"
el.setAttribute("data-state", "collapsed");

But data attributes have their own special API as well. Say you have an element with multiple data attributes (which is totally fine):

<span 
  data-info="123" 
  data-index="2" 
  data-prefix="Dr. "
  data-emoji-icon="🏌️‍♀️"
></span>

If you have a reference to that element, you can set and get the attributes like:

// Get
span.dataset.info; // 123
span.dataset.index; // 2

// Set
span.dataset.prefix = "Mr. ";
span.dataset.emojiIcon = "🎪";

Note the camelCase usage on the last line there. It automatically converts kebab-style attributes in HTML, like data-this-little-piggy, to camelCase style in JavaScript, like dataThisLittlePiggy.

This API is arguably not quite as nice as classList with the clear add, remove, toggle, and replace methods, but it’s better than nothing.

You have access to inline datasets as well:

<img src="spaceship.png"
  data-ship-id="324" data-shields="72%"
  onclick="pewpew(this.dataset.shipId)">
</img>

JSON data inside data attributes

<ul>
  <li data-person='
    {
      "name": "Chris Coyier",
      "job": "Web Person"
    }
  '></li>
</ul>

Hey, why not? It’s just a string and it’s possible to format it as valid JSON (mind the quotes and such). You can yank that data and parse it as needed.

const el = document.querySelector("li");

let json = el.dataset.person;
let data = JSON.parse(json);

console.log(data.name); // Chris Coyier
console.log(data.job); // Web Person

JavaScript use-cases

The concept is that you can use data attributes to put information in HTML that JavaScript may need access to do certain things.

A common one would have to do with database functionality. Say you have a “Like” button:

<button data-id="435432343">♡</button>

That button could have a click handler on it which performs an Ajax request to the server to increment the number of likes in a database on click. It knows which record to update because it gets it from the data attribute.

Specifications

Browser support

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
7611125.1

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
10810735.0-5.1

A Complete Guide to Data Attributes originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/a-complete-guide-to-data-attributes/feed/ 19 302917
What’s the Difference Between Width/Height in CSS and Width/Height HTML attributes? https://css-tricks.com/whats-the-difference-between-width-height-in-css-and-width-height-html-attributes/ https://css-tricks.com/whats-the-difference-between-width-height-in-css-and-width-height-html-attributes/#comments Fri, 24 Jan 2020 16:03:15 +0000 https://css-tricks.com/?p=301933 Some HTML elements accept width and height as attributes. Some do not. Those attributes are sometimes referred to as presentational attributes. The thing to know about them is that they are overridden by any other styling information whatsoever. That makes them ideal as a fallback.


What’s the Difference Between Width/Height in CSS and Width/Height HTML attributes? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Some HTML elements accept width and height as attributes. Some do not. For example:

<!-- valid, works, is a good idea -->
<img width="500" height="400" src="..." alt="...">
<iframe width="600" height="400" src="..."></iframe>
<svg width="20" height="20"></svg>

<!-- not valid, doesn't work, not a good idea -->
<div width="40" height="40"></div>
<span width="100" height="10"></span>

Those attributes are sometimes referred to as presentational attributes. The thing to know about them is that they are overridden by any other styling information whatsoever. That makes them ideal as a fallback.

So, if CSS loads and has a declaration like:

img {
  width: 400px;
}

…that is going to override the width="500" on the <img> tag above. Presentational attributes are the weakest kind of styling, so they are overridden by any CSS, even selectors with very low specificity.

What might be a smidge confusing is that presentational attributes seem like they would have high specificity. These inline styles, for instance, are very strong:

<img style="width: 500px; height: 400px;" src="..." alt="...">

Using an inline style (which works on any element, not a select few), we’ve moved from the weakest way to apply width and height to one of the strongest. Regular CSS will not override this, with a selector of any specificity strength. If we need to override them from CSS, we’ll need !important rules.

img {
  width: 400px !important;
}

To reiterate, presentational attributes on elements that accept them (e.g. <img>, <iframe>, <canvas>, <svg>, <video>) are a good idea. They are fallback sizing and sizing information as the page is loading. They are particularly useful on <svg>, which may size themselves enormously in an awkward way if they have a viewBox and lack width and height attributes. Browsers even do special magic with images, where the width and height are used to reserve the correct aspect-ratio derived space in a situation with fluid images, which is great for a smooth page loading experience.

But presentational attributes are also weak and are usually overridden in the CSS.


What’s the Difference Between Width/Height in CSS and Width/Height HTML attributes? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/whats-the-difference-between-width-height-in-css-and-width-height-html-attributes/feed/ 3 301933
Working with Attributes on DOM Elements https://css-tricks.com/working-with-attributes-on-dom-elements/ https://css-tricks.com/working-with-attributes-on-dom-elements/#comments Fri, 30 Aug 2019 14:30:43 +0000 https://css-tricks.com/?p=294650 The DOM is just a little weird about some things, and the way you deal with attributes is no exception. There are a number of ways to deal with the attributes on elements. By attributes, I mean things like the …


Working with Attributes on DOM Elements originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
The DOM is just a little weird about some things, and the way you deal with attributes is no exception. There are a number of ways to deal with the attributes on elements. By attributes, I mean things like the id in <div id="cool"></div>. Sometimes you need to set them. Sometimes you need to get them. Sometimes there are fancy helper APIs. Sometimes there isn’t.

For this article, I’ll assume el is a DOM element in your JavaScript. Let’s say you’ve done something like const el = document.querySelector("#cool"); and matched <div id="cool"> or whatever.

Some attributes are also attributes of the DOM object itself, so iff you need to set an id or title, you can do:

el.id; // "cool"
el.title = "my title";
el.title; // "my title";

Others that work like that are lang, align, and all the big events, like onclick.

Then there are attributes that work similarly to that but are nested deeper. The style attribute is like that. If you log el.style you’ll see a ton of CSS style declarations. You can get and set them easily:

el.style.color = "red";
module.style.backgroundColor = "black";

You can get computed colors this way too. If you do module.style.color hoping to get the color of an element out of the gate, you probably won’t get it. For that, you’d have to do:

let style = window.getComputedStyle(el);
style.color; // whatever in CSS won out

But not all attributes are like first-class attributes like that.

el['aria-hidden'] = true; // nope

That “works” in that it sets that as a property, but it doesn’t set it in the DOM the proper way. Instead, you’ll have to use the generic setter and getter functions that work for all attributes, like:

el.setAttribute("aria-hidden", true);
el.getAttribute("aria-hidden");

Some attributes have fancy helpers. The most fancy is classList for class attributes. On an element like:

<div class="module big"></div>

You’d have:

el.classList.value; // "module big"
el.classList.length; // 2
el.classList.add("cool"); // adds the class "cool", so "module big cool"
el.classList.remove("big"); // removes "big", so "module cool"
el.classList.toggle("big"); // adds "big" back, because it was missing (goes back and forth)
el.classList.contains("module"); // true

There’s even more, and classList itself behaves like an array so you can forEach it and such. That’s a pretty strong reason to use classes, as the DOM API around them is so handy.

Another attribute type that has a somewhat fancy help is data-*. Say you’ve got:

<div data-active="true" data-placement="top right" data-extra-words="hi">test</div> 

You’ve got dataset:

el.dataset;
/*
{
  active: "true",
  "placement", "top right"
*/

el.dataset.active; // "true"
el.dataset.extraWords; // "hi", note the conversion to camelCase

el.dataset.active = "false"; // setters work like this

Working with Attributes on DOM Elements originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/working-with-attributes-on-dom-elements/feed/ 8 294650