There are two problems with your suggested approach -- specificity and coupling. The rules of CSS are such that .collection > li is a more specific selector than .collection-item. So if you want a particular item in the list to be red, you can't just give it a class name .warning-item and style against that -- you have to match or exceed the existing specificity. In the simple case, this isn't too bad, but it's surprisingly easy to end up representing deeply nested structures in your CSS which are very difficult to override.
The coupling problem is really just a way of saying that it might not be a good idea to describe the specifics of your HTML implementation in CSS. Class names are like an interface. One refactoring I've actually done a lot is switching out lists like the above for a combination of nav and anchor elements. It's great to be able to do that without needing to rewrite all the corresponding CSS, too.
These are tools designed to help you manage complexity and increase flexibility, not dogma. If you don't find your HTML needing to change much, or you don't need to make styles overrideable, then YAGNI. Hopefully it makes sense why framework authors, whose work is explicitly designed to be overridden, would choose this approach.
I'm just provided the link here in case anyone else was wondering the same thing.
I tend to agree with you, but I was heavily chastised by lead the front end dev at my last gig for ever directly applying design styles to tag entities as doing it as above is considered best practice at the moment (until the cycle comes around again to another best practice).
You want one collection li's to not have the style? Use an alternative class on the ul: "collection collection-alt".
You want nested li's to not inherit the styles? Use ".collection > li" in your CSS.
In any case, assigning a class on each li goes exactly against CSS best practices, because it prevents taking advantage of the inheritance of property values or of advanced selectors.
I think the whole community went to separating the HTML tag names from the styles and work only with class names [1].
If you start styling your tags directly it imminently increase the code debt if you scale. Let's say you just want to add another element inside the tag. I can give you example :
<ul class='collection'><li></li></ul>
.collection > li { color: red; }
and later on you add a anchor as a child you would need to force the specificy to this element <ul class='collection'><li><a class='collection-link'></a></li></ul>
.collection-link { color: blue; } // this will not work
.collection > li .collection-link { color: blue; } // increased complexity
I would almost always advice against styling tag names, except when you are doing css reset.As to this specific case, though, I was surprised to see your "this will not work" comment and tested it. It worked: http://jsfiddle.net/brlewis/p0Locwgp/
<ul class='collection'>
<li>
Is red
<ul class='collection'>
<li class='collection-special'>Should be blue</li>
</ul>
</li>
</ul>
.collection > li { color: red; }
.collection-special { color: blue; }
http://jsbin.com/tulenoxutu/1/edit?html,css,outputI don't usually nitpick but I don't think one link is representative of the `whole community`. Just this thread seems to prove it's pretty divided on the issue.
What is the recommendation, then? .collection .collection-item .collection-item-anchor? Genuinely curious here.
[1] http://www.smashingmagazine.com/2011/12/12/an-introduction-t... [2] http://bramsmulders.com/how-i-improved-my-workflow-with-smac... [3] https://github.com/davidtheclark/scalable-css-reading-list
I don't usually reply in this way, but this way of writing CSS has been proven to me in many hard to predict situations and is something that I would fight for in every possible way, everywhere I can. :D
I've been part of large projects that if you don't follow some styleguide rules you end up with "!important" in your codebase. Which is bad.
Scalable CSS writing ( even more important for a CSS framework that you use as a base ) consists of a more modular approach to your stylesheet.
Let's say you have a list I would usually do it :
<ul class='collection'>
<li class='collection-item'>
<a class='button button--primary'></a>
</li>
<li class='collection-item'>Normal Text</li>
</ul>
By doing this I can safely remove the .button, code ( module ) and put it somewhere else on my page without affecting how it will look like. Something more if I feel that I have a totally different link in this exact place, well yes. I would call it '.collection-item-link', because '.special-fancy-link' isn't semantic at all.At my last job, fighting about CSS and dev processes sometimes overtook actual coding and design. I'm glad to be free of control-freak colleagues. Smart and nice control-freaks, but control-freaks nonetheless.
<li class='collection-item'>
No matter how you sell it, what you have here is a css tautology. It's a "list item", the element name is right there for all to see and use, including the machine. Yet, the first thing you do is give it a new slightly similar name "collection-item". And then the very next item you do it all again. And then to justify it all, call it "OOCSS" like it rolls off the tongue.
The machine blinks but renders your tautology anyway. The machine has no say in what is the most sensible approach.
On another example, let me say: There's nothing wrong with "#sidebar h3".
A typical house might have a garage at the side. Still part of the house, but different and permanent enough to have its own ID. It has furniture inside, as does the house. But garage furniture serves a different purpose. The point is, #main and #garage are perfectly fine and make a lot of sense. "Skinning" and code re-use can be achieved in different ways using CSS. As long as there's a coherent logical approach, you can have skinning, performance and a maintenance friendly site without ever touching frameworks. The other thing is that repetition of some code is not a problem. We don't need to be OCD about a handful of repeating CSS rules. There is not usually any progression into wild, unruly CSS just because a few repeats are found here and there.
Funny but ugly (and irrelevant) stuff in the smashingmag website HTML code...
<li id="menu-item-2016" class="menu-item menu-item-type-taxonomy menu-item-object-post_tag menu-item-2016 menu-item-techniques">
CSS used "out of the box" is production-ready, and can perform incredibly well in all sorts of environments. CSS grids can be useful, but are not necessary. That's my opinion based on several years working in this area.
If you think "CSS grids gone wrong" isn't a thing, then think again. I'm talking about long term maintenance of the site where the "grid" becomes this "thing that someone installed ages ago that may or may not get the special attention it requires in future". Grids are needy, they have dependencies that may get compromised over time depending who is working on the site and how the design evolves. They have limitations, and they have underlying complexity that works to give the illusion of simplicity. Personally I prefer my illusions in the content, not the code.
The names are similar because they've created a general framework. They should have probably name-spaced the component as well with prefixes.
Using class names creates a scope so your rules don't spill out and pollute everything else. It's like local variables in a function, and it's also a hack to behave more like XML. For example:
<li class="product-sku">
is approximating:
<sku>
Maybe web components will fix this, but I'm not up-to-speed with that technology.
A class denotes something special. You don't need to repeat yourself here. The best way to eliminate side affects is by doing explicit targeting so your CSS only does what you say it can and nothing else.
html > body > div.header > h1 { color: #FFFFFF; }
I guess it's come about from trying to be more semantic within the documents.
Declaring Headings with classes is a good example as well.
h1,
.h1{
font-size:20px;
}
h2,
.h2{
font-size:18px;
}
etc... This allows you to apply <h1> styles to <h3> or even <p>'s while still keeping the content semantically correct and designers happy.Another few other common ones are
strong,
.strong{
font-weight:600;
}
small,
.small{
text-size:10px;
}
The same can go with .collection, somebody may want to use the styles on something thats not a list for example <div>'s.It also does not really go against inheritance, themes like .collection-alt can still work.
Sometimes its an overkill and I don't always do it, but in some cases (heavily responsive sites) it has worked really well. Its also easier to work in a team with one approach, rather then just doing it for headings etc why not take the principle/standard across all styles.
<ul class="list-reset">
<li class="inline-block mr1 h4 border border-red">Half-Smoke</li>
<li class="inline-block mr1 h4 border border-green">Kielbasa</li>
<li class="inline-block mr1 h4 border border-blue">Bologna</li>
<li class="inline-block mr1 h4 border border-yellow">Prosciutto</li>
</ul>...don't exist. There are many competing schools of thought. In particular, BEM is a school of thought with widespread support which disagrees with your comment.
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Writi...
They explicitly state using css classes is more performant than using tags.
I'd be interested in a CSSPerf(Do they have those?)
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Writi...
Using nesting and tags is less performant than classes. So using more classes is better than less.
> Note: This document was originally written in 2000. Much has changed when it comes to writing CSS that is fast.
<ul class="collection"> <li class="collection-item"> <ul> <li>Bulleted label</li> <li>Bulleted label 2</li> </ul> </li> </ul>
This case must be considered when setting coding standards for a framework.
You want nested li's to not inherit the styles? Use ".collection > li" in your CSS.
Note that ie6 did not support that selector. Until recently that certainly was a case for the frameworks to support.
I'd say, keep it DRY [1].
https://github.com/suitcss/suit/blob/master/doc/naming-conve...
LIs are actually kinda special. It's incredibly difficult to create your own LI in, say, web components because of their specialness (at least I've never seen it work in all browsers though there are probably some crazy hacks to get it there (or at least close enough)).
> which leads location dependency and specificity issues
You have a list of a specific type so you put a class on it. Why would that specific type of list now contain items that can be used in multiple places versus in that specific list and why would they ever be moved from that specific type of list? I don't really understand the issue you're trying to convey.
Using element names instead of class names can be problematic. In some frameworks you may need to use a different element or an element that wraps another element to achieve certain functionality.
Some use generic names like "button large" as class names, but, again in my personal experience, it often causes problems. You might have other elements that need to be "large" and may need to be inside a button - but which "large" do you mean.
So to keep things predictable, I've adopted the following practices:
- Always namespace components.
- Always ensure that selectors work even if the child has a wrapper around it.
- Whenever possible use classnames instead of element names.
And to ensure I don't get tendonitis (not sure if everyone agrees with this):
- If possible provide a shorthand for at least the most used components (i.e. "col"/"col-i" for "collection"/"collection-item"
Bootstrap does a similar thing. Drives me nuts...