It’s been some years since Tab Atkins-Bittner first proposed Cascading Attribute Sheets. I had a situation come up which made me think about them again and I thought I’d share.

On my site I have a handful of blog posts which have a title and/or text content in different languages. As someone who speaks a handful of languages, I like incorporating different languages, phrases, and untranslatable words into my day-to-day blogging. 「手答え」(tegotae) is an example of one of those words. It directly translates to “hand response” but is sometimes translated as “haptic feedback” or “game feel” when used in a video game context.

One problem with my use of other languages is that I’m lacking proper lang attributes on the foreign text, which makes it inaccessible. I’ve started brainstorming ways out of this, but finding a sustainable system while supporting mixed language use — even on my simple site — can be daunting.

What’s hard inside the underlying system.

In my Markdown-powered blog, adding multi-language support to every dynamic text field is difficult. It would require making configurable options (title_lang, title_dir, summary_lang, summary_dir, tag_lang, etc) for every custom text field on my site.

I would then have to go into all my templates and anywhere I echo a value {{ title }} I would have to wrap that in an element that could echo the title in every template where we render a title. I end up with ugly markup like this:

  {% if title_lang %}lang="{{ title_lang }}"{% endif %} 
  {% if title_dir %}dir="{{ title_dir }}"{% endif %}
  {{ title }}
  {% if summary_lang %}lang="{{ summary_lang }}"{% endif %} 
  {% if summary_dir %}dir="{{ summary_dir }}"{% endif %}
  {{ summary }}

And all that is just for titles! 2 elements, 12 lines of code. I have it easy on my static site too. For CMS sites, there is a four fold issue with writing frontend code, backend for processing code, UI code in the CMS, and updating the database to support all these attribute fields. It’s doable, but managing code in multiple places is fraught with disaster. Internationalization is something you want to plan for before even building the site, you don’t baby step into it.

My post content is a slightly different story. My complaints are mild here because it’s my choice to use Markdown, but adding a lang attribute to an element is doable, but I have to break out of the Markdown syntax and write HTML to support it.

## 木組みの家
<h2 lang="ja">木組みの家</h2>

These are two different writing and aural experiences. One is easy to write and the other is correct.

What’s easy in the underlying system.

I already have Art Direction support built into my static site, so I can inject a <style> tag in the <head>:

.post .title {
  color: purple;

When the post renders, the title is purple. Going back to Tab’s proposal, if Cascading Attribute Sheets existed, I could support a multilingual blog post with a block of attributes on the page.

.post .title {
  lang: el;
.post pre:first-of-type() {
  lang: he;
  dir: rtl;

This even seems somewhat easy to polyfill. In fact, here’s a rudimentary polyfill using the CSS parsing engine and Constructible Stylesheets.

See the Pen Rudimentary CAS parser by Dave Rupert (@davatron5000) on CodePen.

I’m cheating a bit and using custom properties for the attributes, but you get the gist. Also I’m cheating the hard parts like :hover or :invalid states. But for a proof of concept, it seems the CSS parser could adapt to do the work.

All that is just for titles.

A technology like Cascading Attribute Sheets would be helpful to me. This is a basic example for internationalized text fields on a blog post, but with all the attributes on all the elements this problem gets broader real quick. If you consider ARIA and the broad set of dynamic states that a chunk of HTML can express via attributes, do we need new mechanism that feels less like a one-off application of attribute soup?

There was a whole decade of browser development where kept adding attributes because attributes were easier than adding HTML. It’s become a mess. Look at how the world could be with Attribute Sheets!

/* forms.cas */
form:has(input[type="search"]) {
  enterkeyhint: 'Search'

input[name="username"] {
	required: true;
  autocomplete: current-password;

input[type="password"] {
	required: true;
  autocomplete: current-password;

input[type="password"][name="new-password"] {
	autocomplete: new-password;
	required: true;
	pattern: '[0-9].{6,}[A-Z]';
  aria-description: 'Provide an alphanumeric password with at least 6 characters';

input[type="password"][name="new-password"]:invalid {
  aria-errormessage: 'Password did not meet requirements';

... etc.

The list goes on, but I feel like the next generation of Twitter Bootstrap could be a single Attribute Sheet file for making your forms good. I’d pay $5 right now for someone to tell me the right way to setup all my form attributes for cross-device success, I’m pretty confused after all these years.

There were two parallel conversations happening on Twitter this week; one about CSS Toggles and another about CSS Speech. These are different ideas, but they somewhat overlap in that they control behavior outside the bounds of visual style. speak: none; has sorely been missing from the platform, a way to hide my garbage code from unsuspecting listeners. And the @machine {} part of CSS Toggles is interesting because CSS (to me) is already a state machine. I’m often in situations where I need to express “If this is this, then these must be that.” I have no horse in this race, but I like the ideas thrown around, but I do wonder if Cascading Attribute Sheets have a role in this future.

If you will allow an old man the pleasure of time, there’s one more correlation I’d like to make. I harken back to the microformats revolution. We poured hours into applying the correct inline classes for parsers and crawlers alike. Then we moved off of that for a more XML flavored feel and poured our hours into adding itemprop attributes. After a couple decades and the dust has settled, we’re doing less of that now and using JSON schemas in the <head> of our pages to inform our search engine gods. If I were hazarding a guess, I wonder if a structured JSON schema proved to be the easiest format to both write and consume. It’s a copy-paste block of properties and values, not hundreds of inline properties and values unsustainably littered through my markup. I rage against the JSON schema gods, but I wonder if they’re right.

Maybe, the block of key-value pairs has a better 手答え than the rest of the options we’ve tried in the past.