樣式設定
Nuxt 在樣式設定方面非常彈性。您可以編寫自己的樣式,或參考本機和外部樣式表。您可以使用 CSS 預處理器、CSS 框架、UI 函式庫和 Nuxt 模組來設定應用程式的樣式。
本機樣式表
如果您要編寫本機樣式表,自然放置的位置是 assets/
目錄。
在元件中匯入
您可以直接在您的頁面、版面配置和元件中匯入樣式表。您可以使用 javascript 匯入,或 css @import
宣告。
<script>
// Use a static import for server-side compatibility
import '~/assets/css/first.css'
// Caution: Dynamic imports are not server-side compatible
import('~/assets/css/first.css')
</script>
<style>
@import url("~/assets/css/second.css");
</style>
CSS 屬性
您也可以在 Nuxt 設定中使用 css
屬性。樣式表自然放置的位置是 assets/
目錄。然後您可以參考其路徑,Nuxt 會將其包含在應用程式的所有頁面中。
export default defineNuxtConfig({
css: ['~/assets/css/main.css']
})
使用字型
將您的本機字型檔案放在您的 ~/public/
目錄中,例如在 ~/public/fonts
中。然後您可以使用 url()
在樣式表中參考它們。
@font-face {
font-family: 'FarAwayGalaxy';
src: url('/fonts/FarAwayGalaxy.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
然後在您的樣式表、頁面或元件中依名稱參考您的字型
<style>
h1 {
font-family: 'FarAwayGalaxy', sans-serif;
}
</style>
透過 NPM 發佈的樣式表
您也可以參考透過 npm 發佈的樣式表。讓我們以流行的 animate.css
函式庫為例。
npm install animate.css
然後您可以直接在您的頁面、版面配置和元件中參考它
<script>
import 'animate.css'
</script>
<style>
@import url("animate.css");
</style>
該套件也可以作為字串在您的 Nuxt 設定的 css 屬性中參考。
export default defineNuxtConfig({
css: ['animate.css']
})
外部樣式表
您可以透過在您的 nuxt.config 檔案的 head 區段中新增 link 元素,將外部樣式表包含在您的應用程式中。您可以使用不同的方法來達成此結果。請注意,本機樣式表也可以像這樣包含。
您可以使用 Nuxt 設定的 app.head
屬性來操作 head
export default defineNuxtConfig({
app: {
head: {
link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }]
}
}
})
動態新增樣式表
您可以使用 useHead composable 在您的程式碼中動態設定 head 中的值。
useHead({
link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }]
})
Nuxt 在底層使用 unhead
,您可以參考其完整的文件 這裡。
使用 Nitro 插件修改渲染的 Head
如果您需要更進階的控制,您可以攔截渲染的 html 與 hook 並以程式方式修改 head。
在 ~/server/plugins/my-plugin.ts
中建立一個插件,如下所示
export default defineNitroPlugin((nitro) => {
nitro.hooks.hook('render:html', (html) => {
html.head.push('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">')
})
})
外部樣式表是渲染阻塞資源:它們必須在瀏覽器渲染頁面之前載入和處理。包含不必要的大型樣式的網頁需要更長的時間才能渲染。您可以在 web.dev 上閱讀更多相關資訊。
使用預處理器
要使用像 SCSS、Sass、Less 或 Stylus 這樣的預處理器,請先安裝它。
npm install -D sass
編寫樣式表自然的位置是 assets
目錄。然後您可以使用預處理器的語法,在您的 app.vue
(或版面配置檔案) 中匯入您的原始檔。
<style lang="scss">
@use "~/assets/scss/main.scss";
</style>
或者,您可以使用 Nuxt 設定的 css
屬性。
export default defineNuxtConfig({
css: ['~/assets/scss/main.scss']
})
如果您需要在預處理檔案中注入程式碼,例如包含顏色變數的 sass partial,您可以使用 vite preprocessors options 來完成。
在您的 assets
目錄中建立一些 partials
$primary: #49240F;
$secondary: #E4A79D;
然後在您的 nuxt.config
中
export default defineNuxtConfig({
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "~/assets/_colors.scss" as *;'
}
}
}
}
})
Nuxt 預設使用 Vite。如果您希望改用 webpack,請參考每個預處理器載入器的 文件。
預處理器 Worker (實驗性)
Vite 提供了一個 實驗性選項,可以加速預處理器的使用。
您可以在您的 nuxt.config
中啟用此功能
export default defineNuxtConfig({
vite: {
css: {
preprocessorMaxWorkers: true // number of CPUs minus 1
}
}
})
單一檔案元件 (SFC) 樣式設定
Vue 和 SFC 最棒的事情之一是它在自然處理樣式設定方面的優異表現。您可以直接在元件檔案的 style 區塊中編寫 CSS 或預處理器程式碼,因此您將擁有絕佳的開發人員體驗,而無需使用像 CSS-in-JS 這樣的東西。但是,如果您希望使用 CSS-in-JS,您可以找到支援它的第三方函式庫和模組,例如 pinceau。
您可以參考 Vue 文件,以獲得關於在 SFC 中設定元件樣式的完整參考。
Class 和 Style 綁定
您可以利用 Vue SFC 功能,使用 class 和 style 屬性來設定元件的樣式。
<script setup lang="ts">
const isActive = ref(true)
const hasError = ref(false)
const classObject = reactive({
active: true,
'text-danger': false
})
</script>
<template>
<div class="static" :class="{ active: isActive, 'text-danger': hasError }"></div>
<div :class="classObject"></div>
</template>
請參考 Vue 文件 以獲得更多資訊。
使用 v-bind
的動態樣式
您可以使用 v-bind 函式在您的 style 區塊中參考 JavaScript 變數和表達式。綁定將是動態的,這表示如果變數值變更,樣式將會更新。
<script setup lang="ts">
const color = ref("red")
</script>
<template>
<div class="text">hello</div>
</template>
<style>
.text {
color: v-bind(color);
}
</style>
Scoped Styles
scoped 屬性允許您隔離元件的樣式。使用此屬性宣告的樣式只會套用至此元件。
<template>
<div class="example">hi</div>
</template>
<style scoped>
.example {
color: red;
}
</style>
CSS Modules
您可以使用帶有 module 屬性的 CSS Modules。使用注入的 $style
變數來存取它。
<template>
<p :class="$style.red">This should be red</p>
</template>
<style module>
.red {
color: red;
}
</style>
預處理器支援
SFC style 區塊支援預處理器語法。Vite 內建支援 .scss、.sass、.less、.styl 和 .stylus 檔案,無需設定。您只需要先安裝它們,它們就會直接在 SFC 中透過 lang 屬性使用。
<style lang="scss">
/* Write scss here */
</style>
您可以參考 Vite CSS 文件 和 @vitejs/plugin-vue 文件。對於 webpack 使用者,請參考 vue loader 文件。
使用 PostCSS
Nuxt 內建了 postcss。您可以在您的 nuxt.config
檔案中設定它。
export default defineNuxtConfig({
postcss: {
plugins: {
'postcss-nested': {},
'postcss-custom-media': {}
}
}
})
為了在 SFC 中正確地語法突顯,您可以使用 postcss lang 屬性。
<style lang="postcss">
/* Write postcss here */
</style>
預設情況下,Nuxt 已經預先設定了以下插件
- postcss-import:改進
@import
規則 - postcss-url:轉換
url()
宣告 - autoprefixer:自動新增供應商前綴
- cssnano:最小化和清除
利用版面配置實現多種樣式
如果您需要完全不同地設定應用程式不同部分的樣式,您可以使用版面配置。為不同的版面配置使用不同的樣式。
<template>
<div class="default-layout">
<h1>Default Layout</h1>
<slot />
</div>
</template>
<style>
.default-layout {
color: red;
}
</style>
第三方函式庫和模組
Nuxt 在樣式設定方面沒有既定偏好,並為您提供了多種選擇。您可以使用任何您想要的樣式設定工具,例如流行的函式庫,如 UnoCSS 或 Tailwind CSS。
社群和 Nuxt 團隊開發了大量的 Nuxt 模組,使整合更容易。您可以在網站的 模組區 發現它們。以下是一些幫助您入門的模組
- UnoCSS:即時隨需原子化 CSS 引擎
- Tailwind CSS:實用優先的 CSS 框架
- Fontaine:字型度量回退
- Pinceau:適應性樣式框架
- Nuxt UI:現代 Web 應用程式的 UI 函式庫
- Panda CSS:在建置時產生原子化 CSS 的 CSS-in-JS 引擎
Nuxt 模組為您提供了良好的開箱即用開發人員體驗,但請記住,如果您的愛用工具沒有模組,並不代表您不能在 Nuxt 中使用它!您可以為自己的專案自行設定。根據工具的不同,您可能需要使用 Nuxt 插件 和/或 製作自己的模組。如果您這樣做了,請與 社群 分享!
輕鬆載入 Web 字型
您可以使用 Nuxt Google Fonts 模組 來載入 Google 字型。
如果您正在使用 UnoCSS,請注意它帶有一個 web fonts presets,可以方便地從常見的供應商 (包括 Google Fonts 等) 載入字型。
進階
轉場效果
Nuxt 帶有與 Vue 相同的 <Transition>
元素,並且也支援實驗性的 View Transitions API。
字型進階最佳化
我們建議使用 Fontaine 來減少您的 CLS。如果您需要更進階的東西,請考慮建立一個 Nuxt 模組來擴展建置流程或 Nuxt 執行階段。
LCP 進階最佳化
您可以執行以下操作來加速全域 CSS 檔案的下載速度
- 使用 CDN,使檔案在物理位置上更接近您的使用者
- 壓縮您的資源,最好使用 Brotli
- 使用 HTTP2/HTTP3 進行傳輸
- 將您的資源託管在同一個網域上 (不要使用不同的子網域)
如果您正在使用像 Cloudflare、Netlify 或 Vercel 這樣的現代平台,這些事情大多應該會自動為您完成。您可以在 web.dev 上找到 LCP 最佳化指南。
如果您的所有 CSS 都由 Nuxt 內嵌,您可以 (實驗性地) 完全停止在您渲染的 HTML 中參考外部 CSS 檔案。您可以使用 hook 來實現這一點,您可以將其放置在模組或您的 Nuxt 設定檔案中。
export default defineNuxtConfig({
hooks: {
'build:manifest': (manifest) => {
// find the app entry, css list
const css = Object.values(manifest).find(options => options.isEntry)?.css
if (css) {
// start from the end of the array and go to the beginning
for (let i = css.length - 1; i >= 0; i--) {
// if it starts with 'entry', remove it from the list
if (css[i].startsWith('entry')) css.splice(i, 1)
}
}
},
},
})