---
url: /dna/guide/styling.md
---
# Styling

## Global styles

You can define global styles for your components using the static `globalStyles` property. This property can be a string, an array of strings or a `CSSStyleSheet` instance.

::: warning

Be careful when using global styles, as they will affect the entire document and may lead to unexpected results if not managed properly.
Always use a [style technique](#other-styling-techniques) that scopes your CSS rules to avoid collisions.

:::

When a component is defined, its global styles are injected into the document `<head>` inside a `<style>` tag (or adopted if a `CSSStyleSheet` is used).

```tsx
import { Component, customElement } from '@chialab/dna';

@customElement('x-card')
class Card extends Component {
    static globalStyles = `
        x-card {
            display: block;
        }
    `;
}
```

### Importing CSS modules

You can also import CSS as `CSSStyleSheet` instances if your bundler supports it.

```tsx
import { Component, customElement } from '@chialab/dna';
import styles from './x-card.css' with { type: 'css' };

@customElement('x-card')
class Card extends Component {
    static globalStyles = styles;
}
```

## Scoped styles

DNA can render plain `<style>` tags in a template, but what about style encapsulation?

Since components can be extended and stylesheets inherited, we need to be able to scope CSS rules based on the final component definition.

::: info

You may don't need to use DNA's scoped style if you are already using a styling strategy to build and distribuite your CSS files. Other good options are CSS-in-JS, CSS Modules and BEM with lazy loading styles.

:::

Every `<style>` tag rendered to a component is scoped.

```tsx
import { Component, customElement, property } from '@chialab/dna';

@customElement('x-card')
class Card extends Component {
    @property() title: string = '';

    render() {
        return <>
            <style>
                h1 { color: cadetblue; }
            </style>
            <h1>{this.title}</h1>
        </>;
    }
}
```

The previous component will be rendered as follow:

```html
<h1>Unaffected heading</h1>
<div
    is="x-card"
    title="Alan Turing">
    <style>
        [:scope='x-card'] h1 {
            color: cadetblue;
        }
    </style>
    <h1>Alan Turing</h1>
    <div></div
></div>
```

In the resulting HTML of the example above, the first `H1` color will not be affected by the scoped style declaration.

### How does it work?

DNA uses the component definition name to prefix all CSS rules with an unique selector for the element. For example, the rule

```css
h1 {
    color: cadetblue;
}
```

is transformed into

```css
[:scope='x-card'] h1 {
    color: cadetblue;
}
```

### The `:host` pseudo selector

If you need to style the component root itself, you can use the `:host` selector like in Shadow DOM contexts:

```css
:host {
    color: #333;
    font-family: sans-serif;
}
```

You can also define styles for component states with `:host(*selector*)` rule:

```css
:host(:hover) {
    background-color: #e5e5e5;
}

:host(:hover) span {
    color: red;
}
```

The `:host` selector will respect component definition also for inherited styles.

## Other styling techniques

Every component node has the `is` attribute populated with the defined name of the component class. You can use an attribute selector to scope your CSS, for example using nesting:

```css
/* CUSTOM ELEMENT */
x-card {
    h1 {
        color: cadetblue;
    }
}

/* BUILT IN ELEMENT */
[is='x-card'] {
    h1 {
        color: cadetblue;
    }
}
```

### Plain CSS

Some bundlers import CSS files in JavaScript and auto-append `<link>` tags. In this case, you have to manually set the scope for your rules:

```css
/* CUSTOM ELEMENT */
x-card .title {
    color: cadetblue;
}

/* BUILT IN ELEMENT */
[is='x-card'] .title {
    color: cadetblue;
}
```

```html
<link
    href="x-card.css"
    rel="stylesheet" />
```

### CSS Modules

If you are using a transpiler, you can also use CSS Modules, which imports CSS classes as JavaScript references in order to use them in a template:

::: code-group

```tsx [x-card.tsx]
import { Component, customElement, property } from '@chialab/dna';
import { title } from './x-card.css';

@customElement('x-card', {
    extends: 'div',
})
class Card extends Component {
    @property() title: string = '';

    render() {
        return <h1 class={title}></h1>;
    }
}
```

```css [x-card.css]
.title {
    color: cadetblue;
}
```

:::

## The `css` helper

The `css` helper is a method internally used by DNA convert a CSS string into its scoped version. This can be used to add extra manipulation to the CSS string:

```ts
import { css } from '@chialab/dna';

const cssText = css('x-article', 'h1 { color: red; }').replace(/red/g, 'blue');

const style = document.createElement('style');
style.textContent = cssText;

document.head.appendChild(style);
```
