I’ve recently the been letting go of my blind faith in page-wide semantic HTML. Today I found this old post from Jeff Croft describing the myth of content and presentation separation in HTML and CSS, which provides a realistic layman’s take on the situation: semantic HTML is too hard.
While I agree with that sentiment 100%, I’ve also been wondering why semantic markup is too hard and realized it’s because the semantic HTML paradigm is too weak to support a modern web experience.
Blueprint likes to do things like throw a date string into a div with a class of
span-14. Those classes become layout macros, allowing a designer to create and edit a page design very quickly. (Jeff Croft is one of Blueprint’s progenitors.)
But those display-rules-as-classes are a bad bad bad commingling of content and markup, according to a semantic HTML purist. Like other purists, I once believed that people should lose a digit for using divs outside of defining headers, content, sidebars/navs, and footers. And spans? They’re basically an admission of semantic defeat.
Like Jeff, I found that philosophy led to 3 challenges in real life:
- It’s nearly impossible to build a web UI without some non-semantic markup.
- Purely semantic markup often requires a lot more work from the CSS, which can bloat files.
- As a result of the previous points and some other stuff, nearly-pure semantic markup can take a long time to build.
At a certain point, pragmatism takes over: is it worth paying someone to spend extra time building bloated CSS in the name of “future compatibility”? And if it’s so hard, does that indicate some deeper flaw in the semantic HTML model?
Consider the classic argument for semantic markup and forwards compatibility: the mobile device. Shouldn’t that be solved in a stylesheet’s media attribute? Or ignored altogether, as the iPhone presages full browsers one mobile devices (yay, death of WAP).
Here’s a more nuanced take on the whole “semantic HTML or die” philosophy:
- Keep markup purely semantic for a web UI’s document component. No divs, no spans, no class=”left”. JS probably shouldn’t touch the document interface, except for typographically-oriented functionality like increasing font sizes.
- Use functional markup for a web UI’s application components. Recognize that you’re building chrome from deeply intermingled HTML, CSS, and JS. Put hooks as necessary within the HTML.
Headers, navs, footers, and forms all fall within the application UI camp. Basically, anything that’s in a CMS’s app/template. From a user’s perspective, a website nav is little more than customized browser chrome, living alongside the browser’s location box and back button. With search and dynamic taxonomies exploding content hierarchies, it makes less and less sense to say a nav “should” be expressed as a list. Suckerfish dropdown menus and similar CSS wizardry are interesting because they manage to overcome the constraints presented by HTML, not because they’re elegant or appropriate.
The document UI components should only include the page text – what typically lives in the “content” div and is stored in the CMS database. When people talk about forward compatibility, this is most of what they should consider anyway – the data. This is what HTML was originally designed to represent: text, read and clicked. Keep this interface code semantic.
(Readability is a great browser plugin that hides all of a website’s application UI components, leaving only the document content – it’s a beautiful thing.)