Say you're building a conceptual widget named Awesome Widget and you want to completely protect it from conflicting with either surrounding elements or child elements that reside as content inside the widget.
What we don't want
div ul li {}
Solution 1: CSS child combinator
Using the CSS child combinator selector to specify that only direct children should be targeted.
.awesomewidget > div > ul > li {}
Solution 2: class namespacing
Using aw (Awesome Widget) as the namespace for each class, decreasing the chance of any other elements on the page using that exact namespace + classname.
.awesomewidget .aw-container .aw-list .aw-listitem {}
There's also something like @namespace in CSS but that's only for XML.
Besides solution 1 and 2, are there any others that can be used? Which one would you prefer? Any best practises?
EDIT: example of a problem that arises without proper namespacing / styling conflict prevention
Widget styling:
.awesomewidget > div ul li {
background-color:red;
}
User styling:
ul li {
background-color:blue;
}
Markup:
<div class="awesomewidget">
<div>
<ul>
<li>
<!-- user content starts here -->
<p>I am the user and I want to add some content here. Let's add a list:</p>
<ul>
<li>Why is this list-item red and not blue?</li>
</ul>
<!-- user content ends here -->
</li>
<li>
<!-- user content starts here -->
<!-- user content ends here -->
</li>
</ul>
</div>
</div>
You need to keep the widget CSS rules as self-contained as possible, which means that you will need to specify every property that is critical to you design, and make sure that properties like float: none , position: static and so on are explicitly set.
To resolve such conflicts, you have CSS Cascade. The CSS Cascade is a way for browsers to resolve conflicting CSS declarations. By specifying CSS rules, you specify where the CSS style is added to the cascade hierarchy. The further down a hierarchy a declaration falls, the less likely it will end up as the final style.
I would prefer to use a combination of the two solutions like:
.awesomewidget > div ul li {}
Because the second one adds a LOT of unecessary weight to the markup.
For your example, I would add a wrapper around the user content with class .user
and then prepend their CSS with .user
. However, this is not graceful, it adds some markup, and I think it would be prone to failure.
XBL might help if it ever gets implemented in browsers as it has ways of designing widgets which can avoid passing on styling information.
Another advantage, btw, to including the child combinator is performance. It does not need to check all levels of possible children to determine how to render.
But if you're going to do class-namespacing for brevity, two at most should be enough I would think, unless you're not naming distinctly enough:
.awesomewidget .aw-listitem {}
You could also give a container (with a well namespaced class) to the non-user content section(s) at the highest level possible which does not enclose the user content, saving yourself from that risk. <div/>
is pretty handy for that kind of arbitrary grouping and made for that purpose...
If you're experiencing many CSS namespacing conflicts, maybe it's time to consider switching to a front-end JS framework like Facebook's ReactJS. This, in conjunction with Webpack Module Loader, will allow you to leverage many fine JS libraries that will streamline your development workflow. CSS-loader, for example, will help you manage your CSS development by doing local scoping, which is just what you're looking for.
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