Schema Based Styling

View on Github written on April 13th, 2013

Short Introduction to Microdata

Microdata is a way to embed meaningful meta data into a web application and to construct relationships and associations. One of the more popular kinds of microdata is Schema, which is endorsed by Bing, Yahoo, and Google. If this is the first time you have heard of Schema and you would like more information, consider reading through the getting started page.

Styling Microdata through Attributes

In CSS you may target any element through its attribute. Ordinarily we would target an element by a common selector such as a class or an id. If you wish, you may review all the many ways you can select an element with CSS. It turns out that the attributes we use to specify schema microdata are usable as selectors in our CSS. This means that we can create common styles for types of information.

Consider the following markup for a Post Address:

<p itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
    <span itemprop="streetAddress">123 Some Street St.</span>
    <span itemprop="addressLocality">City</span>
    <span itemprop="addressRegion">Somewhere</span>
    <span itemprop="postalCode">12345</span>
</p>

The output for this is:

123 Some Street St. City Somewhere 12345

The traditional way we would target such markup is by adding a class. We might, for example, add the class PostalAdresss to the paragraph tag like such:

<p class="PostalAdress" itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">

And then target the class in our CSS like:

.PostalAdress { /* css styles here */ }

Yet, sometimes we wish to create a stronger relationship between the meaning of our data and its visual representation. We might, for example, wish the above address to always span two lines. We might want the region to appear entirely in uppercase. We might want a comma to appear visually after the region, but not to appear in the markup. etc.

So we devise the following CSS:

*[itemprop="streetAddress"]:after {
    white-space: pre;
    content: "\A";
}
*[itemprop="addressRegion"] {
    text-transform: uppercase;
}
*[itemprop="addressRegion"]:after {
    content: ","
}

But typing that out each and every time can become cumbersome. It turns out that although we can target itemscope and itemtype attributes, it Would be nicer if we could simply generate class names for each element with schema meta data automatically. Consider the following jquery snippet which will do just that:

$(function(){
    // Add Itemscope Class Name
    $('*[itemscope]').each( function() {
        $(this).addClass($(this).attr('itemtype').replace('http://schema.org/', '').toLowerCase());
    });

    // Add Itemtype Class Name
    $('*[itemprop]').each( function() {
        $(this).addClass($(this).attr('itemprop'));
    });
});

With these CSS hooks we can create style relationships between data. This hierarchical styling is most obvious when using a preprocessor such as LESS or SASS instead of raw CSS.

Consider a rewrite of our previous CSS example into LESS, which clearly illustrates the hierarchical relationship:

.postaladress {
    .streetaddress {
        &:after {
            white-space: pre;
            content: "\A";
        }
    }
    .addresslocality {}
    .addressregion {
        text-transform: uppercase;
        &:after {
            content: ","
        }
    }
    .postalcode {}
}

We can now create meaningful styles for hierarchical relationships without the need to add arbitrary classes. If we limit or extend the scope of our .postaladdress class we can create styles for the different ways in which the information is presented without altering the markup.

The Next Logical Step

The benefit of having semantic styling on addresses is of limited use: not all websites collate large amounts of address or contact information. But what about the case of articles on a blog or products for sale on a merchant site. What if we could extend the principles of object inheritance to not just our semantic markup, but to our visual representation as well? By organizing our information semantically we are also able to predict how we want that information represented visually. And so we can create rules to modify the visual presentation according to what kind of information we have, and its relationship to other information on the page. A product for sale may need to look differently when it is presented in an article than when it is shown on the product page.