An elegant way to enable CSS-customizable Angular components
Tags: angular
Published: 2022-01-03 07:38:05

---
title: An elegant way to enable CSS-customizable Angular components
published: true
date: 2021-05-26 07:51:54 UTC
tags: angular
canonical_url: 
---

 ![An elegant way to enable CSS-customizable Angular components](https://blog.merckx.fr/content/images/2021/05/david-pisnoy-46juD4zY1XA-unsplash.jpeg)

Originally posted on my blog: https://blog.merckx.fr/css-customizable-angular-components.

Creating components with Angular is a bless. The API to declare inputs and outputs is clear and simple. View encapsulation makes sure that styles don't leak outside of the component's host. However, there is one thing that is not clearly defined by the Angular framework: providing an API to let consumers customize styles of a component.

You can of course achieve it by setting up inputs. You would have to declare the inputs and put inline styles on elements inside your component. You would also sometimes have to use `@HostBinding` to attach styles to the host element.

The alternative I suggest in this post is making use of CSS custom properties, also called variables. If you don't know what they are, there is a great page about this topic on [MDN's website](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties).

<style>
p em {
  color: blue;
}
</style>
Let's directly have a look at an example of a card component. It has a title and projects content right below it.

```html
<h3>{{title}}</h3>

<div class="content">
  <ng-content></ng-content>
</div>
```

_card.component.html_

```typescript
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-card',
  templateUrl: './card.component.html',
  styleUrls: ['./card.component.css']
})
export class CardComponent {
  @Input() title = '';
}
```

_card.component.ts_

```css
:host {
  padding: var(--card-padding, 10px 10px);
  border: var(--card-border, 1px solid grey);
  box-shadow: var(--card-box-shadow, 1px 1px 4px 1px grey);
  display: inline-block;
}

h3 {
  color: var(--card-title-color, black);
  padding: 0;
  margin: 0;
  font-weight: bold;
  font-size: 16px;
}

.content {
  margin: 5px 0;
  font-size: 12px;
}
```

_card.component.css_

The last CSS file is where we enable CSS customization. The card component uses a few CSS variables `--card-padding`, `--card-border`, `--card-box-shadow` and `--card-title-color`. You can also note that we provide fallback values with the syntax: `color: var(--card-title-color, black /* <- fallback value */ );`.

Let's now have a look at how one can consume the card component and customize its style.

```html
<app-card [title]="'Card #1'" class="card-1">
  <p>This is card #1.</p>
</app-card>

<app-card [title]="'Card #2'" class="card-2">
  <p>This is card #2.</p>
</app-card>
```

_app.component.html_

```css
app-card {
  margin: 3px;
  --card-box-shadow: 0 0 4px 0px grey;
}

app-card.card-1 {
  --card-title-color: red;
}

app-card.card-2 {
  --card-title-color: blue;
}
```

_app.component.css_

Our application template declares two cards. Each receives a CSS class. In the CSS file, we say that the `--card-box-shadow` of the cards should be `0 0 4px 0px grey`. `.card-1`gets a red title and `.card-2`a blue one.

![An elegant way to enable CSS-customizable Angular components](https://blog.merckx.fr/content/images/2021/05/Screenshot-2021-05-26-at-09.03.11.png)
_The two cards of our application_

CSS variables, or custom properties, act like other CSS properties: inheritance and specificity rules apply the same way.

You can also define CSS variables for the whole application by using the `:root` selector.

```css
:root {
  --card-box-shadow: 0 0 4px 0px grey;
  --card-title-color: red;
  --card-border: 1px solid grey;
}
```

_Define variables globally_

This technique enables developers and consumers to keep concerns separate: what is relevant to styling stays in CSS. It is also an elegant way for library creators to give more customization capabilities to their components.

* * *

KM

Photo by [David Pisnoy](https://unsplash.com/@davidpisnoy?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/colors?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)