Andy Davies

Web Performance Consultant

What if We Could Use CSS to Alter HTML Attributes?

As the ideas behind responsive web design mature, and our skills and experience with them grow, we're faced with a gap between what the tools and technologies can do and what we'd like them to do.

We often end up trying to fill the gap with javascript and using it not just for behaviour but to change appearance and content too.

Javascript might be the right tool for many things, but should we really be embedding attributes that control appearance in our scripts, or might a declarative approach that uses CSS to change HTML attributes be clearer?

Syntax

A syntax that allows HTML attributes to be changed via CSS might look something like this:

HTMLattribute : [operator] value

e.g.

HTMLattribute :  value        // set value
HTMLattribute : +value        // add value e.g. to lists such as class, rel
HTMLattribute : -value        // remove value from list
HTMLattribute : ^value        // toggle value - remove if there, add if not

The syntax needs improving, for example the HTML attributes probably need prefixing to prevent clashes with CSS properties that share the same name.

I'm also not sure about the list operators, but the syntax is good enough to illustrate some of the ways the idea might be useful.

Classes as hooks for javascript e.g. conditional loading

The class and rel attributes sometimes get used as hooks for javascript but what if we want to add a hook that depends on viewport size?

We could use matchMedia(), but as Jeremy Keith points out in Conditionally loading content, using matchMedia() requires maintaining breakpoints in more than one place.

Jeremy eventually chose the option of generating a hidden marker on the body element using :after (see Conditional CSS), it works but it's a bit of a hack.

What if we could just add a class directly using CSS and use that as the hook for our javascript?

/* add class big-screen to html element */
  
@media all and (min-width: 1024px) {
  html {
      class: +"big-screen";
  }
}

Data- attributes for configuration of widgets e.g. tweet buttons etc.

jQuery mobile, social media buttons and other widgets are increasingly using HTML5 data- attributes for configuration.

The tweet button has options such as big buttons vs little buttons, counts, count position etc., all controlled via data- attributes.

In smaller viewports we might want to make the tweet button larger so it's easier to touch, and free up some room by hiding the count.

/* set the data- attributes that makes button bigger and removes tweet count */
  
@media all and (max-width: 480px) {
  .twitter-share-button {
      data-size: "large";
      data-count: "none";
  }
}

Swapping content

The srcset / picture proposals will help resolve the responsive images problem, so we probably don't need another solution but as a use-case it shows how updating HTML attributes could be used to swap content, while still keeping all the content in HTML.

<!-- img element that uses data- attributes to declare images, keeping content in HTML -->

<img src="small.jpg" data-src-med="medium.jpg" data-src-lge="large.jpg">
/* use media queries and attr() function to replace the small image if appropriate */

@media all and (min-width: 321px) and (max-width: 800px) {
  img {
      src: attr(data-src-med);
  }
}

@media all and (min-width: 801px) {
  img {
      src: attr(data-src-lge);
  }
}

This is just an illustration as an approach like this for responsive images wouldn't enable the UA to use network connection throughput to pick the most appropriate image that the other proposals do.

Feedback

At the moment this is just an idea, an idea which almost certainly has plenty of issues, so what I'm really looking for is feedback.

Is it a useful idea, how would you use it, how could it be improved, what issues are there implementing it etc. or have I just been drinking too much coffee?

Cascading Attribute Sheets

Added: 24 Aug 2012

Tab Atkins and Fantasai have come out with a similar proposal for Cascading Attribute Sheets

The syntax is pretty similar but Tab and Fantasai suggested another way of adding to an existing property, so with their syntax my first example would look like this:

/* add class big-screen to html element */
  
@media all and (min-width: 1024px) {
  html {
      class: attr(class) big-screen;
  }
}

The proposal and comment are well worth a read.

Comments