├── public
└── favicon.ico
├── .vscode
└── extensions.json
├── src
├── main.js
├── views
│ ├── JaKoView.vue
│ ├── MonospaceView.vue
│ ├── SerifView.vue
│ ├── SansSerifView.vue
│ ├── HomeView.vue
│ └── CharacterSetView.vue
├── components
│ ├── CJKCharacterDisplay.vue
│ ├── FontComparisonDisplay.vue
│ ├── FontMoreDisplay.vue
│ └── CustomFontTestDisplay.vue
├── router
│ └── index.js
├── App.vue
└── assets
│ ├── color.css
│ └── main.css
├── vite.config.js
├── package.json
├── .gitignore
├── .github
└── dependabot.yml
├── README.md
├── vercel.json
├── index.html
└── LICENSE
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YuKongA/Font-Weight-Test/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
3 | }
4 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import './assets/main.css'
2 |
3 | import { createApp } from 'vue'
4 | import App from './App.vue'
5 | import router from './router'
6 |
7 | const app = createApp(App)
8 |
9 | app.use(router)
10 |
11 | router.push('/')
12 |
13 | app.mount('#app')
14 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { fileURLToPath, URL } from 'node:url'
2 |
3 | import { defineConfig } from 'vite'
4 | import vue from '@vitejs/plugin-vue'
5 |
6 | // https://vitejs.dev/config/
7 | export default defineConfig({
8 | base: './',
9 | plugins: [
10 | vue(),
11 | ],
12 | resolve: {
13 | alias: {
14 | '@': fileURLToPath(new URL('./src', import.meta.url))
15 | }
16 | },
17 | })
18 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "font_weight_test",
3 | "version": "1.1.1",
4 | "type": "module",
5 | "private": true,
6 | "scripts": {
7 | "dev": "vite --host",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "vue": "^3.5.26",
13 | "vue-router": "^4.6.4"
14 | },
15 | "devDependencies": {
16 | "@vitejs/plugin-vue": "^6.0.3",
17 | "vite": "npm:rolldown-vite@latest"
18 | }
19 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | .DS_Store
12 | dist
13 | dist-ssr
14 | coverage
15 | *.local
16 | package-lock.json
17 |
18 | /cypress/videos/
19 | /cypress/screenshots/
20 |
21 | # Editor directories and files
22 | .vscode/*
23 | !.vscode/extensions.json
24 | .idea
25 | *.suo
26 | *.ntvs*
27 | *.njsproj
28 | *.sln
29 | *.sw?
30 | *.lock
31 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "npm" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "daily"
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### Font Weight Test
2 |
3 | 网址: https://font.yukonga.top/
4 |
5 | 本仓库使用 [Vue](https://vuejs.org/) + [Vite](https://vitejs.dev/) 创建
6 |
7 | ```
8 | 2025.09.08
9 | - CJK 添加扩展 J 区
10 | - 重新整理 CJK 节选
11 |
12 | 2024.10.14
13 | - 新增可变字体测试
14 | - 新增同字字形测试
15 | - 增补 CJK 节选
16 |
17 | 2024.06.29
18 | - 重构项目,提高代码复用
19 | - 取消对日韩文字单独指定语言类型
20 |
21 | 2023.11.29
22 | - 添加深色模式支持
23 |
24 | 2023.11.07
25 | - 切换到类 Material Design 3 样式
26 | - 切换到 Vue 框架 SPA 单页 Web 应用
27 |
28 | 2023.11.06
29 | - 切换到最新的 MiSans VF 作为参考字体
30 |
31 | 2023.10.26
32 | - 对日韩文字单独指定 lang 语言类型
33 | ```
34 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "redirects": [
3 | {
4 | "source": "/sans-serif",
5 | "destination": "./",
6 | "permanent": false
7 | },
8 | {
9 | "source": "/serif",
10 | "destination": "./",
11 | "permanent": false
12 | },
13 | {
14 | "source": "/monospace",
15 | "destination": "./",
16 | "permanent": false
17 | },
18 | {
19 | "source": "/ja-ko",
20 | "destination": "./",
21 | "permanent": false
22 | },
23 | {
24 | "source": "/character-set",
25 | "destination": "./",
26 | "permanent": false
27 | }
28 | ]
29 | }
--------------------------------------------------------------------------------
/src/views/JaKoView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 日文字体
4 |
5 |
6 |
7 |
8 |
9 |
10 | 韩文字体
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
11 | 字体字重测试
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/CJKCharacterDisplay.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 默认
6 | 简中
7 | 繁中
8 | 日文
9 | 韩文
10 |
11 |
12 |
13 |
14 | {{ character }}
15 | {{ character }}
16 | {{ character }}
17 | {{ character }}
18 | {{ character }}
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/components/FontComparisonDisplay.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ weight }} -
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHistory } from 'vue-router'
2 | import HomeView from '../views/HomeView.vue'
3 |
4 | const router = createRouter({
5 | history: createWebHistory(import.meta.env.BASE_URL),
6 | routes: [
7 | {
8 | path: '/',
9 | name: '首页',
10 | component: HomeView
11 | },
12 | {
13 | path: '/sans-serif',
14 | name: '无衬线',
15 | component: () => import('../views/SansSerifView.vue')
16 | },
17 | {
18 | path: '/serif',
19 | name: '衬线',
20 | component: () => import('../views/SerifView.vue')
21 | },
22 | {
23 | path: '/monospace',
24 | name: '等宽',
25 | component: () => import('../views/MonospaceView.vue')
26 | },
27 | {
28 | path: '/ja-ko',
29 | name: '日韩',
30 | component: () => import('../views/JaKoView.vue')
31 | },
32 | {
33 | path: '/character-set',
34 | name: '编码',
35 | component: () => import('../views/CharacterSetView.vue')
36 | },
37 | ]
38 | })
39 |
40 | export default router
--------------------------------------------------------------------------------
/src/views/MonospaceView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 正常字体
4 |
5 |
6 |
8 |
9 |
10 |
11 | 倾斜字体
12 |
13 |
14 |
16 |
17 |
18 |
19 | 更多示例
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 YuKongA
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/views/SerifView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 正常字体
4 |
5 |
6 |
8 |
9 |
10 |
11 | 倾斜字体
12 |
13 |
14 |
16 |
17 |
18 |
19 | 更多示例
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/views/SansSerifView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 正常字体
4 |
5 |
6 |
8 |
9 |
10 |
11 | 倾斜字体
12 |
13 |
14 |
16 |
17 |
18 |
19 | 更多示例
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/components/FontMoreDisplay.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | -{{ weight }}-
8 |
9 |
10 |
11 |
12 |
13 |
14 |
43 |
44 |
--------------------------------------------------------------------------------
/src/views/HomeView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 常用字重映射
4 |
5 |
6 | 100 - 淡体 Thin (Hairline)
7 | 200 - 特细 ExtraLight (UltraLight)
8 | 300 - 细体 Light
9 | 350 - 次细 DemiLight
10 | 400 - 标准 Normal (Regular)
11 | 500 - 适中 Medium
12 | 600 - 次粗 SemiBold (DemiBold)
13 | 700 - 粗体 Bold
14 | 800 - 特粗 ExtraBold (UltraBold)
15 | 900 - 浓体 Black (Heavy)
16 | 950 - 特浓 ExtraBlack (UltraBlack)
17 |
18 |
19 |
20 | 字重对照展示
21 |
22 | 设备字体:
23 |
24 | MiSans VF:
25 |
26 |
27 |
28 | 典型同字字形
29 |
30 |
31 |
32 |
33 |
34 | 详细字体测试
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/assets/color.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --vt-c-primary: 20, 184, 166;
3 | --vt-c-surface-1: 255, 255, 255;
4 | --vt-c-surface-2: 20, 20, 24;
5 |
6 | --vt-c-white: rgb(252, 252, 255);
7 | --vt-c-black: rgb(18, 18, 22);
8 |
9 | --vt-c-text-light-1: rgb(26, 26, 30);
10 | --vt-c-text-light-2: rgb(60, 60, 70);
11 |
12 | --vt-c-text-dark-1: rgb(240, 240, 245);
13 | --vt-c-text-dark-2: rgb(204, 204, 214);
14 |
15 | --vt-c-active-color: rgb(20, 184, 166);
16 | --vt-c-hover-color: rgb(45, 212, 191);
17 |
18 | --vt-c-footer-text-1: rgb(55, 50, 70);
19 | --vt-c-footer-text-2: rgb(225, 230, 250);
20 |
21 | --vt-c-footer-background: rgba(20, 184, 166, 0.16);
22 | --vt-c-footer-hover: rgba(20, 184, 166, 0.6);
23 | --vt-c-footer-link-hover: rgb(56, 189, 248);
24 | }
25 |
26 | :root {
27 | --color-background: var(--vt-c-white);
28 | --color-text: var(--vt-c-text-light-1);
29 | --color-active: var(--vt-c-active-color);
30 | --color-hover: var(--vt-c-hover-color);
31 | --color-footer-background: var(--vt-c-footer-background);
32 | --color-footer-text: var(--vt-c-footer-text-1);
33 | --color-footer-hover: var(--vt-c-footer-hover);
34 | --color-footer-link-hover: var(--vt-c-footer-link-hover);
35 | --color-glass-bg: rgba(var(--vt-c-surface-1), 0.55);
36 | --color-glass-border: rgba(160, 200, 190, 0.35);
37 | --color-gradient-1: linear-gradient(135deg, rgba(var(--vt-c-primary), 0.12), rgba(var(--vt-c-primary), 0.06));
38 | }
39 |
40 | @media (prefers-color-scheme: dark) {
41 | :root {
42 | --color-background: var(--vt-c-black);
43 | --color-text: var(--vt-c-text-dark-2);
44 | --color-active: var(--vt-c-active-color);
45 | --color-hover: var(--vt-c-hover-color);
46 | --color-footer-background: var(--vt-c-footer-background);
47 | --color-footer-text: var(--vt-c-footer-text-2);
48 | --color-footer-hover: var(--vt-c-footer-hover);
49 | --color-footer-link-hover: var(--vt-c-footer-link-hover);
50 | --color-glass-bg: rgba(var(--vt-c-surface-2), 0.55);
51 | --color-glass-border: rgba(100, 130, 200, 0.35);
52 | --color-gradient-1: linear-gradient(135deg, rgba(var(--vt-c-primary), 0.16), rgba(var(--vt-c-primary), 0.10));
53 | }
54 | }
--------------------------------------------------------------------------------
/src/views/CharacterSetView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | GB2312 (节选)
4 |
5 |
6 | ℃ $ ¤ ¢ £ ‰ § № ★ ⒛ ⑴ * + , - . / 0 お く ぐ け げ こト ド ナ ニ ヌ ネ ノ ハ バ パ ︵ ︶ ︹ ︺
7 | ︿ ﹀
8 | И Й К Л М Н ㄒ ㄙ ㄚ ㄛ ┚ ┛ ├ 卮 氐 囟 胤 馗 毓 睾 鼗 亟 僖 儆 僭 僬 僦 苻 苓 茑 茚 茆 茔 茕 掼 揲 揸 揠 揿 揄 揞 揎 唣 猬 猸 猱 獐 獍 獗 獠 獬 阋
9 | 阚 滏
10 | 潆 潇 漤 漕 邂 邈 邃 驺 驿 驽 缫 缬 缭 缯 缰 缱 缲 韬 橐 樽 樨 橘 罹 羁 罾 盍 褶 襁 蝾 蝻 箴 篑 篁 篌 篥 綦 綮 繇 纛 蹑 蹒 蹼 蹯 蹴 躅 饔 髻 髭 髹
11 |
12 |
13 |
14 | GBK (节选)
15 |
16 |
17 | 〇 〡 〢 〣 〤 〥 〦 〧 〨 〩 ㊣ ㎎ ㎏ ㎜ ㎝ ㎞ ㎡ ﹗ ﹞ ﹟ ﹠ ﹡ ˙ ― ℅ ℉ ↙∕ ∟ ∣ ╬ ╭ ╯ ╱ ╲ ╳ ▁ ▂
18 | ▃ ▄▕
19 | ▼ ╜ ╫ 丏 丒 丗 丟 丠 両 丣 喩 喪 喫 喬 喭 單 喯 尷 屃 屄 屆 屇 屌 屍 屒 屓 屔 屖 屗 屘 撘 撚 撛 撜 撝 撟 撠 撡 撢 撣 撥 撦 撧 撨 柪 柫 柭 柮 柲 柵 柶 柷
20 | 柸 柹
21 | 柺 査 柼 柾 栁 栂 爯 爲 榓 榖 榗 榙 榚 榝 榞 榟 榠 榡 榢 榣 榤 榥 榦 暊 暋 暍 暎 暏 暐 暒 暓 暔 暕 暘 暙 暚 暛 暜 暞
22 |
23 |
24 |
25 | GB18030-2000 (节选)
26 |
27 |
28 | Ä Æ Å À Á Â Ã Ç È É Ê Ë Ð Ì Í Î Ï Ö Ø Ò Ó Ô Õ Ñ Ù Ú Û Ü Ý Þ ä æ å â ã ç ë ð
29 | î ï
30 | ö ø ô õ ñ û ý þ 㑇 㑊 㕮 㘎 㙍 㙘 㙦 㛃 㛚 㛹 㟃 㠇 㠓 㤘 㥄 㧐 㧑 㧟 㫰 㬊 㬎 㬚 㭎 㭕 㮾 㰀 㳇 㳘 㳚 㴔 㵐 㶲 㸆 㸌 㺄 㻬 㽏 㿠 䁖 䂮 䃅 䃎 䅟
31 | 䌹 䎃 䎖 䏝 䏡 䏲 䐃 䓖 䓛 䓨 䓫 䓬 䗖 䗛 䗪 䗴 䜣 䝙 䢺 䢼 䣘 䥽 䦃 䲟 䲠 䲢 䴓 䴔 䴕 䴖 䴗 䴘 䴙 䶮
32 |
33 |
34 |
35 | CJK Unified (节选)
36 |
37 |
38 |
39 | 扩展 A 区: 㐀 㐁 㐂 㐃 㐄 㐅 㐆 㐇 㐈 㐉 㐊 㐋 㐌 㐍 㐎
40 | 㐏
41 | 扩展 B 区: 𠀀 𠀁 𠀂 𠀃 𠀄 𠀅 𠀆 𠀇 𠀈 𠀉
42 | 𠀊 𠀋 𠀌 𠀍 𠀎 𠀏
43 | 2003 新增: 龦 龧 龨 龩 龪 龫 龬 龭 龮 龯 龰 龱 龲 龳 龴
44 | 龵
45 | 扩展 C 区: 𪜀 𪜁 𪜂 𪜃 𪜄 𪜅 𪜆 𪜇 𪜈 𪜉
46 | 𪜊 𪜋 𪜌 𪜍 𪜎 𪜏
47 | 扩展 D 区: 𫝀 𫝁 𫝂 𫝃 𫝄 𫝅 𫝆 𫝇 𫝈 𫝉
48 | 𫝊 𫝋 𫝌 𫝍 𫝎 𫝏
49 | 2012 新增: 鿌
50 | 扩展 E 区: 𫠠 𫠡 𫠢 𫠣 𫠤 𫠥 𫠦 𫠧 𫠨 𫠩
51 | 𫠪 𫠫 𫠬 𫠭 𫠮 𫠯
52 | 2015 "急用汉字": 鿍 鿎 鿏 䲤 鿑 鿒 鿓 鿔 鿕
53 |
54 | 扩展 F 区: 𬺰 𬺱 𬺲 𬺳 𬺴 𬺵 𬺶 𬺷 𬺸 𬺹
55 | 𬺺 𬺻 𬺼 𬺽 𬺾 𬺿
56 | 2017 新增: 鿥 鿦 鿧 鿨 鿩 鿪 鿖 鿗 鿙 鿚 鿜
57 | 鿠
58 | 2018 新增: 鿫 鿬 鿭 鿮 鿯
59 | 扩展 G 区: 𰀀 𰀁 𰀂 𰀃 𰀄 𰀅 𰀆 𰀇 𰀈 𰀉
60 | 𰀊 𰀋 𰀌 𰀍 𰀎 𰀏
61 | 2021 "急用科学与技术用字": 鿰 鿱 鿲 鿳 鿴 鿵 鿶 鿷 鿸 鿹
62 | 鿺 鿻 鿼
63 | 2021 "10 个需分离的汉字": 䶶 䶷 䶸 䶹 䶺 䶻 䶼 䶽 䶾
64 | 䶿
65 | 2021 "昆曲工尺谱用字": 𪛗 𪛘 𪛙 𪛚 𪛛 𪛜
66 | 𪛝
67 | 2021 新增: 鿽 鿾 鿿 𪛞 𪛟 𫜵 𫜶 𫜷
68 | 𫜸
69 | 扩展 H 区: 𱍐 𱍑 𱍒 𱍓 𱍔 𱍕 𱍖 𱍗 𱍘 𱍙
70 | 𱍚 𱍛 𱍜 𱍝 𱍞 𱍟
71 | 2022 新增: 𫜹
72 | 扩展 I 区:
73 |
74 | 扩展 J 区:
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/components/CustomFontTestDisplay.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 字重: {{ fontWeight }}
5 |
7 |
8 |
9 |
10 | 字号: {{ fontSize }}
11 |
13 |
14 |
15 |
16 | 字型:
17 |
18 |
19 | {{ lang.label }}
20 |
21 |
22 |
23 |
24 |
25 | 文本:
26 |
27 |
28 |
29 |
30 | 示例:
31 |
32 | {{ testText }}
33 |
34 |
35 |
36 |
37 |
38 |
116 |
117 |
--------------------------------------------------------------------------------
/src/assets/main.css:
--------------------------------------------------------------------------------
1 | @import "color.css";
2 |
3 | /* CSS 变量定义
4 | ----------------------------------------*/
5 | :root {
6 | /* 基础尺寸 */
7 | --base-font: clamp(14px, 1.7vw, 16px);
8 | --heading-font: clamp(20px, 2.3vw, 26px);
9 | --wrapper-font: clamp(26px, 3.3vw, 34px);
10 | --nav-font: clamp(15px, 1.8vw, 19px);
11 |
12 | /* 布局尺寸 */
13 | --content-width: 90%;
14 | --card-padding: 0.4cm;
15 | --side-margin: 5%;
16 | --border-radius: 0.3cm;
17 | --border-color: rgba(150, 150, 200, 0.35);
18 |
19 | /* 间距 */
20 | --title-margin-top: 0.4cm;
21 | --title-margin-bottom: 0.2cm;
22 |
23 | /* 页脚相关 */
24 | --footer-height: 30px;
25 | --safe-area-max-inset-bottom: env(safe-area-max-inset-bottom, 36px);
26 | --content-bottom-margin: calc(var(--footer-height) + var(--footer-bottom-margin) + 20px);
27 |
28 | /* 动画 */
29 | --transition-normal: all 0.28s ease;
30 | --transition-slow: all 0.6s ease;
31 | }
32 |
33 | /* 基础重置和通用样式
34 | ----------------------------------------*/
35 | * {
36 | margin: 0;
37 | padding: 0;
38 | box-sizing: border-box;
39 | }
40 |
41 | body {
42 | background: var(--color-gradient-1), var(--color-background);
43 | color: var(--color-text);
44 | line-height: 1.45;
45 | min-height: 100vh;
46 | padding-bottom: calc(60px + var(--safe-area-max-inset-bottom));
47 | }
48 |
49 | a {
50 | text-decoration: none;
51 | color: inherit;
52 | }
53 |
54 | #sans-serif {
55 | font-family: sans-serif;
56 | }
57 |
58 | #serif {
59 | font-family: serif;
60 | }
61 |
62 | #monospace {
63 | font-family: monospace;
64 | }
65 |
66 | /* 布局容器
67 | ----------------------------------------*/
68 | #app {
69 | min-height: 100vh;
70 | padding-bottom: var(--content-bottom-margin);
71 | box-sizing: border-box;
72 | }
73 |
74 | /* 顶部导航(玻璃态)
75 | ----------------------------------------*/
76 | .app-header.glass-nav {
77 | position: sticky;
78 | padding-top: 35px;
79 | z-index: 20;
80 | backdrop-filter: saturate(1.15) blur(12px);
81 | -webkit-backdrop-filter: saturate(1.15) blur(12px);
82 | }
83 |
84 | /* 顶部整体容器 */
85 | .header-shell {
86 | margin-top: 10px;
87 | }
88 |
89 | /* 标题样式
90 | ----------------------------------------*/
91 | h2 {
92 | color: var(--color-text);
93 | transition: var(--transition-normal);
94 | }
95 |
96 | h2 {
97 | font-size: var(--heading-font);
98 | margin: var(--title-margin-top) var(--side-margin) var(--title-margin-bottom);
99 | font-weight: 600;
100 | width: var(--content-width);
101 | letter-spacing: 0.2px;
102 | }
103 |
104 | /* 卡片组件
105 | ----------------------------------------*/
106 | .round {
107 | width: var(--content-width);
108 | margin: 0 var(--side-margin);
109 | padding: var(--card-padding);
110 | border-radius: 18px;
111 | border: 1px solid var(--color-glass-border);
112 | font-size: var(--base-font);
113 | transition: var(--transition-slow);
114 | background: var(--color-glass-bg);
115 | box-shadow: 0 8px 24px rgba(20, 20, 40, 0.12);
116 | backdrop-filter: saturate(1.1) blur(10px);
117 | -webkit-backdrop-filter: saturate(1.1) blur(10px);
118 | animation: fadeUp 500ms ease both;
119 | }
120 |
121 | .round:not(:last-child) {
122 | margin-bottom: 0.5cm;
123 | }
124 |
125 | .round> :nth-child(2) {
126 | margin-bottom: 0.15cm;
127 | }
128 |
129 | .round:hover {
130 | transform: translateY(-2px);
131 | box-shadow: 0 12px 32px rgba(20, 20, 40, 0.18);
132 | }
133 |
134 | @keyframes fadeUp {
135 | from {
136 | opacity: 0;
137 | transform: translateY(8px);
138 | }
139 |
140 | to {
141 | opacity: 1;
142 | transform: translateY(0);
143 | }
144 | }
145 |
146 | /* 掠影动画关键帧 */
147 | @keyframes sheen {
148 | 0% {
149 | transform: translateX(-120%);
150 | }
151 |
152 | 100% {
153 | transform: translateX(120%);
154 | }
155 | }
156 |
157 | /* 导航样式
158 | ----------------------------------------*/
159 | .ul {
160 | width: var(--content-width);
161 | margin: 0 var(--side-margin);
162 | padding: 0;
163 | font-size: var(--base-font);
164 | border-radius: 18px;
165 | border: 1px solid var(--color-glass-border);
166 | box-shadow: 0 8px 24px rgba(20, 20, 40, 0.12);
167 | line-height: clamp(2.6, 2.6 + 1.5vw, 4.6);
168 | overflow: hidden;
169 | transition: var(--transition-normal);
170 | background: var(--color-glass-bg);
171 | backdrop-filter: saturate(1.1) blur(10px);
172 | -webkit-backdrop-filter: saturate(1.1) blur(10px);
173 | list-style: none;
174 | display: grid;
175 | grid-template-columns: repeat(6, 1fr);
176 | }
177 |
178 | .li {
179 | transition: var(--transition-normal);
180 | }
181 |
182 | .li:last-child {
183 | border-right: none;
184 | }
185 |
186 | .li a {
187 | display: block;
188 | text-align: center;
189 | font-size: var(--nav-font);
190 | padding: clamp(0.3em, 0.3em + 0.8vw, 0.6em) 0;
191 | transition: var(--transition-normal);
192 | color: var(--color-text);
193 | font-weight: 500;
194 | letter-spacing: 0.1px;
195 | }
196 |
197 | /* 交互状态
198 | ----------------------------------------*/
199 | .nothing {
200 | position: relative;
201 | transition: var(--transition-normal);
202 | background-color: transparent;
203 | overflow: hidden;
204 | /* 让掠影在圆角内裁切 */
205 | }
206 |
207 | .nothing:hover {
208 | background-color: var(--color-hover);
209 | color: var(--color-background);
210 | box-shadow: 0 8px 18px rgba(20, 20, 40, 0.12), inset 0 -2px 8px rgba(255, 255, 255, 0.08);
211 | }
212 |
213 | .nothing:active {
214 | background-color: var(--color-active);
215 | }
216 |
217 | .nothing.active {
218 | background-color: var(--color-active);
219 | font-weight: 600;
220 | color: var(--color-background);
221 | }
222 |
223 | /* 掠影(shine)效果:在 hover 时从左到右扫过 */
224 | .nothing::before {
225 | content: "";
226 | position: absolute;
227 | inset: 0;
228 | border-radius: inherit;
229 | pointer-events: none;
230 | background: linear-gradient(90deg,
231 | rgba(255, 255, 255, 0) 0%,
232 | rgba(255, 255, 255, 0.22) 45%,
233 | rgba(255, 255, 255, 0) 100%);
234 | transform: translateX(-120%);
235 | opacity: 0;
236 | }
237 |
238 | .nothing:hover::before {
239 | opacity: 0.85;
240 | animation: sheen 700ms ease forwards;
241 | }
242 |
243 | .nothing.active::before {
244 | opacity: 0;
245 | }
246 |
247 | /* 字符表格
248 | ----------------------------------------*/
249 | .character-table {
250 | width: 100%;
251 | border-collapse: collapse;
252 | backdrop-filter: blur(4px);
253 | }
254 |
255 | .character-table th,
256 | .character-table td {
257 | border: 1px solid var(--color-glass-border);
258 | padding: 8px 12px;
259 | text-align: center;
260 | font-size: 16px;
261 | line-height: 1.5;
262 | }
263 |
264 | .character-table th {
265 | font-weight: 600;
266 | background-color: transparent;
267 | }
268 |
269 | /* 移除最外层边框 */
270 | .character-table tr:first-child th {
271 | border-top: none;
272 | }
273 |
274 | .character-table tr:last-child td {
275 | border-bottom: none;
276 | }
277 |
278 | .character-table th:first-child,
279 | .character-table td:first-child {
280 | border-left: none;
281 | }
282 |
283 | .character-table th:last-child,
284 | .character-table td:last-child {
285 | border-right: none;
286 | }
287 |
288 | /* 页脚
289 | ----------------------------------------*/
290 | #footer {
291 | font-family: "MiSans VF";
292 | position: fixed;
293 | bottom: 0;
294 | height: var(--footer-height);
295 | bottom: calc(env(safe-area-inset-bottom, 0px) + 10px);
296 | left: 50%;
297 | transform: translate(-50%, 0);
298 | width: 260px;
299 | background-color: var(--color-footer-background);
300 | backdrop-filter: blur(10px);
301 | color: var(--color-footer-text);
302 | padding: 0;
303 | border-radius: 10px;
304 | text-align: center;
305 | display: flex;
306 | align-items: center;
307 | justify-content: center;
308 | border: 1px solid var(--color-glass-border);
309 | box-shadow: 0 6px 20px rgba(20, 20, 40, 0.12);
310 | }
311 |
312 | /* 页脚链接
313 | ----------------------------------------*/
314 | a.footer-msg {
315 | color: var(--color-footer-text);
316 | transition: color 0.3s;
317 | }
318 |
319 | a.footer-msg:visited {
320 | color: var(--color-footer-text);
321 | }
322 |
323 | a.footer-msg:active {
324 | color: #FFCC7A;
325 | }
326 |
327 | #footer a.footer-msg {
328 | transition: color 0.5s ease;
329 | }
330 |
331 | #footer:hover a.footer-msg:hover {
332 | color: var(--color-footer-link-hover);
333 | }
334 |
335 | /* 响应式布局
336 | ----------------------------------------*/
337 | @media screen and (min-width: 768px) {
338 | :root {
339 | --content-width: min(85%, 800px);
340 | --side-margin: auto;
341 | }
342 |
343 | .round {
344 | line-height: 1.6;
345 | }
346 |
347 | .ul {
348 | margin: 0 auto 0.5cm;
349 | max-width: 800px;
350 | }
351 |
352 | h2 {
353 | margin: var(--title-margin-top) auto var(--title-margin-bottom);
354 | text-align: left;
355 | max-width: 800px;
356 | }
357 |
358 | .wrapper {
359 | margin: 1cm auto 0.8cm;
360 | max-width: 800px;
361 | }
362 | }
363 |
364 | @media screen and (min-width: 1024px) {
365 | :root {
366 | --content-width: min(75%, 900px);
367 | }
368 |
369 | .ul,
370 | h2,
371 | .wrapper {
372 | max-width: 900px;
373 | }
374 | }
375 |
376 | @media screen and (min-width: 1200px) {
377 | :root {
378 | --content-width: min(70%, 1000px);
379 | }
380 |
381 | .ul,
382 | h2,
383 | .wrapper {
384 | max-width: 1000px;
385 | }
386 | }
387 |
388 | /* 包装器
389 | ----------------------------------------*/
390 | .wrapper {
391 | color: var(--color-text);
392 | font-family: "MiSans VF";
393 | font-weight: 600;
394 | text-align: center;
395 | font-size: var(--wrapper-font);
396 | margin: 0 auto;
397 | transition: var(--transition-normal);
398 | letter-spacing: 0.2px;
399 | }
400 |
401 | /* 统一强调色 */
402 | .accent {
403 | color: var(--color-active);
404 | }
405 |
406 | /* 视图分组标题 */
407 | .section-title {
408 | font-weight: 600;
409 | }
410 |
411 | /* CJK 分组网格 */
412 | .cjk-columns {
413 | display: grid;
414 | grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
415 | gap: 14px;
416 | }
417 |
418 | .cjk-item {
419 | break-inside: avoid;
420 | -webkit-column-break-inside: avoid;
421 | background: var(--color-glass-bg);
422 | border: 1px solid var(--color-glass-border);
423 | border-radius: 12px;
424 | padding: 12px;
425 | margin-bottom: 0;
426 | }
427 |
428 | .cjk-item .accent {
429 | display: block;
430 | margin-bottom: 6px;
431 | }
432 |
433 | .cjk-text {
434 | letter-spacing: 0.1px;
435 | }
436 |
437 | /* gb-block 单列 */
438 | .gb-block {
439 | white-space: normal;
440 | word-break: keep-all;
441 | hyphens: none;
442 | line-height: 1.8;
443 | font-size: clamp(15px, 1.9vw, 18px);
444 | padding: 2px 0;
445 | }
446 |
447 | @media screen and (min-width: 1024px) {
448 | .cjk-columns {
449 | grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
450 | gap: 14px;
451 | }
452 | }
453 |
454 | /* 标签文本(次级标题) */
455 | .label {
456 | font-weight: 500;
457 | }
458 |
459 | /* 间距工具类(简短且常用) */
460 | .mb-0 {
461 | margin-bottom: 0 !important;
462 | }
463 |
464 | .mb-sm {
465 | margin-bottom: 0.5em;
466 | }
467 |
468 | .mb-md {
469 | margin-bottom: 0.6rem;
470 | }
471 |
472 | .mb-xl {
473 | margin-bottom: 1.5em;
474 | }
475 |
476 | /* 页面路由切换动画 */
477 | .page-enter-active,
478 | .page-leave-active {
479 | transition: opacity 250ms ease, transform 250ms ease;
480 | }
481 |
482 | .page-enter-from,
483 | .page-leave-to {
484 | opacity: 0;
485 | transform: translateY(8px);
486 | }
487 |
--------------------------------------------------------------------------------