---
title: Styles | Components
contributors:
  - manucorporat
  - zanettin
  - cunzaizhuyi
  - manuelsanchez2
  - literalpie
  - forresst
  - DustinJSilk
  - saikatdas0790
  - LiKang6688
  - Craiqser
  - adamdbradley
  - the-r3aper7
  - mhevery
  - igorbabko
  - mrhoodz
  - tanftw
updated_at: '2023-09-19T17:37:26Z'
created_at: '2023-03-20T23:45:13Z'
---

import PackageManagerTabs from '~/components/package-manager-tabs/index.tsx';

# Styles

Qwik does not enforce a specific styling approach, you can style your Qwik app using any method you prefer, such as CSS, CSS-in-JS, CSS modules...

## CSS Modules

Qwik supports [CSS Modules](https://github.com/css-modules/css-modules) out of the box thanks to [Vite](https://vitejs.dev/guide/features.html#css-modules).

To use CSS modules, simply create a `.module.css` file. For example, `MyComponent.module.css` and import it in your component.

```css /container/#a title="src/components/MyComponent/MyComponent.module.css"
.container {
  background-color: red;
}
```

Then, import the CSS module in your component.

```tsx {2} /styles/ /container/#a title="src/components/MyComponent/MyComponent.tsx"
import { component$ } from '@builder.io/qwik';
import styles from './MyComponent.module.css';

export default component$(() => {
  return <div class={styles.container}>Hello world</div>;
});
```

Remember that Qwik uses `class` instead of `className` for CSS classes.

Qwik also accepts arrays, objects, or a combination of them to assign multiple classes:
```tsx title="src/components/MyComponent/MyComponent.tsx"
import { component$ } from '@builder.io/qwik';
import styles from './MyComponent.module.css';

export default component$((props) => {
  // Array syntax example
  return <div class={[
    styles.container, 
    'p-8', 
    props.isHighAttention ? 'text-green-500' : 'text-slate-500',
    { active: true}
  ]}>Hello world</div>;

  // Object syntax example
  return <div class={{  
    'text-green-500': props.isHighAttention,
    'p-4': true
  }}>Hello world</div>;
});
```

## Global Styles

Many apps use a global stylesheet for browser resets and defining global styles. This is a good practice, but it is not recommended to use it for styling your components. Qwik is optimized to let the browser download the styles that are needed for the current view. If you use a global stylesheet, all of the styles will be downloaded on the first load, even if they are not needed for the current view.

```tsx
import './global.css';
```

> Automatically, Qwik will try to inline this file in production mode if the amount of CSS is less than 10KB. If the file is larger than 10KB, it will be loaded as a separate file.

## CSS-in-JS

Qwik has first-class CSS-in-JS support using [styled-vanilla-extract](https://github.com/wmertens/styled-vanilla-extract), which provides an extremely efficient css-in-js solution without any runtime!

```tsx title="style.css.ts"
import { style } from 'styled-vanilla-extract/qwik';

export const blueClass = style({
  display: 'block',
  width: '100%',
  height: '500px',
  background: 'blue',
});
```

```tsx title="component.tsx"
import { component$ } from '@builder.io/qwik';
import { blueClass } from './styles.css';

export const Cmp = component$(() => {
  return <div class={blueClass} />;
});
```

<PackageManagerTabs>
<span q:slot="pnpm">
```shell
pnpm run qwik add styled-vanilla-extract
```
</span>
<span q:slot="npm">
```shell
npm run qwik add styled-vanilla-extract
```
</span>
<span q:slot="yarn">
```shell
yarn run qwik add styled-vanilla-extract
```
</span>
<span q:slot="bun">
```shell
bun run qwik add styled-vanilla-extract
```
</span>
</PackageManagerTabs>

Please refer to the [docs of our official integration](/docs/integrations/styled-vanilla-extract/index.mdx) for more information.

> **How about emotion or other CSS-in-JS libs?** While extremely popular, emotion and other CSS-in-JS libs are not the best choice for Qwik. [They are not optimized for runtime performance and they don't have a good SSR streaming support](https://dev.to/srmagura/why-were-breaking-up-wiht-css-in-js-4g9b), leading to a degraded server and client performance.

## Styled-components

The styled-components library is a popular tool in React-land for writing CSS-in-JS. Thanks to the same [styled-vanilla-extract](https://github.com/wmertens/styled-vanilla-extract) plugin, you can write your styles with styled-components syntax in Qwik with zero-runtime cost!

<PackageManagerTabs>
<span q:slot="pnpm">
```shell
pnpm run qwik add styled-vanilla-extract
```
</span>
<span q:slot="npm">
```shell
npm run qwik add styled-vanilla-extract
```
</span>
<span q:slot="yarn">
```shell
yarn run qwik add styled-vanilla-extract
```
</span>
<span q:slot="bun">
```shell
bun run qwik add styled-vanilla-extract
```
</span>
</PackageManagerTabs>

Like this:

```tsx title="styles.css.ts"
import { styled } from 'styled-vanilla-extract/qwik';

export const BlueBox = styled.div`
  display: block;
  width: 100%;
  height: 500px;
  background: blue;
`;
```

```tsx title="component.tsx"
import { component$ } from '@builder.io/qwik';
import { BlueBox } from './styles.css';

export const Cmp = component$(() => {
  return <BlueBox />;
});
```

## Scoped CSS

To use scoped CSS, you can use the `useStylesScoped$()` hook exported from `@builder.io/qwik`.

```tsx {4-8} title="src/components/MyComponent/MyComponent.tsx"
import { component$, useStylesScoped$ } from '@builder.io/qwik';

export default component$(() => {
  useStylesScoped$(`
    .container {
      background-color: red;
    }
  `);
  return <div class="container">Hello world</div>;
});
```

You can also import an external CSS file. For that you need to add the `?inline` query parameter to the import of the CSS file, and pass the default export of the CSS file to the `useStyleScoped$()` hook.

```css title="src/components/MyComponent/MyComponent.css"
.container {
  background-color: red;
}
```

```tsx {3,6} title="src/components/MyComponent/MyComponent.tsx"
import { component$, useStylesScoped$ } from '@builder.io/qwik';

import styles from './MyComponent.css?inline';

export default component$(() => {
  useStylesScoped$(styles);
  return <div class="container">Hello world</div>;
});
```


### `:global()` selector

Using `useStylesScoped$` will scope all child selectors in a ruleset to the component. If you need to style child components rendered through a `<Slot />`, you will need to break out of the scoped styles using the `:global()` selector.

```tsx
import { useStylesScoped$, component$ } from '@builder.io/qwik';

export const List = component$(() => {
  useStylesScoped$(`
    .list {
      display: flex;

      > :global(*nth-child(3)) {
        width: 100%
      }
    }
  `);

  return (
    <div class="list">
      <Slot />
    </div>;
  );
});
```

This will render a css selector of `.list.⭐️8vzca0-0 > *:nth-child(3)`, allowing you to target child components. This could be considered the equivalent of using `::ng-deep` in Angular.

> Beware that this may have unintended effects that cascade down your component tree.


## `useStyles$()`

A lazy-loadable reference to component's styles.

Component styles allow Qwik to lazy load the style information for the component only when needed, which avoids double loading during SSR hydration.

```tsx
import { useStyles$, component$ } from '@builder.io/qwik';
import styles from './code-block.css?inline';

export const CmpStyles = component$(() => {
  useStyles$(styles);
  return <span class="my-text">Some text</span>;
});
```

```css
// code-block.css
.my-text {
  color: red;
}
```

> Notice that in order to import CSS as a string in Vite, you need to add the `?inline` query parameter to the import, like this: `import styles from './code-block.css?inline';`

`useStyles$` uses lazy loading strings that won't dynamically update. If you'd like to evaluate some JS, use a `style` tag instead

```tsx
export const CmpStyles = component$(() => {
  const primaryColor = "red";

  // ❌ Does not work
  useStyles$(`
    .my-text {
      --primary-color: ${primaryColor};
    }
  `);

  // ✅ Adding in the style attribute works
  return (
    <span 
      style={{ "--primary-color": primaryColor }} 
      class="my-text"
    >
      Some text
    </span>
  );
});
```


## CSS Preprocessors

Thanks to [Vite](https://vitejs.dev/guide/features.html#css-pre-processors), Qwik supports CSS preprocessors like Sass, Less, Stylus, and PostCSS.

There is no need to install Qwik-specific plugins for them, but the corresponding pre-processor itself must be installed:


<PackageManagerTabs>
<span q:slot="pnpm">
```shell
# .scss and .sass
pnpm add -D sass

# .less
pnpm add -D less

# .styl and .stylus
pnpm add -D stylus
```
</span>
<span q:slot="npm">
```shell
# .scss and .sass
npm add -D sass

# .less
npm add -D less

# .styl and .stylus
npm add -D stylus
```
</span>
<span q:slot="yarn">
```shell
# .scss and .sass
yarn add -D sass

# .less
yarn add -D less

# .styl and .stylus
yarn add -D stylus
```
</span>
<span q:slot="bun">
```shell
# .scss and .sass
bun add -D sass

# .less
bun add -D less

# .styl and .stylus
bun add -D stylus
```
</span>
</PackageManagerTabs>

Check [Vite's docs](https://vitejs.dev/guide/features.html#css-pre-processors) for more information.

## Tailwind

To use Tailwind in your app, you can add it to your app with our built-in integration:


<PackageManagerTabs>
<span q:slot="pnpm">
```shell
pnpm run qwik add tailwind
```
</span>
<span q:slot="npm">
```shell
npm run qwik add tailwind
```
</span>
<span q:slot="yarn">
```shell
yarn run qwik add tailwind
```
</span>
<span q:slot="bun">
```shell
bun run qwik add tailwind
```
</span>
</PackageManagerTabs>

Check out [the integration docs](/docs/integrations/tailwind/index.mdx) for more information.

## PostCSS

It is also possible to use PostCSS in your app with our built-in integration:


<PackageManagerTabs>
<span q:slot="pnpm">
```shell
pnpm run qwik add postcss
```
</span>
<span q:slot="npm">
```shell
npm run qwik add postcss
```
</span>
<span q:slot="yarn">
```shell
yarn run qwik add postcss
```
</span>
<span q:slot="bun">
```shell
bun run qwik add postcss
```
</span>
</PackageManagerTabs>

Important: Since we are using vite, the configuration should look as follows to work:

```shell
// Configuration with vite
module.exports = {
  plugins: {
    autoprefixer: {},
    "postcss-preset-env": {
      stage: 3,
      features: {
        "nesting-rules": true,
      },
    },
  },
}
```

Now you will be able to use CSS with nesting-rules like the following ones:

```css
body {
  & .box {
    background: red;

    &:hover {
      background: yellow;
    }
  }
}
```

Check out [the integration docs](/docs/integrations/postcss/index.mdx) for more information.

## Why not inline styles using the `<style>` tag?

A naive way to ensure that a component has the correct styles loaded is to inline the style information into a component like so.

```tsx
export const MyComponent = () => {
  return (
    <>
      <style>.my-class { color: red; }</style>
      My Component
    </>
  );
}
```

The problem with this approach is that we will load styles twice.

1. The styles are inserted into the HTML as part of the SSR.
2. Then when the component is invalidated and needs to be re-rendered, the styles are loaded again because they are inlined.

What is needed is to load the styles independently from the component. This is what [`useStyles$()`](/docs/(qwik)/components/styles/index.mdx#usestyles) is for. There are two scenarios:

1. The component is rendered on the server and the styles are inserted into `<head>` as part of the SSR.
   - Adding a new instance of a component to the application does not require that we load the styles as they are already included as part of SSR.
2. The component is rendered on the client for the first time. In that case, the new component does not have styles in the `<head>` as the component was not part of SSR.
   - Adding a new component that was not part of SSR requires that styles are loaded and inserted into `<head>`.
