Vue 3 + Vite 項目 px 轉 vw 完整使用指南
🚀 第一步:插件安裝
1.1 安裝命令
# 使用 npm 安裝
npm install postcss-px-to-viewport-8-plugin --save-dev# 或使用 yarn 安裝
yarn add postcss-px-to-viewport-8-plugin --dev# 或使用 pnpm 安裝
pnpm add postcss-px-to-viewport-8-plugin --save-dev
1.2 驗證安裝
安裝完成后,檢查 package.json
文件中是否包含該依賴:
{"devDependencies": {"postcss-px-to-viewport-8-plugin": "^1.2.5"}
}
?? 第二步:Vite 配置方法
2.1 方法一:直接在 vite.config.js 中配置(推薦)
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import postcssViewport from "postcss-px-to-viewport-8-plugin";export default defineConfig({plugins: [vue()],resolve: {alias: {"@": fileURLToPath(new URL("./src", import.meta.url)),},},css: {postcss: {plugins: [postcssViewport({// 設計稿的視口寬度viewportWidth: 1920,// 設計稿的視口高度(可選)viewportHeight: 1080,// 轉換后的單位精度unitPrecision: 3,// 需要轉換的CSS屬性,* 表示所有屬性propList: ["*"],// 轉換后的視口單位viewportUnit: "vw",// 字體相關屬性轉換后的單位fontViewportUnit: "vw",// 不需要轉換的選擇器selectorBlackList: [".ignore", ".hairlines"],// 最小轉換的像素值,小于這個值的px不會被轉換minPixelValue: 1,// 是否轉換媒體查詢中的pxmediaQuery: false,// 是否直接替換屬性值而不添加備用屬性replace: true,// 忽略某些文件夾下的文件或特定文件exclude: [/node_modules/, /\.min\.css$/],// 只轉換匹配的文件(可選)include: undefined,// 是否添加橫屏時的媒體查詢landscape: false,// 橫屏時使用的單位landscapeUnit: "vw",// 橫屏時的視口寬度landscapeWidth: 568,}),],},},
});
2.2 方法二:使用 postcss.config.js 配置文件
如果項目不使用 ES 模塊(package.json 中沒有"type": “module”),可以創建 postcss.config.js
:
module.exports = {plugins: {"postcss-px-to-viewport-8-plugin": {viewportWidth: 375,viewportHeight: 667,unitPrecision: 3,propList: ["*"],viewportUnit: "vw",fontViewportUnit: "vw",selectorBlackList: [".ignore", ".hairlines"],minPixelValue: 1,mediaQuery: false,replace: true,exclude: [/node_modules/, /\.min\.css$/],include: undefined,landscape: false,landscapeUnit: "vw",landscapeWidth: 568,},},
};
然后在 vite.config.js
中引用:
export default defineConfig({// ...其他配置css: {postcss: "./postcss.config.js",},
});
🧪 第三步:使用示例和驗證方法
3.1 創建測試組件
創建 src/components/PxToVwDemo.vue
:
<template><div class="demo-container"><!-- 頭部區域 --><header class="header"><div class="header-content"><h1 class="main-title"><span class="title-icon">📐</span>px轉vw響應式演示</h1><p class="subtitle">現代化響應式設計工具與演示平臺</p></div><div class="header-bg"></div></header><!-- 控制面板 --><section class="control-panel"><div class="panel-card"><h3 class="panel-title">🎛? 設計稿基準設置</h3><div class="design-width-selector"><buttonv-for="width in designWidths":key="width.value":class="['width-btn', { active: currentDesignWidth === width.value }]"@click="setDesignWidth(width.value)">{{ width.label }}</button></div></div><div class="panel-card"><h3 class="panel-title">🧮 實時轉換計算器</h3><div class="calculator"><div class="input-group"><label>px值:</label><inputv-model.number="pxInput"type="number"placeholder="輸入px值"class="calc-input"/></div><div class="conversion-result"><span class="result-label">轉換結果:</span><span class="result-value">{{ convertedVw }}vw</span><span class="result-desc">(基于{{ currentDesignWidth }}px設計稿)</span></div></div></div></section><!-- 視口信息面板 --><section class="viewport-info"><div class="info-card"><div class="info-item"><span class="info-label">當前視口</span><span class="info-value">{{ viewportWidth }}px</span></div><div class="info-item"><span class="info-label">1vw等于</span><span class="info-value">{{ (viewportWidth / 100).toFixed(2) }}px</span></div><div class="info-item"><span class="info-label">縮放比例</span><span class="info-value">{{ (viewportWidth / currentDesignWidth).toFixed(3) }}</span></div><div class="info-item"><span class="info-label">設備類型</span><span class="info-value">{{ deviceType }}</span></div></div></section><!-- UI組件演示區域 --><section class="demo-section"><h2 class="section-title">🎨 UI組件演示</h2><!-- 按鈕演示 --><div class="demo-card"><h3 class="demo-title">按鈕組件</h3><div class="button-demo"><button class="btn btn-primary">主要按鈕</button><button class="btn btn-secondary">次要按鈕</button><button class="btn btn-success">成功按鈕</button><button class="btn btn-warning">警告按鈕</button><button class="btn btn-danger">危險按鈕</button></div></div><!-- 表單演示 --><div class="demo-card"><h3 class="demo-title">表單組件</h3><div class="form-demo"><div class="form-group"><label class="form-label">用戶名</label><input type="text" class="form-input" placeholder="請輸入用戶名" /></div><div class="form-group"><label class="form-label">郵箱地址</label><input type="email" class="form-input" placeholder="請輸入郵箱" /></div><div class="form-group"><label class="form-label">個人簡介</label><textarea class="form-textarea" placeholder="請輸入個人簡介"></textarea></div></div></div><!-- 卡片演示 --><div class="demo-card"><h3 class="demo-title">卡片組件</h3><div class="card-demo"><div class="feature-card"><div class="card-icon">🚀</div><h4 class="card-title">高性能</h4><p class="card-desc">優化的響應式轉換算法,確保最佳性能表現</p></div><div class="feature-card"><div class="card-icon">🎯</div><h4 class="card-title">精確轉換</h4><p class="card-desc">精確的px到vw轉換,支持多種設計稿基準</p></div><div class="feature-card"><div class="card-icon">📱</div><h4 class="card-title">響應式</h4><p class="card-desc">完美適配各種屏幕尺寸和設備類型</p></div></div></div><!-- 忽略轉換演示 --><div class="demo-card"><h3 class="demo-title">轉換控制演示</h3><div class="ignore-demo"><div class="comparison-group"><div class="comparison-item"><h4>固定尺寸 (ignore)</h4><div class="fixed-box">120px × 80px</div><p class="desc">使用 px-to-viewport-ignore 注釋</p></div><div class="comparison-item"><h4>響應式尺寸</h4><div class="responsive-box">120px × 80px → vw</div><p class="desc">自動轉換為vw單位</p></div></div></div></div></section><!-- 交互演示區域 --><section class="interactive-section"><h2 class="section-title">🎮 交互演示</h2><div class="demo-card"><h3 class="demo-title">Hover效果演示</h3><div class="hover-demo"><div class="hover-card" v-for="i in 6" :key="i"><span class="hover-text">懸停卡片 {{ i }}</span></div></div></div></section></div>
</template><script>import { ref, computed, onMounted, onUnmounted } from 'vue'export default {name: 'PxToVwDemo',setup() {// 響應式數據const viewportWidth = ref(window.innerWidth)const currentDesignWidth = ref(375)const pxInput = ref(24)// 設計稿寬度選項const designWidths = ref([{ label: '移動端 375px', value: 375 },{ label: '平板 750px', value: 750 },{ label: '桌面 1920px', value: 1920 },])// 計算屬性const convertedVw = computed(() => {if (!pxInput.value || !currentDesignWidth.value) return '0.00'return ((pxInput.value / currentDesignWidth.value) * 100).toFixed(2)})const deviceType = computed(() => {const width = viewportWidth.valueif (width < 768) return '📱 移動設備'if (width < 1024) return '📟 平板設備'return '🖥? 桌面設備'})// 方法const updateViewportWidth = () => {viewportWidth.value = window.innerWidth}const setDesignWidth = width => {currentDesignWidth.value = width}// 生命周期onMounted(() => {window.addEventListener('resize', updateViewportWidth)})onUnmounted(() => {window.removeEventListener('resize', updateViewportWidth)})return {viewportWidth,currentDesignWidth,pxInput,designWidths,convertedVw,deviceType,setDesignWidth,}},}
</script><style scoped>/* 全局樣式 */* {box-sizing: border-box;}/* 容器樣式 */.demo-container {min-height: 100vh;background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);padding: 20px;font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;}/* 頭部樣式 */.header {position: relative;text-align: center;margin-bottom: 40px;overflow: hidden;border-radius: 20px;}.header-content {position: relative;z-index: 2;padding: 40px 20px;background: rgba(255, 255, 255, 0.1);backdrop-filter: blur(10px);border: 1px solid rgba(255, 255, 255, 0.2);}.header-bg {position: absolute;top: 0;left: 0;right: 0;bottom: 0;background: linear-gradient(45deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));animation: float 6s ease-in-out infinite;}.main-title {font-size: 32px;font-weight: 700;color: white;margin: 0 0 10px 0;text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);}.title-icon {display: inline-block;margin-right: 10px;font-size: 36px;animation: bounce 2s infinite;}.subtitle {font-size: 16px;color: rgba(255, 255, 255, 0.9);margin: 0;font-weight: 300;}/* 控制面板樣式 */.control-panel {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;margin-bottom: 30px;}.panel-card {background: rgba(255, 255, 255, 0.95);backdrop-filter: blur(10px);border-radius: 16px;padding: 24px;box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);border: 1px solid rgba(255, 255, 255, 0.2);transition:transform 0.3s ease,box-shadow 0.3s ease;}.panel-card:hover {transform: translateY(-5px);box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);}.panel-title {font-size: 18px;font-weight: 600;color: #2c3e50;margin: 0 0 16px 0;}/* 設計稿寬度選擇器 */.design-width-selector {display: flex;gap: 8px;flex-wrap: wrap;}.width-btn {padding: 8px 16px;border: 2px solid #e1e8ed;border-radius: 20px;background: white;color: #657786;font-size: 12px;font-weight: 500;cursor: pointer;transition: all 0.3s ease;white-space: nowrap;}.width-btn:hover {border-color: #667eea;color: #667eea;transform: scale(1.05);}.width-btn.active {background: linear-gradient(135deg, #667eea, #764ba2);border-color: #667eea;color: white;box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);}/* 計算器樣式 */.input-group {margin-bottom: 16px;}.input-group label {display: block;font-size: 14px;font-weight: 500;color: #374151;margin-bottom: 6px;}.calc-input {width: 100%;padding: 12px 16px;border: 2px solid #e5e7eb;border-radius: 12px;font-size: 16px;transition: all 0.3s ease;background: white;}.calc-input:focus {outline: none;border-color: #667eea;box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);}.conversion-result {padding: 16px;background: linear-gradient(135deg, #f8fafc, #e2e8f0);border-radius: 12px;border-left: 4px solid #667eea;}.result-label {font-size: 14px;color: #64748b;font-weight: 500;}.result-value {font-size: 24px;font-weight: 700;color: #667eea;margin: 0 8px;font-family: 'Courier New', monospace;}.result-desc {font-size: 12px;color: #94a3b8;}/* 視口信息樣式 */.viewport-info {margin-bottom: 30px;}.info-card {background: rgba(255, 255, 255, 0.95);backdrop-filter: blur(10px);border-radius: 16px;padding: 24px;box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);border: 1px solid rgba(255, 255, 255, 0.2);display: grid;grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));gap: 20px;}.info-item {text-align: center;padding: 16px;background: linear-gradient(135deg, #f8fafc, #e2e8f0);border-radius: 12px;transition: transform 0.3s ease;}.info-item:hover {transform: scale(1.05);}.info-label {display: block;font-size: 12px;color: #64748b;font-weight: 500;margin-bottom: 8px;text-transform: uppercase;letter-spacing: 0.5px;}.info-value {display: block;font-size: 18px;font-weight: 700;color: #1e293b;font-family: 'Courier New', monospace;}/* 演示區域樣式 */.demo-section {margin-bottom: 40px;}.section-title {font-size: 28px;font-weight: 700;color: white;text-align: center;margin-bottom: 30px;text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);}.demo-card {background: rgba(255, 255, 255, 0.95);backdrop-filter: blur(10px);border-radius: 16px;padding: 24px;margin-bottom: 24px;box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);border: 1px solid rgba(255, 255, 255, 0.2);transition:transform 0.3s ease,box-shadow 0.3s ease;}.demo-card:hover {transform: translateY(-5px);box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15);}.demo-title {font-size: 20px;font-weight: 600;color: #2c3e50;margin: 0 0 20px 0;padding-bottom: 12px;border-bottom: 2px solid #e2e8f0;}/* 按鈕演示樣式 */.button-demo {display: flex;gap: 12px;flex-wrap: wrap;}.btn {padding: 12px 24px;border: none;border-radius: 8px;font-size: 14px;font-weight: 600;cursor: pointer;transition: all 0.3s ease;text-transform: uppercase;letter-spacing: 0.5px;}.btn:hover {transform: translateY(-2px);box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);}.btn-primary {background: linear-gradient(135deg, #667eea, #764ba2);color: white;}.btn-secondary {background: linear-gradient(135deg, #6c757d, #495057);color: white;}.btn-success {background: linear-gradient(135deg, #28a745, #20c997);color: white;}.btn-warning {background: linear-gradient(135deg, #ffc107, #fd7e14);color: white;}.btn-danger {background: linear-gradient(135deg, #dc3545, #e83e8c);color: white;}/* 表單演示樣式 */.form-demo {display: grid;gap: 20px;}.form-group {display: flex;flex-direction: column;}.form-label {font-size: 14px;font-weight: 600;color: #374151;margin-bottom: 8px;}.form-input,.form-textarea {padding: 12px 16px;border: 2px solid #e5e7eb;border-radius: 8px;font-size: 16px;transition: all 0.3s ease;background: white;}.form-input:focus,.form-textarea:focus {outline: none;border-color: #667eea;box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);}.form-textarea {min-height: 80px;resize: vertical;}/* 卡片演示樣式 */.card-demo {display: grid;grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));gap: 20px;}.feature-card {background: linear-gradient(135deg, #f8fafc, #e2e8f0);border-radius: 12px;padding: 24px;text-align: center;transition: all 0.3s ease;border: 2px solid transparent;}.feature-card:hover {transform: translateY(-5px);border-color: #667eea;box-shadow: 0 8px 25px rgba(102, 126, 234, 0.15);}.card-icon {font-size: 48px;margin-bottom: 16px;display: block;}.card-title {font-size: 18px;font-weight: 600;color: #2c3e50;margin: 0 0 12px 0;}.card-desc {font-size: 14px;color: #64748b;line-height: 1.5;margin: 0;}/* 忽略轉換演示樣式 */.ignore-demo {padding: 20px;background: linear-gradient(135deg, #f8fafc, #e2e8f0);border-radius: 12px;}.comparison-group {display: grid;grid-template-columns: 1fr 1fr;gap: 24px;}.comparison-item {text-align: center;}.comparison-item h4 {font-size: 16px;font-weight: 600;color: #2c3e50;margin: 0 0 16px 0;}.fixed-box {width: 120px; /* px-to-viewport-ignore */height: 80px; /* px-to-viewport-ignore */background: linear-gradient(135deg, #95a5a6, #7f8c8d);color: white;display: flex;align-items: center;justify-content: center;border-radius: 8px;font-size: 12px;font-weight: 600;margin: 0 auto 12px auto;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);}.responsive-box {width: 120px;height: 80px;background: linear-gradient(135deg, #e67e22, #d35400);color: white;display: flex;align-items: center;justify-content: center;border-radius: 8px;font-size: 12px;font-weight: 600;margin: 0 auto 12px auto;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);transition: transform 0.3s ease;}.responsive-box:hover {transform: scale(1.05);}.desc {font-size: 12px;color: #64748b;margin: 0;}/* 交互演示樣式 */.interactive-section {margin-bottom: 40px;}.hover-demo {display: grid;grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));gap: 16px;}.hover-card {height: 100px;background: linear-gradient(135deg, #667eea, #764ba2);border-radius: 12px;display: flex;align-items: center;justify-content: center;color: white;font-weight: 600;cursor: pointer;transition: all 0.3s ease;position: relative;overflow: hidden;}.hover-card::before {content: '';position: absolute;top: 0;left: -100%;width: 100%;height: 100%;background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);transition: left 0.5s ease;}.hover-card:hover {transform: translateY(-5px) scale(1.05);box-shadow: 0 12px 30px rgba(102, 126, 234, 0.3);}.hover-card:hover::before {left: 100%;}.hover-text {position: relative;z-index: 1;}/* 動畫定義 */@keyframes float {0%,100% {transform: translateY(0px);}50% {transform: translateY(-10px);}}@keyframes bounce {0%,20%,50%,80%,100% {transform: translateY(0);}40% {transform: translateY(-10px);}60% {transform: translateY(-5px);}}/* 響應式設計 */@media (max-width: 768px) {.control-panel {grid-template-columns: 1fr;}.comparison-group {grid-template-columns: 1fr;}.card-demo {grid-template-columns: 1fr;}.button-demo {justify-content: center;}.main-title {font-size: 24px;}.section-title {font-size: 22px;}}@media (max-width: 480px) {.demo-container {padding: 16px;}.panel-card,.demo-card {padding: 16px;}.hover-demo {grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));}.design-width-selector {justify-content: center;}.width-btn {font-size: 11px;padding: 6px 12px;}}
</style>
3.2 在主應用中使用
在 src/App.vue
中引入演示組件:
<template><div id="app"><PxToVwDemo /></div>
</template><script>
import PxToVwDemo from "./components/PxToVwDemo.vue";export default {name: "App",components: {PxToVwDemo,},
};
</script>
3.3 驗證方法
-
啟動開發服務器:
npm run dev
-
打開瀏覽器開發者工具:
- 按 F12 打開開發者工具
- 切換到 Elements/元素面板
- 查看編譯后的 CSS
-
驗證轉換結果:
- 原始 CSS:
font-size: 24px
- 轉換后:
font-size: 6.4vw
- 原始 CSS:
-
測試響應式效果:
- 調整瀏覽器窗口大小
- 觀察頁面元素是否按比例縮放
- 使用設備模擬器測試不同屏幕尺寸
📖 配置參數詳細說明
核心參數
參數名 | 類型 | 默認值 | 說明 |
---|---|---|---|
viewportWidth | Number | 320 | 設計稿的視口寬度,通常是設計師給出的設計稿寬度 |
viewportHeight | Number | 568 | 設計稿的視口高度,一般不需要配置 |
unitPrecision | Number | 5 | 轉換后的單位精度,即小數點后保留幾位 |
propList | Array | [‘*’] | 需要轉換的 CSS 屬性列表 |
viewportUnit | String | ‘vw’ | 轉換后的視口單位 |
fontViewportUnit | String | ‘vw’ | 字體相關屬性轉換后的單位 |
過濾參數
參數名 | 類型 | 默認值 | 說明 |
---|---|---|---|
selectorBlackList | Array | [] | 不需要轉換的選擇器列表 |
minPixelValue | Number | 1 | 最小轉換的像素值,小于這個值的 px 不會被轉換 |
exclude | RegExp/Array | undefined | 忽略某些文件夾下的文件或特定文件 |
include | RegExp/Array | undefined | 只轉換匹配的文件 |
高級參數
參數名 | 類型 | 默認值 | 說明 |
---|---|---|---|
mediaQuery | Boolean | false | 是否轉換媒體查詢中的 px |
replace | Boolean | true | 是否直接替換屬性值而不添加備用屬性 |
landscape | Boolean | false | 是否添加橫屏時的媒體查詢 |
landscapeUnit | String | ‘vw’ | 橫屏時使用的單位 |
landscapeWidth | Number | 568 | 橫屏時的視口寬度 |
配置示例
// 移動端項目配置
postcssViewport({viewportWidth: 375, // iPhone 6/7/8 寬度unitPrecision: 3, // 保留3位小數propList: ["*"], // 轉換所有屬性selectorBlackList: [".ignore", ".hairlines"],minPixelValue: 1, // 1px及以上才轉換mediaQuery: false, // 不轉換媒體查詢exclude: [/node_modules/], // 忽略第三方庫
});// 桌面端項目配置
postcssViewport({viewportWidth: 1200, // 桌面端設計稿寬度unitPrecision: 2, // 保留2位小數propList: ["width", "height", "margin*", "padding*"],selectorBlackList: [".pc-fixed"],minPixelValue: 2, // 2px及以上才轉換mediaQuery: true, // 轉換媒體查詢exclude: [/node_modules/, /\.min\.css$/],
});
🔧 常見問題和解決方案
問題 1:插件不生效,px 沒有被轉換
可能原因:
- 插件配置錯誤
- 文件被 exclude 規則排除
- 選擇器在黑名單中
解決方案:
- 檢查 vite.config.js 配置是否正確
- 確認 CSS 文件路徑沒有被 exclude
- 檢查選擇器是否在 selectorBlackList 中
- 重啟開發服務器
# 重啟開發服務器
npm run dev
問題 2:第三方組件庫樣式被錯誤轉換
解決方案:
postcssViewport({// 排除第三方組件庫exclude: [/node_modules/, /element-plus/, /ant-design-vue/, /vant/],// 或使用選擇器黑名單selectorBlackList: [".el-", // Element Plus".ant-", // Ant Design".van-", // Vant],
});
問題 3:1px 邊框被轉換導致在某些設備上消失
解決方案:
postcssViewport({minPixelValue: 2, // 小于2px的不轉換selectorBlackList: [".hairlines"], // 1px邊框專用類
});
/* 1px邊框專用樣式 */
.hairlines {border: 1px solid #eee; /* 不會被轉換 */
}
問題 4:字體在大屏幕上過大
解決方案:
postcssViewport({viewportWidth: 375,// 使用CSS clamp()限制字體大小范圍// 或者設置最大視口寬度maxDisplayWidth: 750, // 自定義參數,需要額外處理
});
/* 手動使用clamp()限制字體大小 */
.title {font-size: clamp(16px, 4.267vw, 24px);
}
問題 5:開發環境和生產環境表現不一致
解決方案:
// 環境特定配置
const isProduction = process.env.NODE_ENV === "production";postcssViewport({viewportWidth: 375,unitPrecision: isProduction ? 2 : 5, // 生產環境減少精度replace: isProduction, // 生產環境直接替換exclude: isProduction ? [/node_modules/, /\.min\.css$/] : [/node_modules/],
});
🎯 最佳實踐
1. 設計稿規范
- 與設計師確認設計稿寬度(推薦 375px 或 750px)
- 統一設計稿的單位和標注方式
- 建立設計稿到代碼的轉換規范
2. 代碼規范
/* 推薦:使用語義化的尺寸 */
.container {width: 375px;
} /* 全寬 */
.half-width {width: 187.5px;
} /* 半寬 */
.quarter {width: 93.75px;
} /* 四分之一寬 *//* 推薦:建立間距系統 */
.spacing-xs {margin: 4px;
} /* 最小間距 */
.spacing-sm {margin: 8px;
} /* 小間距 */
.spacing-md {margin: 16px;
} /* 中等間距 */
.spacing-lg {margin: 24px;
} /* 大間距 */
.spacing-xl {margin: 32px;
} /* 最大間距 */
3. 團隊協作
- 在項目 README 中說明 px 轉 vw 的使用規范
- 建立代碼審查檢查清單
- 提供設計稿到 vw 的轉換工具或計算器
4. 性能優化
postcssViewport({// 只轉換必要的屬性propList: ["width","height","margin*","padding*","font-size","line-height","top","bottom","left","right",],// 減少不必要的精度unitPrecision: 3,// 排除不需要轉換的文件exclude: [/node_modules/, /\.min\.css$/, /vendor/],
});
📚 相關資源
- postcss-px-to-viewport-8-plugin GitHub
- PostCSS 官方文檔
- Vite CSS 配置文檔
- CSS 視口單位詳解