31

What are the reasons that people seem to prefer techniques such as SMACSS for namespacing, over actual css namespaces?

I've googled this for a bit, but I've been unable to come up with any good resources. (It makes me worried that either my google-fu is crap (very likely) or the css namespace spec is useless (less likely))

John Slegers
  • 45,213
  • 22
  • 199
  • 169
Marcus Stade
  • 4,724
  • 3
  • 33
  • 54
  • 3
    I don't even see it on [When Can I Use?](http://caniuse.com/) and I don't think any browser even partially supports it... – Dominic Barnes May 22 '12 at 13:45
  • 1
    @DominicBarnes — It is at Recommendation status, that means there must be at least two independent implementations of it. – Quentin May 22 '12 at 13:47
  • 2
    @Dominic Barnes: Actually, every modern browser supports it, including IE9+. I recently answered a question about CSS namespaces, which contains code you can use to verify that it works: http://stackoverflow.com/questions/9490155/trouble-getting-declared-namespaces-to-work/9491691#9491691 The main reason I suspect for CSS namespaces not appearing on that site is because there aren't many real-world use cases for it in today's Web industry, since HTML5 is the cool new thing now, which doesn't use namespaces in any way. – BoltClock May 22 '12 at 13:50
  • 2
    Well, `xmlns` apparently doesn't make much sense in html5. @Quentin's answer lead me to the relevant part of the spec (section 3.2.3, edited his answer to include this) that explains that the attribute is essentially only there for compatibility with XHTML parsers. – Marcus Stade May 22 '12 at 14:08

3 Answers3

29

They cover completely different use cases.

CSS namespaces are for applying CSS to XML documents that mix elements from different XML namespaces. e.g. so you can target <foo:p> and <bar:p> without confusion.

SMACSS covers techniques for writing robust CSS that doesn't interfere with other parts of the page. e.g. so that .title in your address book HTML doesn't get muddled with .title in your list of publications HTML.


Further details from the spec:

Note: In HTML, the xmlns attribute has absolutely no effect. It is basically a talisman. It is allowed merely to make migration to and from XHTML mildly easier. When parsed by an HTML parser, the attribute ends up in no namespace, not the "http://www.w3.org/2000/xmlns/" namespace like namespace declaration attributes in XML do.

Marcus Stade
  • 4,724
  • 3
  • 33
  • 54
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • 3
    @xiaoyi — HTML doesn't have namespaces. – Quentin May 22 '12 at 13:48
  • 1
    HTML do have namespaces. Like using embed svg, and other use cases. – xiaoyi May 22 '12 at 13:49
  • 1
    @xiaoyi: No, HTML doesn't have namespaces, because HTML is not XML. You're probably talking about XHTML, which *is* based on XML. – BoltClock May 22 '12 at 13:51
  • 2
    @xiaoyi — The HTML 5 rules for embedding SVG don't use namespaces. A mixed XHTML / SVG document deals only in XML. – Quentin May 22 '12 at 13:51
  • 1
    @Quentin But when interact with embed SVG, you have to use .createElementNS, .setAttributeNS, with explicit namespace settings. otherwise it won't work. – xiaoyi May 22 '12 at 13:53
  • 1
    Thanks for your answer @Quentin, it guided me to the relevant parts of the spec that explains that `xmlns` is virtually useless in html. I've edited your answer to include this, and accepted it. – Marcus Stade May 22 '12 at 14:05
5

Namespaces have a rather nasty syntax in CSS, because the ":" namespace character must be escaped by a leading backslash to differentiate it from a pseudo-class:

html\:img {
  border: 2px solid black;
}
html\:a:visited html\:img {
  border-color: grey;
}

This is only really useful when embedding HTML inside an XML document. When adding the html namespace, elements from the HTML namespace are correctly displayed as they would appear in HTML, allowed access to capabilities that are not yet provided by CSS.

<story xmlns:HTML="http://www.w3.org/Profiles/XHTML-transitional">
  ...
  <restaurant>
    <name>Red Apple Inn</name>
    <logo>
      <HTML:A href="javascript:alert('Visit the Red Apple Inn!')">
        <HTML:IMG src="red-apple.gif" height="50" width="200"/>
      </HTML:A>
    </logo>
    ...

In an HTML5 context, I can't think of any cases where you would need this. The only place where I've seen namespaces in CSS so far, is Webkit's default CSS for SVG or MathML, and they use a different syntax : the @namespace at-rule.

For example, this is code from WebKit/webkit/blob/master/Source/WebCore/css/mathml.css :

@namespace "http://www.w3.org/1998/Math/MathML";

math {
    -webkit-line-box-contain: glyphs replaced;
    text-indent: 0;
    direction: ltr;
}
mtext {
    line-height: 1.0;
}

...

This is code from WebKit/webkit/blob/master/Source/WebCore/css/svg.css :

@namespace "http://www.w3.org/2000/svg";
@namespace html "http://www.w3.org/1999/xhtml";

svg:not(:root), symbol, image, marker, pattern, foreignObject {
    overflow: hidden
}

svg:root {
    width: 100%;
    height: 100%
}

text, foreignObject {
    display: block
}

...
John Slegers
  • 45,213
  • 22
  • 199
  • 169
0

It's too much hassle to get working. Browsers that parse HTML stick everything into the default namespace with the exception of some tag names (eg: svg). That said you can create an element within a special namespace:

<html>
<head>
  <style>
    @namespace foo "http://foo";
    foo|div { color: red; }
  </style>
</head>
<body>
    <div>I'm an HTMLDIVElement</div>
</body>
<script>
  const div = document.createElementNS('http://foo', 'div');
  div.textContent = 'I am namespaced.';
  document.body.appendChild(div);
</script>
</html>

As far as I know, there's no way for the HTML parser to pick another namespace for you. Any element created by the browser's HTML parser is created in the default namespace. Also, once you escape the HTML namespace, they're no longer HTMLElement elements. You can't just use the tagname of button and expect it to be an HTMLButtonElement with all the stylings, interactions, and properties. That also means means no HTML properties like .innerText, .dir, .offsetTop, etc. And the biggest one is no .style. That also means setting a style attribute does nothing. You must specify all your styles in the CSS file.

This really mean this is just for really limited XML contexts and really not meant for general HTML content. There might be a way to make your components implement HTMLElement, though I haven't found one (maybe Web Components?). Still, that would mean all your elements must be constructed with document.createElementNS which is probably far more work than finding another way to scope your CSS components.

ShortFuse
  • 5,970
  • 3
  • 36
  • 36