從各種預先樣式化的主題中選擇,或開發自己的主題。
PrimeVue 是一個與設計無關的函式庫,因此與其他一些 UI 函式庫不同,它不會強制使用特定的樣式,例如 Material Design。樣式是透過主題與元件分離的。一個主題包含兩個部分:基礎 和 預設。基礎是帶有 CSS 變數作為佔位符的樣式規則,而預設是一組設計令牌,透過將令牌映射到 CSS 變數來提供基礎。一個基礎可以使用不同的預設進行配置,目前 Aura、Material、Lara 和 Nora 是可用的內建選項。
樣式化模式架構的核心是基於一個名為 設計令牌 的概念,預設定義了三個層級的令牌配置:基本、語意 和 元件。
基本令牌沒有上下文,顏色調色板是基本令牌的一個很好的例子,例如 blue-50 到 blue-900。名為 blue-500 的令牌可以用作主要顏色、訊息的背景,但就其本身而言,令牌的名稱並不表示上下文。它們通常由語意令牌使用。
語意令牌定義了內容,其名稱表示它們的使用位置,一個眾所周知的語意令牌的例子是 primary.color。語意令牌映射到基本令牌或其他語意令牌。colorScheme 令牌群組是一個特殊的變數,用於根據應用程式中活動的色彩配置定義令牌,這允許根據色彩配置(如深色模式)定義不同的令牌。
元件令牌是每個元件的隔離令牌,例如 inputtext.background 或 button.color,它們映射到語意令牌。例如,button.background 元件令牌映射到 primary.color 語意令牌,後者映射到 green.500 基本令牌。
在定義核心顏色調色板時使用基本令牌,並使用語意令牌指定常見的設計元素,例如焦點環、主要顏色和介面。元件令牌應僅在自訂特定元件時使用。透過將您自己的設計令牌定義為自訂預設,您將能夠定義自己的樣式而無需接觸 CSS。使用樣式類別覆寫 PrimeVue 元件不是最佳實務,應該是最後的手段,建議的方法是設計令牌。
觀看 PrimeVue 主題化揭秘 系列,以透過範例了解更多關於架構的資訊。
theme 屬性用於自訂初始主題。
import PrimeVue from 'primevue/config';
import Aura from '@primevue/themes/aura';
const app = createApp(App);
app.use(PrimeVue, {
// Default theme configuration
theme: {
preset: Aura,
options: {
prefix: 'p',
darkModeSelector: 'system',
cssLayer: false
}
}
});
options 屬性定義了 CSS 將如何從預設的設計令牌產生。
CSS 變數的前綴,預設為 p。例如,primary.color 設計令牌將是 var(--p-primary-color)。
options: {
prefix: 'my'
}
封裝深色模式 CSS 變數的 CSS 規則,預設為 system 以產生 @media (prefers-color-scheme: dark)。如果您需要根據使用者選擇使深色模式可切換,請定義一個類別選取器,例如 .app-dark 並在文件根目錄切換此類別。請參閱深色模式切換部分以了解範例。
options: {
darkModeSelector: '.my-app-dark'
}
定義樣式是否應預設在 CSS 層 內定義。如果需要,CSS 層可以方便地聲明自訂級聯層,以便於自訂。預設值為 false。
options: {
cssLayer: {
name: 'primevue',
order: 'app-styles, primevue, another-css-library'
}
}
Aura、Material、Lara 和 Nora 是可用的內建選項,旨在展示與設計無關的主題化的強大功能。Aura 是 PrimeTek 自己的願景,Material 遵循 Google Material Design v2,Lara 基於 Bootstrap,而 Nora 的靈感來自企業應用程式。請造訪 原始碼 以了解更多關於預設結構的資訊。您可以直接使用它們並進行修改,或者在需要從頭開始建立自己的預設時將它們用作參考。
令牌使用點分隔符描述,例如 primary.color、form.field.background 或 checkbox.icon.checked.color。在預設配置中,當映射點分隔符時,會使用駝峰式大小寫和物件屬性。以下是來自核取方塊元件令牌的範例,用於表示 checkbox.icon.checked.color,所有替代方案都具有相同的結果。
export default {
iconCheckedColor: //...,
}
export default {
icon: {
checkedColor: //...
}
}
export default {
icon: {
checked: {
color: //...
}
}
}
以下鍵在預設方案中保留,不能用作令牌名稱:primitive、semantic、components、directives、colorscheme、light、dark、common、root、states 和 extend。
預設的色彩調色板由 primitive 設計令牌群組定義。您可以使用 CSS 變數或 $dt 實用程式存取色彩。
// With CSS
var(--p-blue-500)
// With JS
$dt('blue.500').value
PrimeVue 使用 system 作為主題設定中的預設 darkModeSelector。如果您的應用程式中有深色模式開關,請將 darkModeSelector 設定為您使用的選取器,例如 .my-app-dark,以便 PrimeVue 可以與您的色彩配置無縫配合。
import PrimeVue from 'primevue/config';
import Aura from '@primevue/themes/aura';
const app = createApp(App);
app.use(PrimeVue, {
// Default theme configuration
theme: {
preset: Aura,
options: {
darkModeSelector: '.my-app-dark',
}
}
});
以下是深色模式開關的一個非常基本的範例實作,您可以透過加入 prefers-color-scheme 來進一步擴展它,以從系統中初始檢索它,並使用 localStorage 使其具有狀態。請參閱此 文章 以了解更多資訊。
<Button label="Toggle Dark Mode" @click="toggleDarkMode()" />
function toggleDarkMode() {
document.documentElement.classList.toggle('my-app-dark');
}
如果您希望一直使用深色模式,請初始套用 darkModeSelector,並且永遠不要更改它。
<html class="my-app-dark">
也可以使用 false 或 none 作為選取器的值來完全停用深色模式。
theme: {
preset: Aura,
options: {
darkModeSelector: false || 'none',
}
}
definePreset 實用程式用於在 PrimeVue 設定期間自訂現有的預設。第一個參數是要自訂的預設,第二個參數是要覆寫的設計令牌。
import PrimeVue from 'primevue/config';
import { definePreset } from '@primevue/themes';
import Aura from '@primevue/themes/aura';
const MyPreset = definePreset(Aura, {
//Your customizations, see the following sections for examples
});
app.use(PrimeVue, {
theme: {
preset: MyPreset
}
});
primary 定義了主要顏色調色板,預設值映射到 emerald 基本令牌。讓我們設定為改用 indigo。
const MyPreset = definePreset(Aura, {
semantic: {
primary: {
50: '{indigo.50}',
100: '{indigo.100}',
200: '{indigo.200}',
300: '{indigo.300}',
400: '{indigo.400}',
500: '{indigo.500}',
600: '{indigo.600}',
700: '{indigo.700}',
800: '{indigo.800}',
900: '{indigo.900}',
950: '{indigo.950}'
}
}
});
在淺色和深色模式之間變化的色彩配置調色板是使用介面令牌指定的。以下範例在淺色模式下使用 zinc,在深色模式下使用 slategray。透過此設定,淺色模式將具有灰階色調,而深色模式將包含藍色調。
const MyPreset = definePreset(Aura, {
semantic: {
colorScheme: {
light: {
surface: {
0: '#ffffff',
50: '{zinc.50}',
100: '{zinc.100}',
200: '{zinc.200}',
300: '{zinc.300}',
400: '{zinc.400}',
500: '{zinc.500}',
600: '{zinc.600}',
700: '{zinc.700}',
800: '{zinc.800}',
900: '{zinc.900}',
950: '{zinc.950}'
}
},
dark: {
surface: {
0: '#ffffff',
50: '{slate.50}',
100: '{slate.100}',
200: '{slate.200}',
300: '{slate.300}',
400: '{slate.400}',
500: '{slate.500}',
600: '{slate.600}',
700: '{slate.700}',
800: '{slate.800}',
900: '{slate.900}',
950: '{slate.950}'
}
}
}
}
});
noir 模式是一種變體的暱稱,該變體使用介面色調作為主要顏色,並且需要額外的 colorScheme 配置才能實作。一個以黑色和白色變體作為主要顏色的範例預設配置;
const Noir = definePreset(Aura, {
semantic: {
primary: {
50: '{zinc.50}',
100: '{zinc.100}',
200: '{zinc.200}',
300: '{zinc.300}',
400: '{zinc.400}',
500: '{zinc.500}',
600: '{zinc.600}',
700: '{zinc.700}',
800: '{zinc.800}',
900: '{zinc.900}',
950: '{zinc.950}'
},
colorScheme: {
light: {
primary: {
color: '{zinc.950}',
inverseColor: '#ffffff',
hoverColor: '{zinc.900}',
activeColor: '{zinc.800}'
},
highlight: {
background: '{zinc.950}',
focusBackground: '{zinc.700}',
color: '#ffffff',
focusColor: '#ffffff'
}
},
dark: {
primary: {
color: '{zinc.50}',
inverseColor: '{zinc.950}',
hoverColor: '{zinc.100}',
activeColor: '{zinc.200}'
},
highlight: {
background: 'rgba(250, 250, 250, .16)',
focusBackground: 'rgba(250, 250, 250, .24)',
color: 'rgba(255,255,255,.87)',
focusColor: 'rgba(255,255,255,.87)'
}
}
}
}
});
UI 元件從應用程式繼承其字體設定,因此沒有字體設計。
表單輸入元件的設計令牌來自 form.field 令牌群組。這個自訂範例將滑鼠懸停時的邊框顏色變更為主要顏色。任何依賴此語意令牌的元件,例如 dropdown.hover.border.color 和 textarea.hover.border.color 都會收到變更。
const MyPreset = definePreset(Aura, {
semantic: {
colorScheme: {
light: {
formField: {
hoverBorderColor: '{primary.color}'
}
},
dark: {
formField: {
hoverBorderColor: '{primary.color}'
}
}
}
}
});
焦點環定義了外框的寬度、樣式、顏色和偏移量。讓我們使用較粗的環,並使用主要顏色作為外框。
const MyPreset = definePreset(Aura, {
semantic: {
focusRing: {
width: '2px',
style: 'dashed',
color: '{primary.color}',
offset: '1px'
}
}
});
特定元件的設計令牌 (design tokens) 定義於 components 層級。如果您要建立自己的樣式,不建議覆寫元件令牌,而應該優先建立自己的預設 (preset)。此設定是全域性的,會套用到所有卡片元件。如果您需要在本機頁面上自訂特定元件,請參閱「Scoped CSS」章節的範例。
const MyPreset = definePreset(Aura, {
components: {
card: {
colorScheme: {
light: {
root: {
background: '{surface.0}',
color: '{surface.700}'
},
subtitle: {
color: '{surface.500}'
}
},
dark: {
root: {
background: '{surface.900}',
color: '{surface.0}'
},
subtitle: {
color: '{surface.400}'
}
}
}
}
}
});
主題系統可以透過新增自訂設計令牌和額外樣式來擴充。此功能提供高度的自訂能力,讓您可以根據自己的需求調整樣式,因為您不受限於預設令牌。
範例預設配置新增了一個新的 accent 按鈕,其中包含自訂的 button.accent.color 和 button.accent.inverse.color 令牌。也可以全域新增令牌,以便在元件之間共用。
const MyPreset = definePreset(Aura, {
components: {
// custom button tokens and additional style
button: {
extend: {
accent: {
color: '#f59e0b',
inverseColor: '#ffffff'
}
}
css: ({ dt }) => `
.p-button-accent {
background: ${dt('button.accent.color')};
color: ${dt('button.accent.inverse.color')};
transition-duration: ${dt('my.transition.fast')};
}
`
}
},
// common tokens and styles
extend: {
my: {
transition: {
slow: '0.75s'
normal: '0.5s'
fast: '0.25s'
},
imageDisplay: 'block'
}
},
css: ({ dt }) => `
/* Global CSS */
img {
display: ${dt('my.image.display')};
}
`
});
設計令牌可以使用 dt 屬性將作用域限定於特定元件。在此範例中,第一個切換開關使用全域令牌,而第二個則使用自己的令牌覆寫全域令牌。
建議使用此方法,而非 :deep(),因為它提供更清晰的 API,同時避免了 CSS 規則覆寫的麻煩。
<template>
<div>
<ToggleSwitch v-model="checked1" />
<ToggleSwitch v-model="checked2" :dt="amberSwitch" />
</div>
</template>
<script setup>
import { ref } from 'vue';
const checked1 = ref(true);
const checked2 = ref(true);
const amberSwitch = ref({
handle: {
borderRadius: '4px'
},
colorScheme: {
light: {
root: {
checkedBackground: '{amber.500}',
checkedHoverBackground: '{amber.600}',
borderRadius: '4px'
},
handle: {
checkedBackground: '{amber.50}',
checkedHoverBackground: '{amber.100}'
}
},
dark: {
root: {
checkedBackground: '{amber.400}',
checkedHoverBackground: '{amber.300}',
borderRadius: '4px'
},
handle: {
checkedBackground: '{amber.900}',
checkedHoverBackground: '{amber.800}'
}
}
}
});
</script>
完全取代目前的預設,常見的使用案例是在執行階段動態變更預設。
import { usePreset } from '@primevue/themes';
const onButtonClick() {
usePreset(MyPreset);
}
將提供的令牌合併到目前的預設中,例如動態變更主要調色盤 (primary color palette)。
import { updatePreset } from '@primevue/themes';
const changePrimaryColor() {
updatePreset({
semantic: {
primary: {
50: '{indigo.50}',
100: '{indigo.100}',
200: '{indigo.200}',
300: '{indigo.300}',
400: '{indigo.400}',
500: '{indigo.500}',
600: '{indigo.600}',
700: '{indigo.700}',
800: '{indigo.800}',
900: '{indigo.900}',
950: '{indigo.950}'
}
}
})
}
更新主要顏色,這是使用 updatePreset 進行相同更新的簡寫。
import { updatePrimaryPalette } from '@primevue/themes';
const changePrimaryColor() {
updatePrimaryPalette({
50: '{indigo.50}',
100: '{indigo.100}',
200: '{indigo.200}',
300: '{indigo.300}',
400: '{indigo.400}',
500: '{indigo.500}',
600: '{indigo.600}',
700: '{indigo.700}',
800: '{indigo.800}',
900: '{indigo.900}',
950: '{indigo.950}'
});
}
更新表面顏色,這是使用 updatePreset 進行相同更新的簡寫。
import { updateSurfacePalette } from '@primevue/themes';
const changeSurfaces() {
//changes surfaces both in light and dark mode
updateSurfacePalette({
50: '{zinc.50}',
// ...
950: '{zinc.950}'
});
}
const changeLightSurfaces() {
//changes surfaces only in light
updateSurfacePalette({
light: {
50: '{zinc.50}',
// ...
950: '{zinc.950}'
}
});
}
const changeDarkSurfaces() {
//changes surfaces only in dark mode
updateSurfacePalette({
dark: {
50: '{zinc.50}',
// ...
950: '{zinc.950}'
}
});
}
$dt 函數會傳回令牌的相關資訊,例如完整路徑和值。如果您需要以程式設計方式存取令牌,這會很有用。
import { $dt } from '@primevue/themes';
const duration = $dt('transition.duration');
/*
duration: {
name: '--transition-duration',
variable: 'var(--p-transition-duration)',
value: '0.2s'
}
*/
const primaryColor = $dt('primary.color');
/*
primaryColor: {
name: '--primary-color',
variable: 'var(--p-primary-color)',
value: {
light: {
value: '#10b981',
paths: {
name: 'semantic.primary.color',
binding: {
name: 'primitive.emerald.500'
}
}
},
dark: {
value: '#34d399',
paths: {
name: 'semantic.primary.color',
binding: {
name: 'primitive.emerald.400'
}
}
}
}
}
*/
以物件形式傳回指定顏色從 50 到 950 的深淺色調。
import { palette } from '@primevue/themes';
// custom color
const values1 = palette('#10b981');
// copy an existing token set
const primaryColor = palette('{blue}');
只有在主題配置中明確啟用分層時,PrimeVue CSS 層才會套用至樣式模式。在非樣式模式中,不包含內建 CSS 類別,因此不需要任何層。
@layer 是一個標準 CSS 功能,用於定義可自訂優先順序的串接層。如果您需要更熟悉圖層,請造訪 MDN 的文件以開始。
cssLayer 預設為停用。當在主題配置中啟用時,PrimeVue 會將內建樣式類別包裝在 primevue 串接層下,以便輕鬆覆寫程式庫樣式。應用程式中沒有圖層的 CSS 具有最高的 CSS 特殊性,因此無論位置或類別的寫法強度如何,您都可以覆寫樣式。
圖層還可讓您更輕鬆地使用 CSS 模組,請參閱 CSS 模組指南以取得範例。
如果 PrimeVue 元件在您的應用程式中出現視覺問題,則可能是 Reset CSS 造成的。CSS 圖層會是一個有效的解決方案,其中包含啟用 PrimeVue 圖層、將 Reset CSS 包裝在另一個圖層中,並定義圖層順序。如此一來,您的 Reset CSS 就不會妨礙 PrimeVue 元件。
/* Order */
@layer reset, primevue;
/* Reset CSS */
@layer reset {
button,
input {
/* CSS to Reset */
}
}
透過啟用 SFC 中樣式元素上的 module 屬性,可以支援 CSS 模組。使用 $style 關鍵字將類別套用至 PrimeVue 元件。建議在使用 CSS 模組時啟用 cssLayer,以便讓 PrimeVue 樣式具有較低的 CSS 特殊性。
<style module>
.myinput {
border-radius: 2rem;
padding: 1rem 2rem;
border-width: 2px;
}
</style>
<template>
<InputText :class="$style.myinput" placeholder="Search" />
</template>
PrimeVue UI 元件使用 rem 單位,1rem 等於 html 元素的字型大小,預設為 16px。使用根字型大小來全域調整元件的大小。本網站使用 14px 作為基準,因此如果您的基準字型大小不同,則可能會與您的應用程式有所差異。
html {
font-size: 14px;
}