loading...
Cover image for Angular Style Encapsulation: You're Doing It Wrong

Angular Style Encapsulation: You're Doing It Wrong

peterdavidcarter profile image Peter David Carter ・3 min read

Style encapsulation is a neat idea... I mean, we're banishing all those crazy collisions in the shared global, just putting your styles where you actually need them, right?

😂

The fact is, on any enterprise scale project you're likely to end up with a hodgepodge approach, with some stuff in the shared global, some in the component and some passed through into class bindings, or even in exceptional cases as dynamically generated and injected custom s/css objects. That's not necessarily bad, but in practice it often is.

Look, this fancy new tool! Let's use it at random with no forethough, tackling each problem as if it exists in isolation! What could go wrong?

The issue for those who see encapsulation as a magic bullet that's going to fix all your styling woes by forcing things into the correct place is that it absolutely won't do that. If you're lazy and don't think through your strategy at a big picture level it can and will bite you in the ass. Repeatedly. And you won't enjoy the process. You have to be strict, you have to be rigorous and you have to expect that switching encapsulation on will, far from reducing your cognative overhead, actually likely increase it. This is because you can't just place your styles in the component that needs them in every scenario. There are many, many different situations, each of which require a different approach.

Developer you think you are, hhhmmmm?

Firstly, and this should I hope be obvious to everyone: if a styling is genuinely applied over the whole app, and particularly if you expect to change it globally, it belongs somewhere shared. Now, you can use shared global css/scss files for this. You can also create a shared component that contains the styles within in. In many ways the latter is preferable, since you get all those lovely reuse benefits, but something to consider when doing it is this: every time you want to customise your component on a per page basis, you're going to have to mess about with input variables and bindings which, in a really large application, could be as much as 3 or 4 or even more layers deep. How much are you going to be customising, and by doing things this way, how much hassle are you going to create for yourself vs the old-school approach of s/css shared over some or part of an application? This is something specific to your application and you should know as a professional developer what the best way is in each scenario. You have to go through that mental process if you want your application to scale correctly.

Secondly, you might think that the little component you're making is just for the page you're on, but is it really? If you want to use those styles elsewhere, they're now stuck in a box. Did you really want to do that? Maybe you did. If you're certain then encapsulating them to a single, per page component was the right call. Again, though, you need to understand the complete design, not just the little patch you're working on.

Thirdly, and probably most importantly, there are no absolute rules you can follow for using styling encapsulation but you absolutely cannot do things at random and hope for the best. What you'll end up with won't just be a spaghetti mess, it'll be a system that actively forces you to create a spaghetti mess that gets worse and worse each time.

Bending your mind around other people's encapulation choices is a bit like understanding The Matrix.

Don't do that.

If there's one thing you take home from this article it's that every time you make a call about where to place a style, you should consider from every angle available what that will mean.

Discussion

pic
Editor guide
Collapse
marcoslooten profile image
Marco Slooten

We have most of the component-specific styling in the components themselves (so scoped to the component). We do have some global styles, for instance, a bunch of variables and mixins (colors, interaction patterns) and things like typography and grids. When I joined the team they were using BEM as a solution, but in my opinion, it's useless once you have component-scoped CSS (it just adds a lot of fluff). For global styles, I can see the use case.

I'm reasonably happy with the current approach, but we do run into issues where we need to override styles with ng-deep too often. How do you deal with that, besides making the components so strict that they will always be implemented exactly the same?

Collapse
peterdavidcarter profile image
Peter David Carter Author

::ng-deep is banned for us due to it being depricated, and support for it being planned to be dropped across browsers, though honestly I don't see how Google will justify the amount of breakage taking away this widely used tool will cause.

One solution that I touched on in the article is to construct a stylings object in the controller of the parent, then pass this through via an input binding and an ngStyle binding. Some people may dislike this approach due to it breaking separation of concerns, but it has often been the only option left short of, as you say, making everything look the same, which is some people's chosen option but not mine.

You are right about the global style and BEM being pretty useless with encapsulation to some degree, but what if you want to style an element contained within an element where those exist in different areas of the shadow DOM (nested components) which do not and are not supposed to have knowledge of each other?

Collapse
marcoslooten profile image
Marco Slooten

Thanks for your reply! Yeah, I can see the use case of style objects. I think in React this pattern is more widely used than in Angular for some reason.

You're last point, you're talking about giving a nested component different styling based on the context they're used in? We'd be using ng-deep from the parent component in most cases, but we're starting to explore global styling for that kind of use case more and more. It's just a shame to lose the encapsulation, but in a way BEM will prevent most accidental overwrites. My gripe was more with using BEM within components that don't have children and have encapsulated styles.

Collapse
Sloan, the sloth mascot
Comment deleted
Collapse
peterdavidcarter profile image
Peter David Carter Author

It's written using the iso basic latin alphabet on my end. Perhaps there's a problem with your browser settings.

(I'll try to keep things simpler for my next article.)