Advertisement

HTML5 Globals and You

by
This post is part of a series called HTML5 and You.
The Official Guide to HTML5 Boilerplate
Rethinking Forms in HTML5

Much has been written on the big ticket changes in HTML5, like forms, semantics, and media, but information on the less splashy changes is sparse. While global attributes aren't the most sexy change of HTML5, they are the change that you will be using over and over and over as you migrate to the new specification.


Introduction: What is a Global Attribute?

While the term attribute relating to HTML might be a bit fuzzy to you, you certainly use them with almost every element that you write. HTML attributes give elements meaning. They also give context. They are both the adjective and verb for an element, if you think of the element as the noun. For instance:

    <div></div>

Doesn't really have much meaning. It's a division of the page, and that's it. When we add an attribute though, it does have meaning:

    <div id="foo" class="bar" style="color: red" title="FooBar To The Rescue"  dir="rtl" lang="en-US" tabindex="1" accesskey="F"></div>

We now have a division that is "Foo" with a class of "Bar", which has a color of red, a title of "FooBar to the Rescue", is displayed right to left, is to be read in US English, and when you press the tab button or "F", it's the first element to have focus. It's basic, I know. The attributes are all those things that give elements meaning. The difference in HTML 5 from previous versions of the specification is there are attributes that can be used on any HTML element. These are now global attributes. Beyond the ones illustrated in the example above, there are some new ones that are global as well which will expand the possibilities beyond just boring peanut butter.

"HTML attributes give elements meaning. They also give context. They are both the adjective and verb for an element, if you think of the element as the noun."


Common Attributes: Which Ones Are Now Global?

This is a relatively minor change in HTML 5. The attributes id, class, style, title, dir, lang, accesskey and tabindex are now valid attributes to have on any HTML element. You want to give a meta tag an id, that's valid now. It's even valid to give that same meta element a direction, language, class or any global attribute for that matter. While they might not have meaning at first blush, it's perfectly valid to define them in any tag that you feel necessary.

    <meta name="description" content="FooBar, making me feel like it is actually FUBAR." id="foo" class="bar" style="color: red" title="FooBar To The Rescue"  dir="rtl" lang="en-US" tabindex="1" accesskey="F">

The above example is perfectly valid in HTML5. That said, where there is no reason to use an attribute, and it looks silly, perhaps the best course of action is to not use that global attribute. A tabindex on a head element might not be the best use of time and energy. The important part to understand is not the odd case of putting a global attribute in something that doesn't quite make sense, but rather the fact that they are available in any element.

Each of these was common attributes in the past, and while their use were restricted somewhat in the past, you probably already thought of them as global. I actually had to look up id, because I couldn't think of an element that you couldn't use it (base, head, html, meta, script, style, title). The old common attributes are just half of the new global attributes though.


Edit Inline: The Contenteditable and Spellcheck Attributes

The first of the new attributes to look at are contenteditable and spellcheck. They are not mutually exclusive and you can use one without the other, but for the purposes of illustration, it makes sense to look at them at the same time. Both of these attributes do what their names imply; they allow an element to be editable (contenteditable) or allows / disallows spellcheck on content. Let's start with contenteditable:

Let's look at number handling first:

    <article id="id">
        <p>You can not edit this paragraph.  I am happy, and and just sit here with no regrets.</p>
        <p contenteditable="true">This paragraph you can edit.</p>
    </article>

In this snippet, we have one paragraph which is not editable, and one that is. When you click on the non-editable paragraph, it works as you would expect by highlighting a word, etc:

However, when you click in the editable portion a whole new world opens:

The paragraph now becomes editable simply by adding the contenteditable attribute. It gets even cooler when we start using the contenteditable with multiple elements. Let's look at a larger snippet and see what happens.

    <article id="edit_test"  contenteditable="true">
        <header>
            <hgroup>
                <h1>Let's See What Happens</h1>
                <h3>Does every element become editable?</h3>
            </hgroup>
        </header>
        <p>You can edit this paragraph now.</p>
        <p>You can edit this paragraph as well.</p>
    </article>

We start with something that looks like this:

When we focus the article element though, we have the entire span editable:

Furthermore, we can style the box (for lack of better term) using the CSS3 pseudo class of :focus

    #edit_test:focus { background: #eee; padding: 1%; }

and it will look something like this:

>

Final notes about contenteditable: there are three basic conditions that it takes: true, false, inherit. You can nest contenteditable conditions with nested tags. For instance, if we do something like:

    <article id="edit_test"  contenteditable="true">
        <header>
            <hgroup contenteditable="false">
                <h1>Let's See What Happens</h1>
                <h3>Does every element become editable?</h3>
            </hgroup>
        </header>
        <p>You can edit this paragraph now.</p>
        <p>You can edit this paragraph as well.</p>
    </article>

We would be able to edit the paragraphs in the article, but not the header group. Since this is a global attribute, you could theoretically add contenteditable to your body element, and then pick and chose the elements which are not editable in the document.

The spellcheck attribute goes along with the contenteditable, but it also can be used where your user might interact with your document, for instance, with forms. The spellcheck attribute is assumed on, unless you say otherwise:

    <article id="edit_test">
        <header>
            <hgroup>
                <h1>Let's See What Happens</h1>
                <h3>Does spellcheck work?</h3>
            </hgroup>
        </header>
        <p spellcheck="false" contenteditable="true">Spell check off.</p>
        <p spellcheck="true" contenteditable="true">Spell check is on.</p>
    </article>

As you can see, when we have the spellcheck set to false, we do not get an indication of a misspelled word, but with it set to true, we do. It's a very simple, but helpful functionality. From my tests, browser implementation is a bit raw, but it does work now.


Adding Behavior: The Hidden Attribute

Another new global attribute is hidden. It basically does the same job as "display: hidden" does with CSS, but within an element. The advantage to this, it gives a semantical meaning to the element that it is not relevant at this moment in time. Therefore, screen readers, etc., would not mention the element in the hidden state when it would with a style of "display: hidden," since that is dealing with its presentation. It is a boolean attribute, therefore, false is the assumed state and you only need to add the attribute name to the element that you wish to hide.

    <article id="hide_test">
        <header>
            <hgroup>
                <h1>Let's See What Happens</h1>
                <h3>Can we hide elements?</h3>
            </hgroup>
        </header>
        <p>We can see this paragraph</p>
        <p hidden>We can't see this paragraph</p>
    </article>

Dragging Elements: The Draggable Attribute

HTML5 implements a new "Drag and Drop" API. While the specifics of the API are a bit out of the scope of this tutorial, the attribute to allow something to be dragged is not. Any element that has draggable set to true, can be dragged:

    <article id="drag_test">
        <header>
            <hgroup>
                <h1>Let's See What Happens</h1>
                <h3>Can we drag elements?</h3>
            </hgroup>
        </header>
        <p draggable="true">We can drag this paragraph.</p>
        <p draggable="false">We can't drag this paragraph</p>
    </article>

Without any JavaScript, you can see the difference in browsers that support draggable. When set to false, if you mousedown over the element it will begin to highlight the text; however, when set to true it does not. In Chrome you get the drag icon, whereas in Firefox you just don't get the highlight of the element. Either way, the browsers are trying to do something with these elements.


Saving Space With Menus: The contextmenu Attribute

The contextmenu attribute allows you to display a menu without taking up valuable UI space for the menu. It is a menu which fires on events, such as mouseup or keyup providing a bubble menu which provides options and actions based on those selections.

    <article id="contextmenu_test">
        <header>
            <hgroup>
                <h1>Let's See What Happens</h1>
                <h3>Can we give a context menu?</h3>
            </hgroup>
        </header>
        <p contextmenu="foo">This paragraph has a context menu called "foo" attached.</p>
    </article>
    <menu id="foo">
        <command label="Step 1: Write Tutorial" onclick="doSomething();">
        <command label="Step 2: Edit Tutorial" onclick="doSomethingElse();">
        <command label="Step 3: ..." onclick="youGetTheDrift();">
    </menu>

In this example, there are a few more things going on with contextmenu that are new. For instance, a menu must be defined, so that the contextmenu knows where to point. In the example above, we are saying, when there is a mouse event (depending on browser implementation), go out and find the menu "foo" in the DOM, and display its commands. The syntax is relatively simple after that. We have a menu label which will display the attribute text, and we have an onclick event which will do whatever we have defined.


The Catch-All: The data-* Attribute

When you add ambiguity to a specification, it tends to be misused, when there are better options available.

I have saved the most controversial global attribute for last. I have mixed feelings with this new one. On one hand, I am looking forward to the ability to connect my logic layer with my behavior layer without going through too many hoops, or using attributes and elements outside of their design specs. On the other hand, I know that when you add ambiguity to a specification, it tends to be overused and misused when there are better options available.

What this attribute is, is a catch-all. Basically, the specification is stating that we can not ever think of all of the use-cases for attributes, therefore we will leave you to your own to make them up. The logic in me feels a specification should give us a set of rules to play with, and leave it at that, but the innovator in me loves having the power to define new attributes. I just know from experience when there is a chance to do something not quite right, but easier, that path generally bites you in the behind. All that said, let's keep it positive and look at a couple of possible cases.

I think this attribute will be a wonderful addition for microformats, and might be the thing that puts them in the forefront of development. I can also see some uses where on the backend, I want to provide some bread crumbs to my behaivor layer in JavaScript to close some gaps. Another idea where you might use this attribute is to provide a location for where you are when you post an article. That might look something like this:

    <article id="data_test" data-latitude="38.254" data-longitude="85.72">
        <header>
            <hgroup>
                <h1>Post From Louisville, KY</h1>
                <h3>Waterfront Park Concert</h3>
            </hgroup>
        </header>
        <p>I've just attached a post from Waterfront Park in Louisville, KY.</p>
    </article>

I can now take those data-* attributes and do something via JavaScript or another API, such as post a map, from attributes from my application layer. It ends up opening a ton of possibilities, but don't forget the immortal words of Ben Parker: "With great power, comes great responsibility."


Conclusion

Like most things in HTML5 at the moment, the browser support for these changes are spotty at best. Some new attributes are supported. some are incorrectly implemented, some have no support at all at the moment! That said, they all appear to degrade nicely without much hoopla involved, so there isn't a compelling case to not begin experimenting and implementing. The specification changes are slowing, so more than likely, what you see is what you will get...at some point. Thanks for reading!

Advertisement