CSS is the language used to style HTML pages. It has a simple set of rules to compute values of properties of every DOM element on a page. Angular provides view encapsulation to make sure component's styles only apply to the given component. However, the style of the DOM elements generated by those components are still affected by global styles. This makes debugging CSS hard.
In every project I worked on, custom CSS code is always at least 10% of total amount of code (in number of lines of code). And we always tend to underestimate the effort needed to maintain it. I never actually measured the time spent working on CSS files but I wouldn't be surprised if it would be around 10% of my time as well. CSS deserves a better place in our all web projects.
- break encapsulation
- poor readability
- break information hiding
- namespace pollution
Unfortunately, it is very rare to use a UI library that doesn't come with global styles. Bootstrap, Material Design, Prime NG and NG Zorro all come with global styles. However, it doesn't mean that you should add more mess to the mess.
Global styles and especially classes are handy because they enable developers to apply styles to elements by labelling (hopefully, those labels are semantically meaningful but that's another debate). That is something we want to keep in a new approach. The attribute we want to get rid of is that global styles are globally applied. Instead, we want global styles that are locally applied.
In this post, I'm going to present an approach based on SASS mixins. I quote the SASS language's website:
Mixins allow you to define styles that can be re-used throughout your stylesheet.
The first thing to this approach is to organize your SASS code the same way you would organize your JS/HTML code. Don't neglect it. I put all the global styles under a folder called
styles. I suggest putting all the mixins in under the
styles/mixins. Modularize mixins in meaningful packages: containers, lists, tables, inputs, buttons, typography etc. At this point, I would suggest something that would look like:
Mixins in actions
Let's have a look at the
quote mixin. This mixin can add some quote-like style to an element: a grey background, some padding, some font style and color.
Here is how we can use our mixin.
At this point, there are several things to note.
Styles stay local
We don't have any style applied globally. We apply global mixins (available to the SASS pre-processor) to local styles.
It keeps the template clean
We assign one class to each
<p>, the classes are then defined in the SASS file of the component. We can then apply several mixins to each class.
While assigning one class to each
<p> seems to be a tedious process, it actually makes sure our template stays clean: we don't overload class attributes. Style definitions are specified in the SASS file.
"Class check" for free
The SASS pre-processor will complain if a mixin doesn't exist, while CSS won't complain if you have a typo in a class.
I will try this approach along with the one described in An elegant way to enable CSS-customizable Angular components in the next big project I have to lead. I'm curious about the results. The intermediate results on a small project were already promising.