14

As far as I know there are two types of CSS namespacing:

Prefix one:

.myapp-alert {...}

and class one:

.myapp .alert {...}

Which one is preferable? Does one has benefits over the other one? Are there any other?

0

2 Answers 2

17

There are no namespaces in CSS. All you do in CSS ends up in global scope. This is by design.

This leads to two problems:

  • What happens to the apps using my library if, in the library, I introduce a given style?

  • What happens to other parts of my 100M-LOC app if I introduce a given style in the part I'm working on?

Those are two distinct situations, which can be handled with two distinct techniques you described in your question.

Prefixes work well for libraries and frameworks. If a framework has an alert icon, this icon may appear anywhere in the page. Thus, you can't just scope the style to a particular element (through class/id selector). This leads, indeed, to the selectors such as:

.my-awesome-framework-icons-alert { ... }

The choice of the prefix is, by the way, important in order to avoid collisions. Popular libraries and frameworks can use small prefixes, knowing that websites that use them will adapt themselves. For instance, a website which uses AngularJS will probably not use ng- prefix for its custom elements. Small libraries, on the other hand, would be better using more esoteric names if they want to be easily integrated within existent projects.

Containers, on the other hand, work well for app components. I don't want all the styles on my About page to be prefixed by about-page-. I would rather create an element <div id="about"> and use that as a scope for the styles which are used on About page only.

Using CSS preprocessors such as LESS, such code avoids much of the duplication compared to prefixes. I simply do:

#about {
    .contact { ... }
    .map { ... }
    ...
}

and let the preprocessor duplicate #about for every relevant style.

7
  • 2
    Good writeup, one negative about your container approach is that a different framework's .map class could add unwanted styles to #about .map. It really depends on how much you care about protecting against 3rd parties or other internal code on the same page.
    – pllee
    Jun 25, 2017 at 23:21
  • @pllee good catch. Seems like you still need to prefix your "scopes" too.
    – Runnick
    Jun 26, 2017 at 6:37
  • @pllee: unless I misunderstood your comment, this is exactly why third party libraries should use prefixes. So not .map, but .one-more-js-lib-map. Jun 26, 2017 at 11:35
  • @ArseniMourzenko yeah they should but they don't always. Also other "internal" widgets can forget to namespace as well.
    – pllee
    Jun 26, 2017 at 15:07
  • you shouldn't use IDs github.com/airbnb/css#id-selectors Apr 2, 2018 at 19:45
1

We use BEM (block element modifier) to solve the problems in CSS that namespaces solve in other languages. http://getbem.com/introduction/

3
  • I don't think BEM solves all the problems, because if other library also uses BEM, it may still break things. You'll probably name things in similar fashion. E.g. if .card .media turns into .card__media it doesn't prevent other developer to name their cards same.
    – Runnick
    Jun 26, 2017 at 6:38
  • @Runnick, it is important to note here that CSS doesn't really stop you from doing anything. It is not a "strongly typed" language with strict rules like C++, Java or .C#. This means that no matter what you decide to do, it is only a convention you are deciding to use and there is no enforcement of the convection by a compiler. The "Block" in BEM structure is literally designed to be a "namespace" in the CSS, but you are in charge of following and enforcing it. Feb 1, 2020 at 22:17
  • @Runnick, if you are looking for something that "enforces" rules for you. The SASS pre-processor (kind of like a compiler for CSS) as Arseni Mourzenko suggests in his accepted answer, might be the best way for you to do that. Feb 1, 2020 at 22:26

Not the answer you're looking for? Browse other questions tagged or ask your own question.