Coding in Paradise

About Brad Neuberg

Making EPUB3 Play Nice with HTML5

Photo by adrigu

Last week I wrote about how EPUB3 is important even in an HTML5 universe. Today I want to write about how to make EPUB3 play nice with HTML5; as it turns out there are some significant problems when you try to use EPUB3 in HTML5.

The Problem

Before I jump in, I want to mention that there are actually two different flavors of HTML5:

Tag soup HTML5 dominates the open web; it's probably 99.9% of all the content you would access with a conventional web browser

EPUB3 allows you to use XHTML5 in your eBooks. In fact, it's built above a feature of XML known as XML namespaces. XML namespaces allow you to declare your own custom elements and attributes by registering a namespace. For example, in the following markup we declare the EPUB3 XML namespace, and then use it on custom attributes (epub:type) to indicate a footnote reference and its definition:

<body xmlns:epub="http://www.idpf.org/2007/ops">
    <p>something <a epub:type="noteref" href="#fn01">1</a></p>
    …
    <aside id="fn01" epub:type="footnote">
        Some footnote content
    </aside>
</body>

There's just one huge crucial problem with this: tag soup HTML5 does not support XML namespaces in any way. In fact, XML namespaces as a mechanism for extending HTML5 are pretty much a deprecated avenue for extending HTML.

The fact that EPUB3 is built above XML namespaces creates incredible problems when trying to use it in an HTML5 situation. I'll touch on some of these problems in a minute, but first why would you ever want to use EPUB3 with tag soup HTML5?

The fact that EPUB3 is built above XML namespaces creates incredible problems when trying to use it in an HTML5 situation

First, the future is creating high quality markup in HTML5 and then publishing it into different channels. Imagine you are a publisher creating medical texts for the education of doctors. One of the channels you would publish your material in would be as an eBook; another would be publishing it to a site that might require a subscription service; a third would be to bundle assessments along with this material and sell them as bite sized chunks as part of a learning management solution.

EPUB3 is only part of this world, not all of it, one channel to place your material in but not the only one.

Imagine you want to create HTML5 that uses EPUB3 footnotes and then flow it into the other channels mentioned above at some point. Most of the non-EPUB3 channels will be tag soup HTML5. Creating EPUB3 footnotes mostly involves using the epub:type attribute, as shown in the example markup above.

Using epub:type in tag soup HTML5 immediately has the following problems:

You are stuck; you simply can't use EPUB3 features in a tag soup HTML5 solution. You can't even create JavaScript or systems to help polyfill in EPUB3 features, as they can't even touch the EPUB3 elements on the page. Why not just serve XHTML5 everywhere then? It's difficult to serve XHTML5 on the open web: XHTML renderers in web browsers tend to be not as well supported; have bugs that take longer to get fixed; are slower since they don't get much attention; have failure modes that generally cause a scary code-filled error page to be shown to end-users; and crucially don't support document.write, which many third-party JavaScript widgets depend on in order to insert themselves, including widgets from Google, Facebook, Twitter, etc. It's also not well supported by open source JavaScript libraries like JQuery.

Photo by adrigu

The Solution

There is a very simple solution that will solve this problem in the future: change epub:type to epub-type. Basically, instead of using XML namespaces, simply prefix your custom attributes and element names in EPUB3 with a dash. Here's that same example shown earlier but using dashes instead of XML prefixes:

<body>
    <p>something <a epub-type="noteref" href="#fn01">1</a></p>
    …
    <aside id="fn01" epub-type="footnote">
        Some footnote content
    </aside>
</body>
There is a very simple solution that will solve this problem in the future: change epub:type to epub-type

Now, you can easily style these using CSS in tag soup HTML5 (example) and easily grab them using querySelector or XPath. No more problems.

[epub-type~=footnote] {
    border-style: dashed;
    color: blue;
}

It seems like epub:type is the one aspect of EPUB3 that is actually getting uptake; changing this to allow epub-type would have a huge effect on being able to use EPUB3 in more situations.

If there's one take away from this article, it would be for the IDPF to adopt epub-type instead of epub:type. The ARIA working group, which created attributes to aid layering accessibility information into HTML for tools such as screen readers, did exactly this: they went from aria: to aria- so it could be used in tag soup HTML5, such as aria-labelledby instead of aria:labelledby.

What about using epub- instead of epub: for other EPUB3 elements?

Before moving on, if I haven't made it clear yet, the most important thing to take away from this article is:

epub:type should be redefined to epub-type!

Another Alternative

epub:type should be redefined to epub-type

An interesting future possibility is to replace epub-type in general in the future with RDFa Lite. This could be as simple as using the typeof and rel attributes as follows:

<body vocab="http://www.idpf.org/2007/ops">
    <p>lorum ipsum. <a rel="noteref" href="#fn01">1</a></p>
    …
    <aside id="fn01" typeof="footnote">
        Some footnote content
    </aside>
</body>

Pretty straightforward and easy.

Photo by adrigu

Update: Romain Deltour shared a workaround with me that allows epub:type to be styled in tag soup HTML5. You basically have to escape the colon. This allows CSS and querySelectorAll to work. Here's a test and some sample code; note that even though this works its a bit janky; it's still not a great idea to have EPUB be built above facilities that tag soup HTML5 has formally deprecated (XML namespaces):

<!DOCTYPE html>
<html>
    <head>
        <style>
        [epub\:type~=footnote] {
            color: blue;
        }
        </style>
        <script>
            window.onload = function(){
                var node = document.querySelector('[epub\\\:type~=footnote]');
                alert(node);
            };
        </script>
    </head>
    <body>
        <h1 epub:type="footnote">This tests epub:type; this file is tag soup HTML5. This H1 has an epub:type="footnote" attribute on it. If the CSS selector works, this should be blue and you should see an alert box that fetched the element from the page using querySelector as well.</h1>
    </body>
</html>

Subscribe to my RSS feed and follow me on Twitter to stay up to date on new posts.

Please note that this is my personal blog — the views expressed on these pages are mine alone and not those of my employer.

Back to Codinginparadise.org