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?

Runnick
  • 205

2 Answers2

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.

  • 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 '17 at 23:21
  • @pllee good catch. Seems like you still need to prefix your "scopes" too. – Runnick Jun 26 '17 at 06: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. – Arseni Mourzenko Jun 26 '17 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 '17 at 15:07
  • you shouldn't use IDs https://github.com/airbnb/css#id-selectors – SandroMarques Apr 02 '18 at 19:45
  • @SandroMarques that link seems to be saying "don't make thing very specific, it's harder to reuse", totally ignoring when you want that specificity, exactly because you are not reusing those parts of the styling – Caleth Apr 03 '18 at 10:23
  • @ArseniMourzenko does a good job summarizing this, because as long as CSS does not provide a mechanism for "scope", this issue will continue to exist. Currently the only way to truly accomplish what you want is to 1) decide on and enforce a CSS naming convention in your project (like BEM) and 2) take the time and effort to convert all 3rd party libraries used in the project to your chosen naming convention. If you choose a common convention like BEM then you can also try to choose 3rd party libraries that use BEM. – Tyson Gibby Feb 01 '20 at 22:37
1

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

  • 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 '17 at 06: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. – Tyson Gibby Feb 01 '20 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. – Tyson Gibby Feb 01 '20 at 22:26