I've just read Scalable and Modular Architecture for CSS and it's got me thinking about a few things. Snook's two principle tennets are:
So this means using semantic class names rather than relying on unsemantic element types for targeting. For example rather than targeting .someClass h5
, I might target .someClass-title
instead so that if the h5 is swapped out for something else, things don't break.
Personally I find encoding an element's hierarchy in its name kind of unpleasant (even if it is semantically correct). I would prefer doing .someClass .title
. But to use a class as generic as title you need to accept that this class will be used in lots of different contexts.
So is there anything wrong with using the same class in completely different contexts if I know it will be namespaced by a previous item in the selector?
For example say I have three different places in my site where a class of 'title' makes sense:
HTML
<header class="pageHeader">
<h1 class="title">Some Title</h1>
</header>
...
<article class="leadArticle>
<h3 class="title">Some Article Title</h3>
</article>
...
<ul class="productPreviews">
<li class="product">
<h5 class="title">Some Product Name</h5>
</li>
</ul>
CSS
.pageHeader .title
{
}
.leadArticle .title
{
}
.productPreview .product .title
{
}
Edit: as Alohci mentions in his answer below, a header tag isn't unsemantic, so perhaps this wasn't the best example to use.
Obviously I might be doing something completely different to the title in these contexts, but title makes absolute sense with it's module's namespace, and I never have any intention of using title as a general selector.
This seems to tick all the boxes. It is semantically rich, completely decoupled from implementation. For example if the last example was changed into an ol or a stack of divs, nothing would break, and if title was wrapped in a div it would still be targeted.
This makes sense to me, but I haven't seen this approach used much and I'm wondering why. An obvious disadvantage is that you are chaining classes in the selector, but I think this is preferable to namespacing each classname.
I prefer using a class like .title rather than selecting just the h5 element, as I feel it decouples the HTML from the CSS some more. If, for whatever reason, you decide an h4 or and h6 is more appropriate for the document outline, or some other element/reason, you would have to refactor your CSS if you are selecting the element(h5) vs select a class(.title).
This is why I prefer to class ALL THE THINGS vs. element selectors because the markup may change over time. If your working on a smaller site that isn't seeing many updates, this may not be a concern, though it's good to be aware of.
As far as if there is anything wrong with using the same class in completely different contexts if you know it will be namespaced by a previous item in the selector, I have mixed thoughts on it.
On one side, some concerns come to mind, for instance the use/meaning/role of .title could be empty without it's parent selector. (.pageHeader .title) While I think that .title is a perfectly fine class name, it may be difficult for other devs to understand it's meaning comes from a parent selector like .pageHeader .title
Another concern is if you are using the class .title for multiple instances of "titles" in a module, you can run into issues. The basic idea is that the local scoping descendant selectors provide can sometimes be too restricting if trying to stretch the reusability of .title within the module. I set up a code demo to show what I'm talking about here.
On the other side, descendant selectors are one of the most used selectors, specifically for their scoping purpose.
Tim Murtaugh, who is one of the developers (not sure if he is the lead dev or not) for A List Apart uses descendant selectors for the majority of his styles on his personal site.
I've recently been exploring this and BEM and would agree with your conclusion, "this is preferable to namespacing each classname."
I prefer .pageHeader .title{...} vs. .pageHeader__title{...} but there are always instances where one approach may be more beneficial in a situation over the other.
As with most things, it depends, but I think if you don't let the nesting go too deep and are thoughtful with how you use them, descendant selectors are powerful and good solution for providing locally scoped styles while also offering a solution for globally scoping styles.
For example:
/* Globally scoped styles for all .title(s) */
.title{
font-family: serif;
font-weight: bold;
}
/* Locally scoped styles for individual .title(s) */
.pageHeader .title {
color: #f00;
}
.leadArticle .title {
color: #00f;
}
.productPreview .product .title {
color: #0f0;
}
I think there's very little to say about this. What you're doing is fine, though it's not the only approach to organizing your markup for CSS. The important thing to understand is that class names are not part of CSS, they're part of HTML.
So the classes applied to an element are not, in HTML terms, "namespaced" by their ancestors in the DOM tree, but stand in their own right. So it is reasonable that you use "title" for the class names of each of the elements in your example because they are all alike in being titles.
A contrary example would be to say use the class name of "note", where on one element it signals a type of comment, but on another element a musical note, and then assuming that their meanings can be distinguished by inspection of an ancestor element. That's not how HTML classes are supposed to work.
It's also work noting that there's nothing unsemantic about <h5>
. Use of element names in your CSS selectors is just another way of describing the relationship between the elements you want to style. .product h5
as a selector means "style fifth level headings in the context of the sub tree of the class 'product' like this ...". That's a different statement from .product .title
which mean "style elements of class 'title' in the context of the sub tree of the class 'product' like this ...". Both statements are useful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With