The Actual Browser Problems with Unquoted Attributes

Chris Coyier //

In HTML (4, 5, whatever) quoting attribute values is optional, kinda. Both of these are totally fine:

<b class=boom>
<b class="boom">

But there are rules and limitations. Hopefully obviously, this is a problem:

<a title=Hi, mom! href=#>

That space in Hi, mom! is the problem. The browser will think the value of the title is Hi, and think mom! is an attribute onto itself. Any whitespace-like character will cause this problem. Mathias Bynens created a tool called the Mother-effin’ unquoted attribute value validator, a simple tool for evaluating a possible attribute value to see if it's valid or not.

The problem characters are: spaces, tabs, line feeds, form feeds, carriage returns, ", ', `, =, <, or >.

The Actual Problems

So those are the rules, but what happens if you actually break the rules? Using some of those characters in unquoted attributes can cause serious problems. Others do not. And some characters not referenced in those rules cause problems.

Let's just look at a bunch of them.


<div rel></div>
<div rel=></div>

Not valid, but not a big deal in any browser. Just sees the rel attribute as present but empty.


<div rel==></div>

Not valid, but works in every browser. Rel attribute seen as "=".


<div rel=&></div>

Rel value seen as "&" in all modern browsers including IE 9 and 10. IE 6, 7, and 8 see empty value, except when accessed through CSS (e.g. content: attr(rel);) in which the value is seen as "&"


<div rel=&a></div>

Rel value seen as "&a" in all modern browsers including IE 9 and 10. IE 6, 7, and 8 sees value as "a".


<div rel=a&b></div>

Rel value seen as "a&b" in all modern browsers including IE 9 and 10. IE 6, 7, and 8 see the value as "a".


<div rel=a&amp;b></div>

In this example the ampersand is encoded. Modern browsers including IE 9 and 10 see the value as "a&b" (same as leaving it unencoded). IE 6, 7, and 8 also behave the same as the last test, truncating the value to only "a".

Seems like IE 6, 7, and 8 don't freak out about ampersands in attribute values, but will truncate the value at the point they first see one (unless it starts with one, then everything after it and until the next one).


<div rel=`></div>

All versions of IE (even 10) have problems here. They treat the backtick character as a quote, so by only using one of them, it's like the entire rest of the document until the next quote is part of the value of the attribute. All other browsers have no problem as see the value as "`".

<div rel=```></div>

This is similarly problematic, because there is an odd number of backticks, it leaves a set of quotes open. All non-IE browsers see the value as "```".

<div rel=``></div>

This is slightly less problematic because what IE sees as quotes are closed. Non-IE browsers see the value as "``".


<div rel=<></div>

Modern browsers, including IE 9 and 10, see the rel attribute value as "<". IE 6 and 7 see the value as blank, but no big disasters ensue. IE 8 sees the value as blank through JavaScript but sees the value as "<" through CSS (e.g. content: attr(rel);).


<div rel=>></div>

Here we're attempting to set the value to ">", but what's actually happening is that we're creating a div with an actual ">" inside it. Another way to see that is:

<div rel=>
  >
</div>

The rel attribute, in every browser, will be blank.


<div rel={@#():,*!![[]]}></div>

This looks weird, but none of these characters are problematic and no browser has any problem with that.


<div rel='></div>
<div rel="></div>

This is problematic in any browser (single or odd numbers of quotes). Similar to the backtick situation only all browsers understand quotes and quotes. This is world-crashing-down problematic, as the entire rest of the document until the next quote is seen as a value of that attribute.


In this article "modern browsers" generally refers to Safari 5.0, Firefox 4, Chrome 12, and Opera 11. IE are generally listed by version. "All browsers" refers to what I listed for modern browsers plus IE 6-10. Some of what I used for testing is at this JS fiddle, which can be easily altered as needed for more tests. No JS libraries were used.

Also see Mathias' in-depth article on the subject, which covers using them in CSS as well.

The moral of the story: if any of this is confusing to you, just quote all your attributes.