CSS 樣式
2025年5月28日大约 2 分鐘
學習內容
- 掌握 Nuxt.js 中的樣式組織與引入方式
- 學習字體設定與管理
- 理解 Vue SFC 樣式特性
1. 本地樣式表管理
assets/ 目錄結構
assets/
├── css/
│ ├── main.css
│ └── components.css
├── scss/
│ ├── _variables.scss
│ ├── _mixins.scss
│ └── main.scss
└── fonts/
└── custom-fonts.woff2
全域樣式配置
/* assets/css/main.css */
:root {
--primary-color: #2c3e50;
--secondary-color: #3498db;
--success-color: #27ae60;
--warning-color: #f39c12;
--danger-color: #e74c3c;
--font-main: 'Noto Sans TC', sans-serif;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-main);
line-height: 1.6;
color: #333;
}
/* 電機系配色方案 */
.ee-primary { background-color: var(--primary-color); }
.ee-secondary { background-color: var(--secondary-color); }
.text-primary { color: var(--primary-color); }
.text-secondary { color: var(--secondary-color); }
nuxt.config.js 全域引入
// nuxt.config.js
export default defineNuxtConfig({
css: [
'~/assets/css/main.css'
]
})
2. 字體管理與優化
本地字體設定
/* assets/css/fonts.css */
@font-face {
font-family: 'EE-Display';
src: url('/fonts/ee-display.woff2') format('woff2');
font-weight: normal;
font-style: normal;
font-display: swap;
}
.display-font {
font-family: 'EE-Display', 'Arial', sans-serif;
}
Google Fonts 動態載入
<!-- layouts/default.vue -->
<script setup>
// 動態載入 Google Fonts
useHead({
link: [
{
rel: 'preconnect',
href: 'https://fonts.googleapis.com'
},
{
rel: 'preconnect',
href: 'https://fonts.gstatic.com',
crossorigin: ''
},
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@300;400;500;700&display=swap'
}
]
})
</script>
3. Vue SFC 樣式特性
動態樣式綁定
<!-- components/EquipmentStatus.vue -->
<template>
<div class="equipment-status">
<div
class="status-indicator"
:class="statusClass"
:style="statusStyle"
>
{{ equipment.name }}
</div>
<div class="status-text" :style="{ color: statusColor }">
{{ equipment.status }}
</div>
</div>
</template>
<script setup>
const props = defineProps({
equipment: {
type: Object,
required: true
}
})
// 動態類別計算
const statusClass = computed(() => ({
'status-available': props.equipment.status === '可用',
'status-maintenance': props.equipment.status === '維修中',
'status-borrowed': props.equipment.status === '已借出'
}))
// 動態樣式計算
const statusColor = computed(() => {
switch(props.equipment.status) {
case '可用': return '#27ae60'
case '維修中': return '#e74c3c'
case '已借出': return '#f39c12'
default: return '#95a5a6'
}
})
const statusStyle = computed(() => ({
borderLeftColor: statusColor.value,
borderLeftWidth: '4px'
}))
</script>
<style scoped>
.equipment-status {
background: white;
border-radius: 6px;
padding: 16px;
margin: 8px 0;
border-left: 4px solid #ddd;
transition: all 0.3s ease;
}
.status-indicator {
font-weight: 500;
margin-bottom: 8px;
}
.status-available {
background-color: #d5f4e6;
}
.status-maintenance {
background-color: #ffeaea;
}
.status-borrowed {
background-color: #fff3cd;
}
</style>
v-bind 動態CSS
<!-- components/ThemeCustomizer.vue -->
<template>
<div class="theme-panel">
<h3>介面主題設定</h3>
<div class="controls">
<label>
主色調:
<input type="color" v-model="primaryColor">
</label>
<label>
字體大小:
<input type="range" v-model="fontSize" min="12" max="20">
</label>
</div>
<div class="preview-text">
電機工程系實驗室管理系統
</div>
</div>
</template>
<script setup>
const primaryColor = ref('#2c3e50')
const fontSize = ref(16)
</script>
<style scoped>
.theme-panel {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.preview-text {
margin-top: 20px;
padding: 15px;
background-color: v-bind(primaryColor);
color: white;
font-size: v-bind(fontSize + 'px');
border-radius: 4px;
text-align: center;
}
.controls {
display: flex;
gap: 20px;
margin: 15px 0;
}
.controls label {
display: flex;
flex-direction: column;
gap: 5px;
}
</style>
CSS Modules 使用
<!-- components/ModularCard.vue -->
<template>
<div :class="$style.card">
<h3 :class="$style.title">{{ title }}</h3>
<p :class="$style.content">{{ content }}</p>
<button :class="[$style.button, $style.primary]">
詳細資訊
</button>
</div>
</template>
<script setup>
defineProps({
title: String,
content: String
})
</script>
<style module>
.card {
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.title {
color: #2c3e50;
margin-bottom: 10px;
}
.content {
color: #666;
line-height: 1.6;
margin-bottom: 15px;
}
.button {
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: 500;
}
.primary {
background-color: #3498db;
color: white;
}
.primary:hover {
background-color: #2980b9;
}
</style>