Tailwind CSS

PrimeVue 與 Tailwind CSS 在樣式化和非樣式化模式下的整合。

Tailwind CSS 是一個基於實用優先設計的熱門 CSS 框架。核心提供具有預定義 CSS 規則的彈性 CSS 類別,以建構您自己的 UI 元素。例如,Tailwind 不像 Bootstrap 中有武斷的btn類別,而是提供像bg-blue-500roundedp-4 等原始類別來套用按鈕。一組可重複使用的類別也可以組合成 Tailwind CSS 元件,甚至有一些程式庫採用這種方法來專門為 Tailwind 建構元件。

Tailwind 是一個出色的 CSS 程式庫,但是當與 Vue.js 結合使用時,它缺乏真正的全面 UI 套件,這就是 PrimeVue 發揮作用的地方,它提供各種高度易於存取且功能豐富的 UI 元件程式庫。PrimeVue 的核心不依賴 Tailwind CSS,相反,我們提供必要的整合點,例如 primeui tailwind 外掛程式和用於非樣式化模式的 Tailwind 版本。

Tailwind CSS 和 PrimeVue 可以透過兩種主要方法一起使用。簡單的方法是像以下範例部分中所示,在 PrimeVue 元件周圍使用 Tailwind CSS 進行版面配置,進階方法更進一步,允許在元件內部使用 Tailwind CSS 以在非樣式化模式中設定整個 UI 套件的樣式。

PrimeTek 在非樣式化模式下提供整個 PrimeVue UI 套件的 Tailwind CSS 版本,它基於具有 IntelliSense 支援的@apply 指令。請造訪PrimeVue 的 Tailwind 版本,以取得文件、示範和其他資源。

tailwindcss-primeui 是 PrimeTek 的官方外掛程式,旨在提供 Prime UI 程式庫(如 PrimeVue)和 Tailwind CSS 之間的一流整合。它旨在以樣式化和非樣式化模式運作。在樣式化模式中,例如,像主要和表面這樣的語義顏色會作為 Tailwind 公用程式提供,例如 bg-primarytext-surface-500text-muted-color

外掛程式可在 npm 上取得。


npm i tailwindcss-primeui

安裝後,在您的 tailwind 設定檔中設定外掛程式。


// tailwind.config.js
module.exports = {
    // ...
    plugins: [require('tailwindcss-primeui')]
};

外掛程式會以一組新的公用程式擴充預設組態。所有變體和中斷點都受支援,例如 dark:sm:hover:bg-primary

調色盤

類別屬性
primary-[50-950]主要調色盤。
surface-[0-950]表面調色盤。
primary預設主要顏色。
primary-contrast預設主要對比色。
primary-emphasis預設主要強調顏色。
border-surface預設主要強調顏色。
bg-emphasis強調背景,例如懸停的元素。
bg-highlight醒目提示背景。
bg-highlight-emphasis具有強調的醒目提示背景。
rounded-border邊框半徑。
text-color具有強調的文字顏色。
text-color-emphasis預設主要強調顏色。
text-muted-color次要文字顏色。
text-muted-color-emphasis具有強調的次要文字顏色。

在樣式化模式中,由於 CSS 特異性,Tailwind 公用程式可能無法覆寫預設樣式,有兩種可能的解決方案。

重要

使用 ! 作為前置詞來強制執行樣式設定。


<InputText placeholder="Overriden" class="!p-8" />

CSS 層

啟用 PrimeVue CSS 層,並設定 tailwind 樣式以透過分層具有更高的特異性。如此一來,就不需要 ! 前置詞。


import PrimeVue from 'primevue/config';
import Aura from '@primevue/themes/aura';

const app = createApp(App);

app.use(PrimeVue, {
    theme: {
        preset: Aura,
        options: {
            cssLayer: {
                name: 'primevue',
                order: 'tailwind-base, primevue, tailwind-utilities'
            }
        }
    }
 });


@layer tailwind-base, primevue, tailwind-utilities;

@layer tailwind-base {
  @tailwind base;
}

@layer tailwind-utilities {
  @tailwind components;
  @tailwind utilities;
}

PrimeVue 和 Tailwind CSS 的範例使用案例。

PrimeVue 調色盤作為公用程式類別。

  • primary
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
  • surface
    0
    50
    100
    200
    300
    400
    500
    600
    700
    800
    900
    950
primary
highlight
box

<div class="flex flex-col gap-12">
    <div class="flex gap-6 flex-wrap">
        <div class="rounded-border p-4 border border-transparent flex items-center justify-center bg-primary hover:bg-primary-emphasis text-primary-contrast font-medium flex-auto transition-colors">primary</div>
        <div class="rounded-border p-4 border border-transparent flex items-center justify-center bg-highlight hover:bg-highlight-emphasis font-medium flex-auto transition-colors">highlight</div>
        <div class="rounded-border p-4 border border-surface flex items-center justify-center text-muted-color hover:text-color hover:bg-emphasis font-medium flex-auto transition-colors">box</div>
    </div>
</div>

使用 Tailwind 公用程式來設定具有 PrimeVue 元件的表單的響應式版面配置。


<div class="flex flex-col gap-6 w-full sm:w-auto">
    <div class="flex flex-col sm:flex-row sm:items-center gap-6">
        <div class="flex-auto">
            <label for="firstname" class="block font-semibold mb-2">Firstname</label>
            <InputText id="firstname" class="w-full" />
        </div>
        <div class="flex-auto">
            <label for="lastname" class="block font-semibold mb-2">Lastname</label>
            <InputText id="lastname" class="w-full" />
        </div>
    </div>
    <div class="flex flex-col sm:flex-row sm:items-center gap-6">
        <div class="flex-1">
            <label for="date" class="block font-semibold mb-2">Date</label>
            <DatePicker inputId="date" class="w-full" />
        </div>
        <div class="flex-1">
            <label for="country" class="block font-semibold mb-2">Country</label>
            <Select v-model="selectedCountry" inputId="country" :options="countries" optionLabel="name" placeholder="Select a Country" class="w-full">
                <template #value="slotProps">
                    <div v-if="slotProps.value" class="flex items-center">
                        <img :alt="slotProps.value.label" src="https://primefaces.org/cdn/primevue/images/flag/flag_placeholder.png" :class="`mr-2 flag flag-${slotProps.value.code.toLowerCase()}`" style="width: 18px" />
                        <div>{{ slotProps.value.name }}</div>
                    </div>
                    <span v-else>
                        {{ slotProps.placeholder }}
                    </span>
                </template>
                <template #option="slotProps">
                    <div class="flex items-center">
                        <img :alt="slotProps.option.label" src="https://primefaces.org/cdn/primevue/images/flag/flag_placeholder.png" :class="`mr-2 flag flag-${slotProps.option.code.toLowerCase()}`" style="width: 18px" />
                        <div>{{ slotProps.option.name }}</div>
                    </div>
                </template>
            </Select>
        </div>
    </div>
    <div class="flex-auto">
        <label for="message" class="block font-semibold mb-2">Message</label>
        <Textarea id="message" class="w-full" rows="4" />
    </div>
</div>

具有自訂 UI 的無頭 PrimeVue 對話方塊。


<Button label="Login" icon="pi pi-user" @click="visible = true" />

<Dialog v-model:visible="visible" pt:root:class="!border-0 !bg-transparent" pt:mask:class="backdrop-blur-sm">
    <template #container="{ closeCallback }">
        <div class="flex flex-col px-8 py-8 gap-6 rounded-2xl" style="background-image: radial-gradient(circle at left top, var(--p-primary-400), var(--p-primary-700))">
            <svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="block mx-auto">
                <path
                    d="M25.87 18.05L23.16 17.45L25.27 20.46V29.78L32.49 23.76V13.53L29.18 14.73L25.87 18.04V18.05ZM25.27 35.49L29.18 31.58V27.67L25.27 30.98V35.49ZM20.16 17.14H20.03H20.17H20.16ZM30.1 5.19L34.89 4.81L33.08 12.33L24.1 15.67L30.08 5.2L30.1 5.19ZM5.72 14.74L2.41 13.54V23.77L9.63 29.79V20.47L11.74 17.46L9.03 18.06L5.72 14.75V14.74ZM9.63 30.98L5.72 27.67V31.58L9.63 35.49V30.98ZM4.8 5.2L10.78 15.67L1.81 12.33L0 4.81L4.79 5.19L4.8 5.2ZM24.37 21.05V34.59L22.56 37.29L20.46 39.4H14.44L12.34 37.29L10.53 34.59V21.05L12.42 18.23L17.45 26.8L22.48 18.23L24.37 21.05ZM22.85 0L22.57 0.69L17.45 13.08L12.33 0.69L12.05 0H22.85Z"
                    fill="var(--p-primary-700)"
                />
                <path
                    d="M30.69 4.21L24.37 4.81L22.57 0.69L22.86 0H26.48L30.69 4.21ZM23.75 5.67L22.66 3.08L18.05 14.24V17.14H19.7H20.03H20.16H20.2L24.1 15.7L30.11 5.19L23.75 5.67ZM4.21002 4.21L10.53 4.81L12.33 0.69L12.05 0H8.43002L4.22002 4.21H4.21002ZM21.9 17.4L20.6 18.2H14.3L13 17.4L12.4 18.2L12.42 18.23L17.45 26.8L22.48 18.23L22.5 18.2L21.9 17.4ZM4.79002 5.19L10.8 15.7L14.7 17.14H14.74H15.2H16.85V14.24L12.24 3.09L11.15 5.68L4.79002 5.2V5.19Z"
                    fill="var(--p-primary-200)"
                />
            </svg>
            <div class="inline-flex flex-col gap-2">
                <label for="username" class="text-primary-50 font-semibold">Username</label>
                <InputText id="username" class="!bg-white/20 !border-0 !p-4 !text-primary-50 w-80"></InputText>
            </div>
            <div class="inline-flex flex-col gap-2">
                <label for="password" class="text-primary-50 font-semibold">Password</label>
                <InputText id="password" class="!bg-white/20 !border-0 !p-4 !text-primary-50 w-80" type="password"></InputText>
            </div>
            <div class="flex items-center gap-4">
                <Button label="Cancel" @click="closeCallback" text class="!p-4 w-full !text-primary-50 !border !border-white/30 hover:!bg-white/10"></Button>
                <Button label="Sign-In" @click="closeCallback" text class="!p-4 w-full !text-primary-50 !border !border-white/30 hover:!bg-white/10"></Button>
            </div>
        </div>
    </template>
</Dialog>

外掛程式也會新增擴充的動畫公用程式,這些公用程式可與樣式類別滾動時動畫指令一起使用。


<Select v-model="animation" :options="animations" placeholder="Select One" class="w-full sm:w-44" />
<div class="py-8 overflow-hidden">
    <div :class="`rounded-border bg-primary w-16 h-16 mx-auto animate-${animation} animate-once animate-duration-1000`"></div>
</div>

動畫

類別屬性
animate-fadeinfadein 0.15s linear
animate-fadeoutfadeout 0.15s linear
animate-slidedownslidedown 0.45s ease-in-out
animate-slideupslideup 0.45s cubic-bezier(0, 1, 0, 1)
animate-scaleinscalein 0.15s linear
animate-fadeinleftfadeinleft 0.15s linear
animate-fadeoutleftfadeoutleft 0.15s linear
animate-fadeinrightfadeinright 0.15s linear
animate-fadeoutrightfadeoutright 0.15s linear
animate-fadeinupfadeinup 0.15s linear
animate-fadeoutupfadeoutup 0.15s linear
animate-fadeindownfadeindown 0.15s linear
animate-fadeoutupfadeoutup 0.15s linear
animate-widthwidth 0.15s linear
animate-flipflip 0.15s linear
animate-flipupflipup 0.15s linear
animate-flipleftfadein 0.15s linear
animate-fliprightflipright 0.15s linear
animate-zoominzoomin 0.15s linear
animate-zoomindownzoomindown 0.15s linear
animate-zoominleftzoominleft 0.15s linear
animate-zoominrightzoominright 0.15s linear
animate-zoominupzoominup 0.15s linear

動畫持續時間

類別屬性
animate-duration-0animation-duration: 0s
animate-duration-75animation-duration: 75ms
animate-duration-100animation-duration: 100ms
animate-duration-200animation-duration: 200ms
animate-duration-300animation-duration: 300ms
animate-duration-400animation-duration: 400ms
animate-duration-500animation-duration: 500ms
animate-duration-700animation-duration: 700ms
animate-duration-1000animation-duration: 1000ms
animate-duration-2000animation-duration: 2000ms
animate-duration-3000animation-duration: 300ms

動畫延遲

類別屬性
animate-delay-noneanimation-duration: 0s
animate-delay-75animation-delay: 75ms
animate-delay-100animation-delay: 100ms
animate-delay-150animation-delay: 150ms
animate-delay-200animation-delay: 200ms
animate-delay-300animation-delay: 300ms
animate-delay-400animation-delay: 400ms
animate-delay-500animation-delay: 500ms
animate-delay-700animation-delay: 700ms
animate-delay-1000animation-delay: 1000ms

反覆計數

類別屬性
animate-infiniteanimation-iteration-count: infinite
animate-onceanimation-iteration-count: 1
animate-twiceanimation-iteration-count: 2

方向

類別屬性
animate-normalanimation-direction: normal
animate-reverseanimation-direction: reverse
animate-alternateanimation-direction: alternate
animate-alternate-reverseanimation-direction: alternate-reverse

時間函數

類別屬性
animate-ease-linearanimation-timing-function: linear
animate-ease-inanimation-timing-function: cubic-bezier(0.4, 0, 1, 1)
動畫-緩和結束animation-timing-function: cubic-bezier(0, 0, 0.2, 1)
動畫-緩和開始與結束animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1)

填充模式

類別屬性
動畫-不填充animation-fill-mode: normal
動畫-向前填充animation-fill-mode: forwards
動畫-向後填充animation-fill-mode: backwards
動畫-雙向填充animation-fill-mode: both

播放狀態

類別屬性
動畫-執行中animation-play-state: running
動畫-暫停animation-play-state: paused

背面可見性狀態

類別屬性
背面-可見backface-visibility: visible
背面-隱藏backface-visibility: hidden