{"componentChunkName":"component---src-templates-blog-post-js","path":"/blog/2008/07/21/microformats-dark-data-and-css-part-2/","result":{"data":{"markdownRemark":{"html":"<p>The <a href=\"https://hexmen.com/blog/2008/07/15/microformats-dark-data-and-css-part-1/\">first part of this article</a> considered over 100 HTML 4 attributes and came to the conclusion <code>class</code> was the only one suitable for storing <em>machine data</em> (i.e. data specifically inserted and intended for machine parsing.)</p>\n<p>In this second part, I’ll review several ways to store data in the class attribute, determine the ‘best’ method, and suggest a CSS implementation change that is (IMO) both trivial and immensely beneficial.</p>\n<p>We start by considering the definition of the class attribute, how it’s value is interpreted, and what restrictions this this places on us for storing data.</p>\n<h3>Isn’t <code>class</code> object-oriented?</h3>\n<p>Some people say <code>class</code> has an object-oriented use as though (X)HTML and CSS are object-oriented languages, with inheritance based on <code>class</code> values. But that’s not how things work: inheritance is based on parent/child relationships, with everything else determined by ”<a href=\"https://www.w3.org/TR/CSS2/cascade.html\">the cascade</a>“.</p>\n<p>Let me illustrate with a contact directory example I hope isn’t too contrived.</p>\n<p>Contact phone numbers are styled using common fonts and padding, but with different background-images based on the type of phone number (home, work, fax etc.) Using a top-level concept class of <code>tel</code>, we <em>“subclass”</em> using <code>home</code>, <code>work</code> and <code>fax</code>.</p>\n<p>Phone numbers can be output and formatted using multiple classes working together:</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\">span</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;tel home&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">+1 212 123 1234</span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span></span></code></pre>\n<p>Because <code>home</code> is such a generic term, we’d write CSS using a 2-class selector like this:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"css\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">.tel</span><span class=\"mtk1\"> {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font</span><span class=\"mtk1\">: ...;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">padding-left</span><span class=\"mtk1\">: </span><span class=\"mtk7\">16px</span><span class=\"mtk1\">;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">transparent</span><span class=\"mtk1\"> </span><span class=\"mtk8\">no-repeat</span><span class=\"mtk1\"> </span><span class=\"mtk8\">middle</span><span class=\"mtk1\"> </span><span class=\"mtk8\">left</span><span class=\"mtk1\">;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">.tel.home</span><span class=\"mtk1\"> {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background-image</span><span class=\"mtk1\">: </span><span class=\"mtk11\">url</span><span class=\"mtk1\">(</span><span class=\"mtk12\">icons/tel-home.gif</span><span class=\"mtk1\">);</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">.tel.work</span><span class=\"mtk1\"> {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background-image</span><span class=\"mtk1\">: </span><span class=\"mtk11\">url</span><span class=\"mtk1\">(</span><span class=\"mtk12\">icons/tel-work.gif</span><span class=\"mtk1\">);</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">.tel.fax</span><span class=\"mtk1\"> {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background-image</span><span class=\"mtk1\">: </span><span class=\"mtk11\">url</span><span class=\"mtk1\">(</span><span class=\"mtk12\">icons/tel-fax.gif</span><span class=\"mtk1\">);</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span></code></pre>\n<p>Dropping <code>tel</code> from the mark-up would cause all styling to be lost - the value <code>home</code> on its own does not encapsulate enough information to determine its position in a class hierarchy. Later on, I’ll come back to this and suggest hyphenation as an option that may embody a class relationship more explicitly.</p>\n<h3>Unordered <code>class</code> data</h3>\n<p>By definition, class is an unordered set of white-space separated values. The values “tel home” and “home tel” should be treated the same, with the CSS selector “.tel.home” applying with equal specificity to both numbers below.</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"html\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><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;tel home&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">+1 212 12341 12112</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><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;home tel&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">+1 212 12341 12112</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span></span></code></pre>\n<p>We must bear this ordering-independence in mind when storing data in <code>class</code>. Trying to store multiple bits of data in sequential order cannot work - e.g. a conference schedule:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"html\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">...</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">li</span><span class=\"mtk17\">&gt;&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 9:00 dtend 9:15&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;9am&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">09:00</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> - Registration</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">li</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\">li</span><span class=\"mtk17\">&gt;&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 9:15 dtend 10:30&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;9:15am&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">09:15</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> - Keynote</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">li</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\">li</span><span class=\"mtk17\">&gt;&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 10:30 dtend 10:45&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;10:30am&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">10:30</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> - Coffee</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">li</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\">li</span><span class=\"mtk17\">&gt;&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 10:45 dtend 12:00&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;10:45am&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">10:45</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> - Session 1</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">li</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\">li</span><span class=\"mtk17\">&gt;&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 13:00 dtend 14:00&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;1pm&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">13:00</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> - Session 1</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">li</span><span class=\"mtk17\">&gt;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">...</span></span></span></code></pre>\n<p><em>Note: in this example, humans are supposed to infer end-times by looking at the start-time of the following event. We include machine-data for end-times because “inference” is not easy for programmers to implement.</em></p>\n<p>Although the order is clear and correct in the mark-up, browsers, parsers and libraries have no obligation to maintain the order when accessed. e.g. a “classes” method could return an arbitrarily ordered array of classes:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"js\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk3\">// fetch the classes for the first item in the schedule:</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">classes</span><span class=\"mtk1\"> = \\</span><span class=\"mtk11\">$</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;.dtstart:nth(0)&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">classes</span><span class=\"mtk1\">();</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk3\">// may output: \\[&quot;9:00&quot;, &quot;9:15&quot;, &quot;dtend&quot;, &quot;dtstart&quot;\\]</span></span></span></code></pre>\n<p>Without further labouring, the take-home point is: data in class-values cannot rely on ordering.</p>\n<h3>The necessity of prefixes</h3>\n<p>You may not be 100% certain how your content will be processed or transformed, or what corruption it may suffer; but you can at least <em>attempt</em> to mitigate disaster.</p>\n<p>For example: times embedded in machine-data can be arbitrarily precise, from specifying years on their own (“2008”), to fully specifying a time-zone and exact second of an event (“20080721T124032+0100”) The longer format is unlikely to cause confusion (to machines), but the shorter variants could easily be mistaken for model numbers. e.g. the ISSN of periodicals for sale:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"html\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">li</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\">a</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;...&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;issn 02624079 dtstart 20080719&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;New Scientist dated 19th July 2008&quot;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">New Scientist no. 2665</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">a</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </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\">li</span><span class=\"mtk17\">&gt;</span></span></span></code></pre>\n<p>As we can’t rely on ordering, we need to join the data-type and the data-value together. A few approaches have been suggested, including wrapping the value, or concatenating the pieces with an arbitrary separator - I suggest using a hyphen, which I’ll justify in a minute:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"html\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">a</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;...&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;issn{02624079} dtstart{20080719}&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">a</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\">a</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;...&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;issn#02624079 dtstart#20080719&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">a</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\">a</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;...&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;issn-02624079 dtstart-20080719&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">a</span><span class=\"mtk17\">&gt;</span></span></span></code></pre>\n<h3>The hyphenated-prefix selector <code>[attribute|=prefix]</code></h3>\n<p>CSS 2 introduced <a href=\"https://www.w3.org/TR/CSS2/selector.html#attribute-selectors\">several attribute selectors</a>, including one I’m calling the hypehenated-prefix selector.</p>\n<p>The specification admits the primary purpose of this selector is for matching language subcodes; i.e. where CSS rules need only apply to content written in some subset of natural languages:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"css\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">[</span><span class=\"mtk12\">lang</span><span class=\"mtk1\">|=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk1\">] </span><span class=\"mtk6\">blockquote</span><span class=\"mtk1\">,</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">[</span><span class=\"mtk12\">lang</span><span class=\"mtk1\">|=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk1\">] </span><span class=\"mtk6\">q</span><span class=\"mtk1\">,</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">blockquote</span><span class=\"mtk1\">[</span><span class=\"mtk12\">lang</span><span class=\"mtk1\">|=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk1\">],</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">q</span><span class=\"mtk1\">[</span><span class=\"mtk12\">lang</span><span class=\"mtk1\">|=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk1\">] {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">quotes</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;“&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;”&quot;</span><span class=\"mtk1\">;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">[</span><span class=\"mtk12\">lang</span><span class=\"mtk1\">|=</span><span class=\"mtk8\">&quot;de&quot;</span><span class=\"mtk1\">] </span><span class=\"mtk6\">blockquote</span><span class=\"mtk1\">,</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">[</span><span class=\"mtk12\">lang</span><span class=\"mtk1\">|=</span><span class=\"mtk8\">&quot;de&quot;</span><span class=\"mtk1\">] </span><span class=\"mtk6\">q</span><span class=\"mtk1\">,</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">blockquote</span><span class=\"mtk1\">[</span><span class=\"mtk12\">lang</span><span class=\"mtk1\">|=</span><span class=\"mtk8\">&quot;de&quot;</span><span class=\"mtk1\">],</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">q</span><span class=\"mtk1\">[</span><span class=\"mtk12\">lang</span><span class=\"mtk1\">|=</span><span class=\"mtk8\">&quot;de&quot;</span><span class=\"mtk1\">] {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">quotes</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;«&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;»&quot;</span><span class=\"mtk1\">;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span></code></pre>\n<p>The rules above specify different quote-marks for German and English. Using the prefix selector means the appropriate rule applies to all English languages, including “en-GB” and “en-US”, as well as content marked no more specifically than lang=“en”. Similarly, the ‘de’ rule applies to all German languages.</p>\n<p>However, this selector can just as easily be applied to classes. We can rewrite the telephone-number example as:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"html\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><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;tel-work&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">+1 212 800 1234</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><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;tel-home&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">+1 212 123 1234</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span></span></code></pre>\n<pre class=\"grvsc-container default-dark\" data-language=\"css\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">[</span><span class=\"mtk12\">class</span><span class=\"mtk1\">|=</span><span class=\"mtk8\">&quot;tel&quot;</span><span class=\"mtk1\">] {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font</span><span class=\"mtk1\">: ...;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">padding-left</span><span class=\"mtk1\">: </span><span class=\"mtk7\">16px</span><span class=\"mtk1\">;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">transparent</span><span class=\"mtk1\"> </span><span class=\"mtk8\">no-repeat</span><span class=\"mtk1\"> </span><span class=\"mtk8\">middle</span><span class=\"mtk1\"> </span><span class=\"mtk8\">left</span><span class=\"mtk1\">;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">.tel-home</span><span class=\"mtk1\"> {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background-image</span><span class=\"mtk1\">: </span><span class=\"mtk11\">url</span><span class=\"mtk1\">(</span><span class=\"mtk12\">icons/tel-home.gif</span><span class=\"mtk1\">);</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">.tel-work</span><span class=\"mtk1\"> {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background-image</span><span class=\"mtk1\">: </span><span class=\"mtk11\">url</span><span class=\"mtk1\">(</span><span class=\"mtk12\">icons/tel-work.gif</span><span class=\"mtk1\">);</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk6\">.tel-fax</span><span class=\"mtk1\"> {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background-image</span><span class=\"mtk1\">: </span><span class=\"mtk11\">url</span><span class=\"mtk1\">(</span><span class=\"mtk12\">icons/tel-fax.gif</span><span class=\"mtk1\">);</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span></code></pre>\n<h3>Relaxing the hyphenated-prefix rules</h3>\n<p>Sadly, the hyphenated-prefix is overly-restricted. In the following example, only one rule applies:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"css\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">[</span><span class=\"mtk12\">class</span><span class=\"mtk1\">|=</span><span class=\"mtk8\">&quot;issn&quot;</span><span class=\"mtk1\">] {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font-weight</span><span class=\"mtk1\">: </span><span class=\"mtk8\">bold</span><span class=\"mtk1\">;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><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></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background-image</span><span class=\"mtk1\">: </span><span class=\"mtk11\">url</span><span class=\"mtk1\">(</span><span class=\"mtk12\">bg/microformat.gif</span><span class=\"mtk1\">);</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span></code></pre>\n<pre class=\"grvsc-container default-dark\" data-language=\"html\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">li</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\">a</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;...&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;issn-02624079 dtstart-20080719&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;New Scientist dated 19th July 2008&quot;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">New Scientist no. 2665</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">a</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk1\">  </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\">li</span><span class=\"mtk17\">&gt;</span></span></span></code></pre>\n<p>The problem is due to the way <code>[attribute|=prefix]</code> is defined:</p>\n<blockquote>\n<p>Match when the element’s “att” attribute value is a hyphen-separated list of “words”, beginning with “val”. <em>The match always starts at the beginning of the attribute value.</em> This is primarily intended to allow language subcode matches (e.g., the “lang” attribute in HTML) as described in <a href=\"https://tools.ietf.org/html/rfc1766\">RFC 1766</a>.</p>\n</blockquote>\n<p>(Emphasis added.)</p>\n<p>If the definition had instead been made to cater for a white space separated set of hyphenated tokens, we’d be in a much better position for styling and parsing machine-data microformats today.</p>\n<h3><code>[attribute|=prefix]</code> implementations</h3>\n<p>(Surprisingly) the big four browsers (including IE7) all support the hyphenation prefix selector. But, JavaScript library support is lacking, specifically (naming the javascript library I use daily) <a href=\"https://jquery.com/\">jQuery</a> doesn’t handle the hyphenated-prefix selector, although it’s a simple patch.</p>\n<p>Assuming JavaScript libraries (or microformat parsers) already implement attribute-selectors, it’s a simple matter to support white space separated hyphenated-prefixes. The key regular-expression is:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"js\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk5\">/</span><span class=\"mtk8\">(</span><span class=\"mtk11\">^|</span><span class=\"mtk5\">\\s</span><span class=\"mtk8\">)</span><span class=\"mtk5\">prefix</span><span class=\"mtk8\">(</span><span class=\"mtk5\">-</span><span class=\"mtk11\">|</span><span class=\"mtk5\">\\s</span><span class=\"mtk11\">|$</span><span class=\"mtk8\">)</span><span class=\"mtk5\">/</span><span class=\"mtk1\">;</span></span></span></code></pre>\n<p>Assuming your users know what they’re doing and are willing to fix their own issues after throwing something stupid at your library, the regular-expression is easily built on executed on the fly:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"js\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\"><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">RegExp</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;(^|</span><span class=\"mtk6\">\\\\</span><span class=\"mtk8\">s)&quot;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">prefix</span><span class=\"mtk1\"> + </span><span class=\"mtk8\">&quot;(-|</span><span class=\"mtk6\">\\\\</span><span class=\"mtk8\">s|$)&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">test</span><span class=\"mtk1\">(</span><span class=\"mtk12\">attribute</span><span class=\"mtk1\">);</span></span></span></code></pre>\n<p>Or (I think), in <a href=\"https://www.w3.org/TR/xpath-functions/#func-matches\">XPath 2.0</a>:</p>\n<pre class=\"grvsc-container default-dark\" data-language=\"\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-source\">//*[matches(@attribute, &quot;(^|\\s)prefix(-|\\s|$)&quot;)]</span></span></code></pre>\n<h3>Encoding data</h3>\n<p>Quotations and ampersands aside (naturally taken care of by normal (X)HTML encoding rules) there’s an obvious problem when data-values contain white space. Fortunately, there’s also an obvious solution, as several methods exist to encode arbitrary data into continuos strings without any white-space. In JavaScript, the methods available include <code>escape</code>, <code>encodeURI</code> and <code>encodeURIComponent</code>, and I’d suggest <code>encodeURI</code> as the best option - providing a good balance between safely encoding data, without being overly aggressive and creating human-unreadable data.</p>\n<h3>Simplicity is the key</h3>\n<p>Microformats success depends on its simplicity; using a few attributes and a handful of patterns to invisibly add extra layers of information to existing content.</p>\n<p>Hopefully, I haven’t suggested anything in conflict with existing microformats. Hyphenated-prefixes should be viewed as an <em>additional tool</em> in your arsenal. Not as a competing or successor solution.</p>\n<p>With a more flexible definition of the that damned attribute selector, I’m sure the <a href=\"http://unapi.info/specs/\">unAPI</a> folks would have produced an <em>even simpler</em> specification, and the arguments around microformat’s <a href=\"http://microformats.org/wiki/datetime-design-pattern\">datetime design pattern</a> would have been resolved years ago.</p>\n<p>Though I’m sure it doesn’t show, I’ve written and rewritten this article many times, but it doesn’t get any more complex:</p>\n<p><strong>If you want to piggy-back machine-data on existing content, use the <code>class</code> attribute. Separate data-types from data-values using a hyphen, and encode the data using something equivalent to JavaScript’s <code>encodeURI</code>.</strong></p>\n<p>That’s all folks</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 .mtk6 { color: #D7BA7D; }\n  .default-dark .mtk7 { color: #B5CEA8; }\n  .default-dark .mtk11 { color: #DCDCAA; }\n  .default-dark .mtk3 { color: #6A9955; }\n  .default-dark .mtk5 { color: #D16969; }\n  .default-dark .mtk10 { color: #4EC9B0; }\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":7,"frontmatter":{"title":"Microformats, dark data and CSS - part 2","blurb":"Acting on data buried in class attribute would be easier with an enhanced attribute selector","date":"2008-07-21T14:52:01.000Z","modified":"2011-01-03T17:20:14.000Z"}}},"pageContext":{"slug":"/blog/2008/07/21/microformats-dark-data-and-css-part-2/","next":{"fields":{"slug":"/blog/2008/07/22/tweaking-png-transparency-with-imagemagick/"},"frontmatter":{"title":"Tweaking PNG transparency with ImageMagick"}},"previous":{"fields":{"slug":"/blog/2008/07/15/microformats-dark-data-and-css-part-1/"},"frontmatter":{"title":"Microformats, dark data and CSS - part 1"}}}},"staticQueryHashes":["1192980692"]}