Back to Basic - Writing meaningful, accessible and semantic markup in Html5

Unless you are living in a cave, I expect you heard Html5 and know that most of the modern browsers has the reasonable support to render html5 pages. In this post, I will take the tiny sample “Bakery” which comes with the Microsoft WebMatrix as a site template and truly upgrade it to html5. The reason I mentioned “truly” because it is already using html5 doctype but the markup is still in xhtml. You can click here if you want to see a screenshot of this website.

The following is the skeleton of this site:

WebMatrix Bakery Skeleton

Now, let us see the markup when it is rendered in the browser:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Fourth Coffee - Home</title>
    <link href="Styles/Site.css" rel="stylesheet" />
</head>
<body>
    <div id="page">
        <div id="header">
            <p class="site-title"><a href="./">Fourth Coffee</a></p>
            <ul id="menu">
                <li><a href="./">Home</a></li>
                <li><a href="About">About Us</a></li>
            </ul>
        </div>
        <div id="body">
            <h1>Welcome to Fourth Coffee!</h1>
            <div id="featuredProdcut">
                <img alt="Featured Product" src="Images/Products/bread.jpg" />
                <div id="featuredProductInfo">
                    <div id="productInfo">
                        <h2>Bread</h2>
                        <p class="price">$1.49</p>
                        <p class="description">Fresh baked French-style bread</p>
                    </div>
                    <div id="callToAction">
                        <a class="order-button" href="order/4" title="Order Bread">Order Now</a>
                    </div>
                </div>
            </div>
            <ul id="products">
                <li class="product">
                    <div class="productInfo">
                        <h3>Carrot Cake</h3>
                        <img class="product-image" src="Images/Products/Thumbnails/carrot_cake.jpg" alt="Image of Carrot Cake" />
                        <p class="description">A scrumptious mini-carrot cake encrusted with sliced almonds</p>
                    </div>
                    <div class="action">
                        <p class="price">$8.99</p>
                        <a class="order-button" href="order/1" title="Order Carrot Cake">Order Now</a>
                    </div>
                </li>
                <!-- More Products -->
            </ul>
        </div>
        <div id="footer">
            &copy;2010 - Fourth Coffee
        </div>
    </div>
</body>
</html>

As I mentioned earlier that it has some flavor of html5, for example, if you see the first line you will find that it does not use long declaration of doctype like <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">, in html5 it has trimmed down to <!DOCTYPE html>. Next, to specify the content type, it is not required to write <meta http-equiv="Content-Type" content="text/html"; charset="utf-8"/>, instead <meta charset="utf-8"/> is used and at last for script and stylesheet the type is no longer required, for example the stylesheet file has been included with <link href="Styles/Site.css" rel="stylesheet"/> without the type="text/css".

But other than the above, there are nothing more that are html5ish also the markup contains too many div and unnecessary css classes. In order to make it truly meaningful, we are going to use some of the new html tags that comes with the html5. First, let me show you the bare minimum of the layout:

<body>
    <header role="banner">
        <h1><a href="/">Fourth Coffee</a></h1>
        <nav>
            <ul>
                <li><a href="/" rel="home">Home</a></li>
                <li><a href="/about">About Us</a></li>
            </ul>
        </nav>
    </header>
    <div role="main">
        <!-- Put your page content over here -->
    <div/>
    <footer role="contentinfo">
        <p>&copy;2010 - Fourth Coffee</p>
    </footer>
</body>

As you can see that we no longer using any container div (e.g. div id="page") since the body itself can act as the container and now it starts with the new header tag instead of the div id="header", the header also contains role="banner", it is not html5 specific instead it is called ARIA landmark role. Inside the header, rather than using p tag for the site title we are using the standard h1 and using the existing text replacing technique to replace it with the site banner. Next, for the top right navigation we are using the new nav element, but we are not using the ARIA role="navigation" as the nav itself stands for the navigation. The rest of the two element are pretty simple for the main content we are using the plain old div with an ARIA role="main" and the for the copyright we are using the new footer element of html5.

Next, for the products, the WebMatrix template is using div for the featured product and ul for the rest of the product listing. But in our case we are going to use another new element section. Initially, there was a misconception to replace div with section which was wrong, if it is only styling or DOM scripting purpose then you should stick with the div, but if want to group some thematically related content which are also self contained and independent part, you can use the section and in our case it is the product.

Now lets see the new markup:

<div role="main">
    <h1>Welcome to Fourth Coffee!</h1>
    <section id="featured">
        <figure>
            <img src="/Images/Products/bread.jpg" alt="Featured Product Bread"/>
        </figure>
        <div>
            <header>
                <h2>Bread</h2>
            </header>
            <div>
                <p>$1.49</p>
                <p>Fresh baked French-style bread</p>
            </div>
            <div>
                <a title="Order Bread" href="/order/4" class="order-button">Order Now</a>
            </div>
        </div>
    </section>
    <section class="product">
        <header>
            <h2>Carrot Cake</h2>
        </header>
        <figure>
            <img class="thumbnail" src="/Images/Products/Thumbnails/carrot_cake.jpg" alt="Carrot Cake"/>
            <figcaption>A scrumptious mini-carrot cake encrusted with sliced almonds</figcaption>
        </figure>
        <p>
            <span>$8.99</span>
            <a class="order-button" href="/order/1" title="Order Carrot Cake">Order Now</a>
        </p>
    </section>
    <!-- More Products -->
<div/>

As you can see that other than using section we are also using the new figure and we are putting the product description in the figcaption also check that each section has its own header like the main document. Now if are wondering what are the css style that are responsible for the styling, here you go:

article, aside, header, figcaption, figure, footer, nav, section
{
    display: block;
}

.thumbnail
{
    background-color: #edece8;
    border: 1px #e6e3d8 solid;
    height: 200px;
    margin: 0 0 7px 0;
    padding: 6px;
    width: 200px;
}

.order-button
{
    background-color: #a52f09;
    border: 1px solid #712107;
    color: #fdfcf7 !important;
    float: right;
    padding: 2px 7px; 
    /*CSS3 properties*/
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    border-radius: 4px;
    -webkit-box-shadow: 1px 2px 4px rgba(136,136,136, 0.6);
    -moz-box-shadow: 1px 2px 5px #b4b4b4;
    box-shadow: 1px 2px 5px #b4b4b4;
}

header[role="banner"]
{
    height: 80px;
}

header[role="banner"] > h1 > a
{
    background: transparent url(../images/brand.png) no-repeat;
    float: left;
    height: 50px;
    margin: 15px;
    padding: 0;
    text-indent: -9999px;
    width: 340px;
}

header[role="banner"] > nav
{
    float: right;
    font-size: 1.4em;
    list-style: none;
}

header[role="banner"] > nav ul
{
    margin-top: 50px;
    list-style: none outside none;
}

header[role="banner"] > nav li
{
    float: left;
    margin-left: 30px;
}

div[role="main"]
{
    border-top: 1px dotted #5d5a53;
    clear: both;
    margin-bottom: 20px;
    padding-top: 20px;
    overflow: hidden;
}

#featured
{
    background-color: #fdfcf7;
    border: 4px solid #e6e3d8;
    height: 300px;
    margin: 20px auto;
    width: 920px;
    /*CSS3 properties*/
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    -webkit-box-shadow: 0px 2px 5px #888;
    -moz-box-shadow: 0px 2px 5px #888;
    box-shadow: 0px 2px 5px #888;
}

#featured > figure
{
    float: left;
    /*CSS3 properties*/
    -moz-border-radius: 3px 0px 0px 3px;
    -webkit-border-radius: 3px 0px 0px 3px;
    border-radius: 3px 0px 0px 3px;
}

#featured > div
{
    float: right;
    height: 100%;
    padding: 0 10px;
    position: relative;
    width: 230px;
}

#featured > div h2
{
    font-size: 2.5em;
    font-weight: normal;
    margin: 5px 0;
}

#featured > div header + div p
{
    font-size: 1.75em;
    margin: 5px 0;
}

#featured > div header + div p + p
{
    font-size: 1.2em;
    margin: 0;
}

#featured > div header + div + div
{
    position: absolute;
    left: 5px;
    right: 5px;
    bottom: 10px;
    width: 230px;
}

#featured > div header + div + div a.order-button
{
    font-size: 2em;
    padding: 5px 0;
    text-align: center;
    width: 220px;
}

.product
{
    float: left;
    margin: 10px 12px;
    width: 215px;
}

.product h2
{
    font-size: 1.75em;
    font-weight: normal;
    margin: 0 0 5px 0;
    padding: 0;
}

.product > figure
{
    height: 250px;
}

.product > p
{
    margin-top: 2em;
}

.product > p > span
{
    float: left;
    font-size: 1.5em;
}

One of the thing that I find incorrect in the WebMatrix template Css3 styling is the ordering, rather than calling it incorrect let me call it as backward looking rather than forward looking, for example when declaring the styles they decide to put the standard declaration first then the browser extension, but the correct order should be the browser extension first then the standard declaration:

Backward looking:

border-radius: 4px; 
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
box-shadow: 1px 2px 5px #b4b4b4;
-webkit-box-shadow: 1px 2px 4px rgba(136,136,136, 0.6);
-moz-box-shadow: 1px 2px 5px #b4b4b4;

Forward looking:

-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
-webkit-box-shadow: 1px 2px 4px rgba(136,136,136, 0.6);
-moz-box-shadow: 1px 2px 5px #b4b4b4;
box-shadow: 1px 2px 5px #b4b4b4;

Now, lets see the other two pages, first the order page which show an order form, but the form does not have any html5 input types and attributes. The following shows the WebMatrix template version:

<form action="" method="post">
    <fieldset class="no-legend">
        <legend>Place Your Order</legend>
        <img class="product-image order-image" src="../Images/Products/Thumbnails/cupcakes.jpg" alt="Image of Cupcakes"/>
        <ol>
            <li class="email">
                <label for="orderEmail">Your Email Address</label>
                <input type="text" id="orderEmail" name="orderEmail"/>
            </li>
            <li class="shiping">
                <label for="orderShipping">Shipping Address</label>
                <textarea rows="4" cols="20" id="orderShipping" name="orderShipping"></textarea>
            </li>
            <li class="quantity">
                <label for="orderQty">Quantity</label>
                <input type="text" id="orderQty" name="orderQty" value="1"/>
                x
                <span id="orderPrice">5.99</span>
                =
                <span id="orderTotal">5.99</span>
            </li>
        </ol>
        <p class="actions">
            <input type="hidden" name="ProductId" value="3" />
            <input type="submit" value="Place Order"/>
        </p>
    </fieldset>
</form>

and here is the revised html5 version:

<form id="order" action="" method="post">
    <fieldset>
        <legend>Place Your Order</legend>
        <img class="thumbnail" src="/images/products/thumbnails/cupcakes.jpg" alt="Cupcakes"/>
        <ul>
            <li>
                <label for="email">Email Address:</label>
                <input type="email" name="email" id="email" placeholder="Type your email" required="required" autofocus="autofocus"/>
            </li>
            <li>
                <label for="address">Shipping Address:</label>
                <textarea rows="4" cols="20" name="address" id="address" placeholder="Type your address" required="required"></textarea>
            </li>
            <li>
                <label for="quantity">Quantity:</label>
                <input type="number" name="quantity" id="quantity" min="1" step="1" max="100" value="1" required="required"/>
                x <span id="price">9.00</span> = <output id="total" for="quantity,price">$9.00</output>
            </li>
            <li><button type="submit" class="order-button">Place Order</button></li>
        </ul>
    </fieldset>
</form>

As you can see that our revised version has some new input types like <input="email"/> and <input type="number"/> and attributes like placeholder, required, autofocus etc etc, but currently only few browsers has the support to take advantages of it, for example if I run it in Opera latest and click the place order with some invalid data it will show the following screen:

Opera html5 form

As you can see Opera does have the built-in support to validate the form, also it is showing the quantity input in an range input rather than plain textbox. I think the iPhone Safari also takes the advantages of html5 form. Though not all the browser has the support of these new values but the good news is it will automatically fallback to the plain old input type="text" even if these new values are used. Maybe in future I will show you how can use some intelligent scripting to trigger these client side features depending upon the browser it is running. One last thing I want to highlight in this form is that to show the total amount we are also using the new output element and to associate with the other elements that are involves in the calculation we are using the for attribute with comma separated values.

At the top of Order and Successful page some kind of wizard like interface is shown which indicates the current steps, I think the best way to code it if we use the new progress element. I this case, we will just wrap the ol with the progress. For example:

Order:

<progress value="2.0" max="3.0">
    <ol>
        <li><span>1</span>Choose Item</li>
        <li class="current"><span>2</span>Details &amp; Submit</li>
        <li><span>3</span>Receipt</li>
    </ol>
</progress>

Successful:

<progress value="3.0" max="3.0">
    <ol>
        <li><span>1</span>Choose Item</li>
        <li><span>2</span>Details &amp; Submit</li>
        <li class="current"><span>3</span>Receipt</li>
    </ol>
</progress>

The last page in the site is the About Us page which basically contains the history of the company and in the side bar a Twitter widgets that shows the result with bakery hash tag. The company history is the prime candidate for the html5 new article element and side bar as aside as it is showing related content with bakery, so the markup becomes:

<article id="about">
    <header>
        <h1>A little bit about Fourth Coffee</h1>
    </header>
    <p>
        Fourth Coffee was founded in 2010 and delivers coffee and fresh baked goods right to your door. 
        In another life, Bill Baker was a developer by day and pastry chef by night.  
        But soon Bill's innate skills with all things involving butter, flour and sugar put him 
        even more in demand than his programming talents and what started out as a way to satisfy 
        his own sweet tooth became all-consuming.  Fourth Coffee is not only a candy-coated wonderland 
        of coffee, pastries, cookies and cakes, it also honors his tech background by employing a state 
        of the art online ordering system that makes it easy for anybody with internet access to 
        order his all natural, locally-sourced confections and have them delivered to their 
        door within 24 hours.
    </p>
</article>
<aside>
<!-- Twitter Widgets goes here -->
</aside>

That’s it for today. As you can see that writing meaningful and clean markup is not only a fun but also an art. In my next post, I will discuss about the Microsoft Webpage that are bundled in the WebMatrix and alternate frameworks that are available in the other platforms, so stay tuned.

Shout it

1 Comment

  • hello
    I browsed this article by accident because i was looking for internet solutions to create an elearning category for
    my fellow readers who are lookings for online lfrench courses...thanks for that post, i saved your site address and will be back to check it out some more later
    Regards

Comments have been disabled for this content.