Angular CSS Strategies

Ben Racicot
3 min readMar 23, 2020

--

With Angular’s deprecation of shadow piercing selectors this article walks though 3 reasons why we never needed them in the first place.

The answer lives in our web development roots.

Example Angular project root folder

The role of a global stylesheet

Component-scoped styles are a great tool but so are unscoped, global styles.

I’ve found that most Angular CSS issues stem from incorrect use of a global stylesheet and a heavy reliance on component styles instead.

Example of a dead style:

Use the Cascade First, Component Styles Last

If you take a page from popular CSS frameworks we see dedicated CSS files for layout, typography, mixins and any reused code…

Applying this global CSS architecture to our app’s web components allows new levels of flexibility.

Styles for elements, utility classes, layouts and even common features have predefined base styles to get your components built fast.

A great example is star ratings. In our application we have many uses for stars. Star rating forms, static star ratings, single stars, lg/md/sm stars etc.

But all stars are styled from a global scss/blocks/stars.scss file.

Here’s a Stackblitz example:

Take your global stylesheet to the next level

The first rule is to maintain 1 level of specificity on all global styles.

Ok, let’s be realistic, you may occasionally need to go 2 levels deep. However, this unwritten rule will drive discipline in the global CSS space and code review will be alerted to changes within these files.

Above is my Stackblitz template where InputTagsComponent exemplifies shared global CSS doing all the work.

  • floating-label.scss drives input styles, states, borders etc.
  • dropdowns.scss drives typeahead results: dropdowns app-wide
  • generic icon, chip, button styles etc… all covered globally.

An Opportunity for a Tidy Design System

Many front-end devs have strong opinions of BEM, OOCSS, SMACSS etc.

And so do I… However, each of those standards have excellent principles that we can benefit from.

For instance OOCSS is strongly focused on separation of “structure and skin”. The image above is just an example of how to adopt something similar where the cascade will now allow one classname for the same affect.

All 358 chips within your app have solid base styles, only overriden if the component which uses it desires.

ShadowDOM Encapsulation

Pete Bacon Darwin mentioned on Angular’s issue Clarify information about deprecation of :ng-deep and recommend replacement that shadowDom view encapsulated components needed a stronger solution.

  • ShadowDom encapsulated components cannot access to global styles.
  • But they do have access to all CSS Custom Properties (CSS variables).

CSS variables should also be part of your global CSS for many purposes.

In conclusion

By styling everything 1 level deep within your global styles the cascade can reset these styles for you (with a 1-level-deep rule)

This setup fundamentally solves many Angular CSS issues such as:

  • actually utilizing a CSS architecture
  • manageable / DRY CSS scalability without specificity deepening
  • shadow-piercing styles existing in the global scope
  • when styles are global, components can override easily
  • root/dark CSS custom properties strategy begins globally
  • no need for deprecated ::ng-deep or shadow piercing at all
  • parent components styling children is now easy
  • optionally create a reusable SCSS variables file
  • lighter weight component styles (containing only reset styles)

What do you think?

Is it possible to maintain 1 level of CSS specificity within an application?

--

--

Ben Racicot

Hi! I’m passionate about web technology, specifically Angular and all things JavaScript.