{"componentChunkName":"component---src-templates-blog-post-js","path":"/blog/2008/07/15/microformats-dark-data-and-css-part-1/","result":{"data":{"markdownRemark":{"html":"<p>There was a bit of kerfuffle when the <a href=\"https://www.bbc.co.uk/blogs/radiolabs/2008/06/removing_microformats_from_bbc.shtml\">BBC dropped support for microformats</a> in their program listings.</p>\n<p>You can’t argue with their reasons: data for <a href=\"http://microformats.org/\">microformats</a> was being read aloud by screen-readers, popping up as tool-tips, and confusing the hell out of their users.</p>\n<p>The microformats community rallied to solve the issue, but <a href=\"https://www.bbc.co.uk/blogs/bbcinternet/2008/07/why_the_bbc_removed_microforma.html\">Auntie Beeb rejected all their proposals</a>; and due to lack of community support, also back-tracked on their own proposal (inserting <code>data-</code> prefixed values into the <code>class</code> attribute.)</p>\n<p>You can’t blame them for rejecting the microformats community’s proposals. This proposal feels particularly torturous:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"html\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  To be held on</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;dtstart dtend&quot;</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">abbr</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;value&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;1998-03-12&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">12 March 1998</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">abbr</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  from</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;dtstart&quot;</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">abbr</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;value&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;08:30&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">8:30am</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">abbr</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">abbr</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;value&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;-0500&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">EST</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">abbr</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  until</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;dtend&quot;</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">abbr</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;value&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;09:30&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">9:30am</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">abbr</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">abbr</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;value&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;-0500&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">EST</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">abbr</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span></span></code></pre>\n<p>That suggestion seems to be the result of a <a href=\"http://rbach.priv.at/Microformats/IRC/2008-06-24#T161218\">30 minute brain-fart by microformat’s spiritual leader</a> and, like the BBC, I find it “complicated” (I doubt that was the first word that sprang to mind though.)</p>\n<p>Let’s go back to the specs and see what HTML gives us to work with. Considering over one hundred <a href=\"https://www.w3.org/TR/REC-html40/index/attributes.html\">attributes in HTML 4</a>, only a handful apply to the elements we’d want to tag (not just <code>&#x3C;abbr></code>, but also <code>&#x3C;span></code>, <code>&#x3C;a></code>, <code>&#x3C;li></code> amongst several others.)</p>\n<p>The only attributes available to insert microformat data and still pass validation are: <code>class</code>, <code>dir</code>, <code>id</code>, <code>lang</code>, <code>style</code> and <code>title</code>.</p>\n<p>We’ve dismissed all event-handling attributes (<code>on_whatever_</code>) as they’re supposed to contain script, and we can quickly dismiss a few more attributes now:</p>\n<p><code>dir</code> can only contain two values (<code>ltr</code> and <code>rtl</code>.)</p>\n<p><code>id</code> must be unique per page; that’s a restriction we can’t work with for microformats.</p>\n<p><code>style</code> attributes are supposed to hold CSS properties. It <em>could</em> be subverted using a <a href=\"https://www.w3.org/TR/CSS21/syndata.html#vendor-keywords\">vendor prefix</a> e.g. <code>style=\"-mf-dtstart: ...\"</code>. However, you’d buy yourself a place in hell, and you’d never get support from the microformats community.</p>\n<p>That leaves us with <code>lang</code>, <code>title</code> and <code>class</code>.</p>\n<h2>Why <code>lang</code>?</h2>\n<p>Good question.</p>\n<p>The <code>lang</code> attribute indicates what language the <em>content</em> of an element is held in. Language codes were defined in <a href=\"https://tools.ietf.org/html/rfc1766\">RFC 1766</a>, since replaced by <a href=\"https://tools.ietf.org/html/rfc3066\">RFC 3066</a>, which has itself been replaced by a pair of RFCs: <a href=\"https://tools.ietf.org/html/rfc4646\">4646</a> and <a href=\"https://tools.ietf.org/html/rfc4647\">4647</a>.</p>\n<p>Amongst the long lists of language codes, you can find a few options that <em>should</em> let you embed machine-data without it being read-aloud. e.g. the language-code <code>zxx</code> indicates there’s “no linguistic content”, so you might think a screen-reader would simply skip the content:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"html\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  To be held on 12 March 1998</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;dtstart dtend&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lang</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;zxx&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">1998-03-12</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  from 8:30am EST</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;dtstart&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lang</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;zxx&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">08:30-0500</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  until 9:30am EST</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;dtend&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lang</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;zxx&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">09:30-0500</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span></span></code></pre>\n<p>Sadly, a quick trial using accessibility features on a mac reveals the content it still read aloud. I suspect the other possible language codes - <code>art</code> for “artificial languages”, and the <code>x-</code> prefix for “private use” - would suffer the same fate.</p>\n<p>Also, the content would need hiding from sighted users using a simple CSS rule: <code>[lang|=zxx] { display: none }</code> - but this would fail under various viewing conditions (e.g. syndicating data via RSS without styles.)</p>\n<p>Finally, the whole idea of marking machine-data using the <code>lang</code> attribute may be frowned upon. RFC 4646 includes this:</p>\n<blockquote>\n<p>Language tags are used to help identify languages, whether spoken, written, signed, or otherwise signaled, for the purpose of communication. This includes constructed and artificial languages, but excludes languages not intended primarily for human communication, such as programming languages.</p>\n</blockquote>\n<p>Looks like the <code>lang</code> attribute’s a bit of a no-no then. That leaves us with <code>class</code> and <code>title</code>.</p>\n<h2><code>title</code> vs. <code>class</code></h2>\n<p>We’ve already mentioned the accessibility issues with <code>title</code>. The BBC have done the research and user-testing other people only think about. Their results show <em>it’s not just screen-readers</em> that get confused by machine-data in <code>title</code> attributes - sighted users are baffled too.</p>\n<p>Fragmenting one machine-readable value into three doesn’t solve the problem - it exacerbates it. The number of elements with mystical tool-tips increases; while human-friendliness increases for some (dates), it decreases for others (timezones).</p>\n<p>The <code>title</code> attribute is meant for humans, no matter how you spin it.</p>\n<h2>All hail the mighty <code>class</code></h2>\n<p>I must apologize: did I just have a ”<code>title</code> vs. <code>class</code>” debate without mentioning <code>class</code>?</p>\n<p>I guess I did. <code>title</code> got disqualified, leaving <code>class</code> to win by default.</p>\n<p><em>(small side-note: out of all the attributes on the short-list, <code>class</code> is the <strong>only one</strong> defined to contain <code>CDATA</code> - i.e. general-purpose Character DATA. Just thought that might be worth a mention.)</em></p>\n<p>Having whittled down our options to one winner, we now need to decide how we’re going to organize our data, and cram it into the <code>class</code> attribute. We need to take into account the definition of <code>class</code>, and that the attribute-value is treated as an <em>unordered</em> list of <em>white-space separated</em> tokens.</p>\n<p>That’s for part 2, where I also propose tweaking a CSS3 selector to change it from a single niche application to become a general purpose tool in a web-designers arsenal.</p>\n<p><strong>Update:</strong> This post predated HTML support for two features which cover the use-cases microformats tried to address: <a href=\"https://html.spec.whatwg.org/multipage/microdata.html#microdata\">microdata</a> and <a href=\"https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes\">custom data attributes</a>.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    position: relative;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n    line-height: 1.4;\n  }\n  \n  .grvsc-code {\n    display: table;\n  }\n  \n  .grvsc-line {\n    display: table-row;\n    box-sizing: border-box;\n    width: 100%;\n    position: relative;\n  }\n  \n  .grvsc-line > * {\n    position: relative;\n  }\n  \n  .grvsc-gutter-pad {\n    display: table-cell;\n    padding-left: 0.75rem;\n    padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2);\n  }\n  \n  .grvsc-gutter {\n    display: table-cell;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    user-select: none;\n  }\n  \n  .grvsc-gutter::before {\n    content: attr(data-content);\n  }\n  \n  .grvsc-source {\n    display: table-cell;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-source:empty::after {\n    content: ' ';\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    user-select: none;\n  }\n  \n  .grvsc-gutter + .grvsc-source {\n    padding-left: 0.75rem;\n    padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2);\n  }\n  \n  /* Line transformer styles */\n  \n  .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before {\n    content: ' ';\n    position: absolute;\n    width: 100%;\n  }\n  \n  .grvsc-line-diff-add::before {\n    background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2));\n  }\n  \n  .grvsc-line-diff-del::before {\n    background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2));\n  }\n  \n  .grvsc-line-number {\n    padding: 0 2px;\n    text-align: right;\n    opacity: 0.7;\n  }\n  \n  .default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .default-dark .mtk17 { color: #808080; }\n  .default-dark .mtk4 { color: #569CD6; }\n  .default-dark .mtk1 { color: #D4D4D4; }\n  .default-dark .mtk12 { color: #9CDCFE; }\n  .default-dark .mtk8 { color: #CE9178; }\n  .default-dark .grvsc-line-highlighted::before {\n    background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1));\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5));\n  }\n</style>","timeToRead":5,"frontmatter":{"title":"Microformats, dark data and CSS - part 1","blurb":"A quick recap of microformats and the HTML attributes originally abused to implement them","date":"2008-07-15T12:53:22.000Z","modified":"2011-01-03T17:20:14.000Z"}}},"pageContext":{"slug":"/blog/2008/07/15/microformats-dark-data-and-css-part-1/","next":{"fields":{"slug":"/blog/2008/07/21/microformats-dark-data-and-css-part-2/"},"frontmatter":{"title":"Microformats, dark data and CSS - part 2"}},"previous":{"fields":{"slug":"/blog/2008/07/10/php-grievance-number-1/"},"frontmatter":{"title":"PHP grievance number 1"}}}},"staticQueryHashes":["1192980692"]}