樣式

Qwik 不會強制執行特定的樣式方法,您可以使用任何您喜歡的方法來設計您的 Qwik 應用程式,例如 CSS、CSS-in-JS、CSS 模組...

CSS 模組

由於 Vite,Qwik 原生支援 CSS 模組

若要使用 CSS 模組,只需建立一個 .module.css 檔案。例如,MyComponent.module.css 並將其導入您的組件中。

src/components/MyComponent/MyComponent.module.css
.container {
  background-color: red;
}

然後,在你的元件中導入 CSS 模組。

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>;
});

請記住,Qwik 使用 class 而不是 className 來表示 CSS 類別。

Qwik 也接受陣列、物件或它們的組合來指定多個類別

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>;
});

全域樣式

許多應用程式使用全域樣式表來進行瀏覽器重置和定義全域樣式。這是一個良好的做法,但不建議將其用於設定元件樣式。Qwik 經過優化,可讓瀏覽器僅下載當前視圖所需的樣式。如果你使用全域樣式表,則所有樣式都將在第一次載入時下載,即使當前視圖不需要它們。

import './global.css';

在生產模式下,如果 CSS 的大小小於 10KB,Qwik 會自動嘗試將此檔案內嵌。如果檔案大於 10KB,它將作為單獨的檔案載入。

CSS-in-JS

Qwik 使用 styled-vanilla-extract 提供一流的 CSS-in-JS 支援,它提供了一個非常高效的 css-in-js 解決方案,而且沒有任何執行時!

style.css.ts
import { style } from 'styled-vanilla-extract/qwik';
 
export const blueClass = style({
  display: 'block',
  width: '100%',
  height: '500px',
  background: 'blue',
});
component.tsx
import { component$ } from '@builder.io/qwik';
import { blueClass } from './styles.css';
 
export const Cmp = component$(() => {
  return <div class={blueClass} />;
});
npm run qwik add styled-vanilla-extract

如需更多資訊,請參閱 我們官方整合的文檔

那 emotion 或其他 CSS-in-JS 函式庫呢? 雖然非常流行,但 emotion 和其他 CSS-in-JS 函式庫並不是 Qwik 的最佳選擇。它們沒有針對執行時效能進行優化,並且沒有良好的 SSR 串流支援,導致伺服器和客戶端效能下降。

Styled-components

styled-components 函式庫是在 React 中編寫 CSS-in-JS 的熱門工具。感謝同樣的 styled-vanilla-extract 外掛,你可以在 Qwik 中使用 styled-components 語法編寫樣式,而無需任何執行時成本!

npm run qwik add styled-vanilla-extract

像這樣

styles.css.ts
import { styled } from 'styled-vanilla-extract/qwik';
 
export const BlueBox = styled.div`
  display: block;
  width: 100%;
  height: 500px;
  background: blue;
`;
component.tsx
import { component$ } from '@builder.io/qwik';
import { BlueBox } from './styles.css';
 
export const Cmp = component$(() => {
  return <BlueBox />;
});

作用域 CSS

要使用作用域 CSS,你可以使用從 @builder.io/qwik 匯出的 useStylesScoped$() 鉤子。

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>;
});

你也可以匯入外部 CSS 檔案。為此,你需要在 CSS 檔案的匯入中添加 ?inline 查詢參數,並將 CSS 檔案的預設匯出傳遞給 useStyleScoped$() 鉤子。

src/components/MyComponent/MyComponent.css
.container {
  background-color: red;
}
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() 選擇器

使用 useStylesScoped$ 會將規則集中所有子選擇器的作用域限定為元件。如果你需要為通過 <Slot /> 渲染的子元件設定樣式,則需要使用 :global() 選擇器跳出作用域樣式。

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>;
  );
});

這將渲染一個 .list.⭐️8vzca0-0 > *:nth-child(3) 的 css 選擇器,允許你定位子元件。這可以被認為等同於在 Angular 中使用 ::ng-deep

請注意,這可能會產生非預期的效果,並向下級聯到你的元件樹中。

useStyles$()

元件樣式的延遲載入參考。

元件樣式允許 Qwik 僅在需要時才延遲載入元件的樣式資訊,從而避免在 SSR 水合過程中重複載入。

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>;
});
// code-block.css
.my-text {
  color: red;
}

請注意,為了在 Vite 中將 CSS 作為字串匯入,你需要在匯入中添加 ?inline 查詢參數,如下所示:import styles from './code-block.css?inline';

CSS 預處理器

感謝 Vite,Qwik 支援 Sass、Less、Stylus 和 PostCSS 等 CSS 預處理器。

不需要為它們安裝 Qwik 特定的外掛,但必須安裝相應的預處理器本身

# .scss and .sass
npm add -D sass
 
# .less
npm add -D less
 
# .styl and .stylus
npm add -D stylus

查看 Vite 的文檔 以獲取更多資訊。

Tailwind

如需在您的應用程式中使用 Tailwind,可以使用我們內建的整合功能將其新增至您的應用程式中

npm run qwik add tailwind

查看整合文件以取得更多資訊。

PostCSS

您也可以使用我們內建的整合功能在您的應用程式中使用 PostCSS

npm run qwik add postcss

重要提示:由於我們使用的是 vite,因此組態應如下所示才能正常運作

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

現在,您將能夠使用嵌套規則的 CSS,如下所示

body {
  & .box {
    background: red;
 
    &:hover {
      background: yellow;
    }
  }
}

查看整合文件以取得更多資訊。

為什麼不使用 <style> 標籤設定 inline 樣式?

一種確保元件載入正確樣式的簡單方法是將樣式資訊內嵌到元件中,如下所示。

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

這種方法的問題在於我們會載入兩次樣式。

  1. 樣式會作為 SSR 的一部分插入到 HTML 中。
  2. 然後,當元件失效並需要重新渲染時,由於樣式是內嵌的,因此會再次載入。

我們需要做的是獨立於元件載入樣式。這就是useStyles$()的用途。有兩種情況

  1. 元件會在伺服器上渲染,並且樣式會作為 SSR 的一部分插入到 <head> 中。
    • 將元件的新執行個體新增到應用程式中並不需要我們載入樣式,因為它們已作為 SSR 的一部分包含在內。
  2. 元件首次在客戶端上渲染。在這種情況下,新的元件在 <head> 中沒有樣式,因為該元件不是 SSR 的一部分。
    • 新增不是 SSR 一部分的元件需要載入樣式並將其插入到 <head> 中。

貢獻者

感謝所有讓這份文件變得更好的貢獻者!

  • manucorporat
  • zanettin
  • cunzaizhuyi
  • manuelsanchez2
  • literalpie
  • forresst
  • DustinJSilk
  • saikatdas0790
  • LiKang6688
  • Craiqser
  • adamdbradley
  • the-r3aper7
  • mhevery
  • igorbabko
  • mrhoodz
  • tanftw