Styling in Angular can be a bit intimidating at the start. Hopefully this will shed a bit of high-level light on the situation.
There are 3 main places to stick your styles in Angular:
- Component styles - Style encapsulated to the component.
- Global styles - Styles in the global scope.
- Dependency styles - mixins & variables that other stylesheets depend on
These are the easiest to talk about so let's keep it brief. Angular uses the excellent Shadow DOM technique to allow us to encapsulate (protect from outside interference) the styles of our components.
- This is the mechanism that allows us to create truly reusable components that we can reuse within the same app or in a different project.
- This also makes styling much easier to read and reason about. As our component is only effected by the styles in the (nice and short) stylesheet and the very minimal global styles we may have.
- It improves separation of concerns. The responsibility of styling a component should be with the component itself, as opposed to the wider app.
NB: Component style encapsulation only works within the component tree. Therefore global styles will still effect all components.
These are the 'normal' way css works. All of the styles are bundled together from the styles.scss file in the project root and added into the head of index.html. You can find the global styles in the compiled output - its usually the last tag in the head tag and looks something like this:
<link rel="stylesheet" href="styles.081464a278750c3f7d11.css">
Global styles do effect all elements inside the app - so it is prudent to be sure anything you add there is truly global, and that a component intended for reuse won't rely on these to be able to render correctly.
I recommend to only have these files (or similar) globally available:
@import "./app/scss/reset"; <- reset browser styles @import "./app/scss/typography"; <- add font-imports @import "./app/scss/base"; <- add basic styles (like fonts)
The order of the imports in styles.scss is important.
Dependency styles are those that are references all over the app, in different feature modules and often in base.scss. These are most likely to be variables and mixins to keep the app consistent.
The reason that the variables and mixins are not in the global scope is that Angular will compile different style bundles for different lazy-loaded modules or chunks individually. Therefore if a module depends on scss $variables that are in the global scope, then the modules are not truly reusable. This is a bit of a point-of-contention as it could be argued that there is still a dependancy on the variables.scss file, however the variables should be considered similar to an API Interface as most components will rely on the --primary-brand-color regardless of which project they are in.
Dependancy style imports can be quite annoying as they can get very long, and need updating every time you move the component in the filetree:
To fix this, an argument can be added to angular.json to let the compiler know where the stylesheets are. This is: stylePreprocessorOptions.includePaths and accepts an array of directories.
I choose to store all of my dependancy styles in a folder called "importable" as shown below:
NB: It is preferable for the scss stylesheets to go into a folder in the root of the project, rather than inside the /assets folder. The assets folder is generally reserved for public files, which doesn't really apply to your stylesheets!
As always - Thanks for reading - if you have any comments or corrections please give me a shout.
Top comments (0)