Dark theme en Angular con CSS fácil
Tags: angular, css
Published: 2023-06-21 14:27:38

Desde ya hace unos años que los dark themes se han vuelto populares por lo que hoy en día casi todas las páginas web poseen uno.

Existen varias formas para lograr nuestro objetivo pero en este post veremos una forma sencilla y rápida de implementar un dark theme utilizando Typescript/Javascript y CSS en una aplicación Angular.

## 1. Variables CSS

El dark theme puede ser implementado utilizando [variables de CSS](https://developer.mozilla.org/es/docs/Web/CSS/Using_CSS_custom_properties). Las variables estan disponibles en casi todos los buscadores exceptuando Internet Explorer.

A continuación les dejo un ejemplo de como definir las variables CSS para el theme por defecto y para el dark theme haciendo uso de una clase:

```css
body {
  --text-color: #222;
  --background-color: #fff;
}

body.dark-theme {
  --text-color: #fff;
  --background-color: #222;
}
```

## 2. Uso de las variables en los estilos globales

Una vez definidas las variables para cada theme, podremos utilizarlas dentro de nuestros estilos globales. Es importante entender que en a partir de ahora la eleccion de los colores dependerá de lo que anteriormente definimos:

```css
body {
  background: var(--background-color);
}

h1,
p {
  color: var(--text-color);
}
```

## 3. Decidir que theme utilizar

Con todo lo anterior ya listo, prender/apagar el dark theme es sencillo y puede realizarse con el siguiente código Typescript/Javascript:

```typescript
document.body.classList.toggle("dark-theme");
```

Lo que hace este código es agregar o quitar la clase `dark-theme` del elemento `body` y de esta manera se produce el cambio en el valor de las variables previamente definidas.

A continuación, dejo una aplicación a modo de ejemplo en donde se definen las variables de CSS antes mencionadas y se utilizan los emojis de 🌞 y 🌚 para activar/desactivar el dark theme:

{% embed https://stackblitz.com/edit/facundo-rodriguez-dark-theme-demo?embed=1&file=src%2Fstyles.css&hideDevTools=1 %}

Lo que hago en la app es definir una función que prende/apaga el dark theme:

```typescript
@Component({...})
export class App {
  toggleDarkTheme(): void {
    document.body.classList.toggle('dark-theme');
  }
}
```

Y en el template agrego un botón que hace uso de esta función:
```html
<button (click)="toggleDarkTheme()">{{ icon() }}</button>
```

Además agrego un signal para poder saber si el dark theme está activo y así determinar que ícono mostrar.

## 4. Leer la preferencia del usuario

CSS ofrece la posibilidad de leer la preferencia del sistema operativo establecida por el usuario a través de la media query `@media(prefer-color-scheme: dark)`.

Esta media query se puede obtener desde Typescript/Javascript de la siguiente manera:

```typescript
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
```

Esto podría usarse al iniciar la aplicación para establecer el tema predeterminado de acuerdo a la preferencia del usuario usando el siguiente código:

```typescript
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
document.body.classList.toggle('dark-theme', prefersDark.matches);
```