fix(theme): 4 个亮色 #4da2b5/#4db892/#80bdca/#80ccb1 不适合做背景色
问题: 之前 Element mix(white) 算法在 S=100% 主色 (#007A95) 上生成的中色 (#4da2b5 / #4db892) 跟主色对比度太低, 作 hover-bg / 选中态底色时白字看不清. 新算法: HSL 降饱和 + 提亮度 (色相不变, 灰度提升). text = S-40 L+15 (中蓝可读, 链接用) light = S-65 L+40 (灰中, disabled 浅背景) lighter = S-65 L+50 (灰浅, hover-bg / 选中态, **够淡字可读**) mix = S-75 L+60 (近白, focus border) 主色 (#007A95): text #2d9cb4 lighter #b7d6dd light #95c2cc mix #dde8ea 次色 (#009963): text #2eb887 lighter #baded1 light #98cdba mix #dfece7 Element Plus 联动: --el-color-primary-light-9 → var(--brand-primary-mix) (近白, 最浅) --el-color-success-light-9 → var(--brand-secondary-mix) theme.js derivePalette 同步改成同算法 (运行时 setBrand 仍正确)
This commit is contained in:
+11
-24
@@ -74,21 +74,6 @@ function hslToHex({ h, s, l }) {
|
||||
/** 把 lightness 限制在 8..92 之间 */
|
||||
function clampL(l) { return Math.max(8, Math.min(92, l)) }
|
||||
|
||||
/**
|
||||
* Element Plus mix() — RGB 线性插值 (Sass mixColor 复刻)
|
||||
* mix(color1, color2, weight) → color1*(1-w) + color2*w
|
||||
* 比 HSL 大幅提亮更克制, 适合政务网站的浅色调.
|
||||
*/
|
||||
function elMix(color1, color2, weight) {
|
||||
weight = Math.max(Math.min(weight, 1), 0)
|
||||
const r1 = parseInt(color1.slice(1, 3), 16), g1 = parseInt(color1.slice(3, 5), 16), b1 = parseInt(color1.slice(5, 7), 16)
|
||||
const r2 = parseInt(color2.slice(1, 3), 16), g2 = parseInt(color2.slice(3, 5), 16), b2 = parseInt(color2.slice(5, 7), 16)
|
||||
const r = Math.round(r1 * (1 - weight) + r2 * weight)
|
||||
const g = Math.round(g1 * (1 - weight) + g2 * weight)
|
||||
const b = Math.round(b1 * (1 - weight) + b2 * weight)
|
||||
return '#' + [r, g, b].map(v => v.toString(16).padStart(2, '0')).join('')
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用派生算法:输入主色 hex, 输出 7 个 --brand-<prefix>-* 变量
|
||||
* @param {string} base 主色 hex
|
||||
@@ -98,11 +83,13 @@ function elMix(color1, color2, weight) {
|
||||
* 深色 (HSL lightness):
|
||||
* deep = L - 12 (hover / active / 标题强调)
|
||||
* darker = L - 22 (顶部导航 / 深底)
|
||||
* 浅色 (Element Plus mix(white, base, N*10%)):
|
||||
* light = 50% mix (背景 / disabled)
|
||||
* lighter = 70% mix (hover-bg / 选中态)
|
||||
* text = 30% mix (链接默认)
|
||||
* mix = 80% mix (输入框 focus border)
|
||||
* 浅色 (HSL 降饱和 + 提亮度, 适合政务网站):
|
||||
* text = S-40 L+15 (链接默认, 中蓝可读)
|
||||
* lighter = S-65 L+50 (hover-bg / 选中态, 浅灰)
|
||||
* light = S-65 L+40 (背景 / disabled, 灰中)
|
||||
* mix = S-75 L+60 (输入框 focus border, 近白)
|
||||
* 之前试过 Element mix(white), 但 S=100% 的主色提亮后跟主色
|
||||
* 对比度太低 (例 #4da2b5), 不适合做选中态背景.
|
||||
*/
|
||||
export function derivePalette(base, prefix = 'primary') {
|
||||
const hsl = rgbToHsl(hexToRgb(base))
|
||||
@@ -111,10 +98,10 @@ export function derivePalette(base, prefix = 'primary') {
|
||||
[`--brand-${p}`]: base,
|
||||
[`--brand-${p}-deep`]: hslToHex({ ...hsl, l: clampL(hsl.l - 12) }),
|
||||
[`--brand-${p}-darker`]: hslToHex({ ...hsl, l: clampL(hsl.l - 22) }),
|
||||
[`--brand-${p}-light`]: elMix('#ffffff', base, 0.5),
|
||||
[`--brand-${p}-lighter`]: elMix('#ffffff', base, 0.7),
|
||||
[`--brand-${p}-text`]: elMix('#ffffff', base, 0.3),
|
||||
[`--brand-${p}-mix`]: elMix('#ffffff', base, 0.8)
|
||||
[`--brand-${p}-text`]: hslToHex({ h: hsl.h, s: Math.max(0, hsl.s - 40), l: clampL(hsl.l + 15) }),
|
||||
[`--brand-${p}-lighter`]: hslToHex({ h: hsl.h, s: Math.max(0, hsl.s - 65), l: clampL(hsl.l + 50) }),
|
||||
[`--brand-${p}-light`]: hslToHex({ h: hsl.h, s: Math.max(0, hsl.s - 65), l: clampL(hsl.l + 40) }),
|
||||
[`--brand-${p}-mix`]: hslToHex({ h: hsl.h, s: Math.max(0, hsl.s - 75), l: clampL(hsl.l + 60) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,16 @@
|
||||
深色 (deep/darker) — HSL 调亮度
|
||||
--brand-primary-deep 暗 12% (hover / active / 标题强调)
|
||||
--brand-primary-darker 暗 22% (顶部导航 / 深底)
|
||||
浅色 (light/lighter/text/mix) — Element Plus mix(white, base, N*10%)
|
||||
--brand-primary-light mix 50% white (背景 / disabled)
|
||||
--brand-primary-lighter mix 70% white (hover-bg / 选中态)
|
||||
--brand-primary-text mix 30% white (链接默认)
|
||||
--brand-primary-mix mix 80% white (输入框 focus border)
|
||||
之前 HSL +35% 算法会生成荧光色 (例 #49deff), 政务网站不适用;
|
||||
改用 Element mix() 才是 RGB 线性插值, 全是低饱和度灰调.
|
||||
浅色 (light/lighter/text/mix) — HSL 降饱和 + 提亮度
|
||||
之前试过 Element mix(white) 算法, 但 S=100% 的主色提亮后
|
||||
跟主色对比度太低 (例 #4da2b5 / #4db892), 文字与背景难辨认,
|
||||
不适合做选中态/hover-bg.
|
||||
现在: 同时降饱和 (S-N) 和提亮度 (L+N), 色相不变, 但灰度提升,
|
||||
是 Element 在 S 低基色上的实际效果模拟, 适合政务网站.
|
||||
--brand-primary-text S-40 L+15 (链接默认, 中蓝可读)
|
||||
--brand-primary-lighter S-65 L+50 (hover-bg / 选中态, 浅灰蓝)
|
||||
--brand-primary-light S-65 L+40 (背景 / disabled, 灰中蓝)
|
||||
--brand-primary-mix S-75 L+60 (输入框 focus border, 近白)
|
||||
|
||||
次色 (绿色 #009963) 走同一套算法, 命名 -secondary.
|
||||
语义上对应 Element Plus success (绿=成功/已批准/已完成), 自动
|
||||
@@ -29,19 +32,19 @@
|
||||
--brand-primary: #007A95;
|
||||
--brand-primary-deep: #004858;
|
||||
--brand-primary-darker: #002129;
|
||||
--brand-primary-light: #80bdca;
|
||||
--brand-primary-lighter: #4da2b5;
|
||||
--brand-primary-text: #b3d7df;
|
||||
--brand-primary-mix: #3395aa;
|
||||
--brand-primary-text: #2d9cb4;
|
||||
--brand-primary-lighter: #b7d6dd;
|
||||
--brand-primary-light: #95c2cc;
|
||||
--brand-primary-mix: #dde8ea;
|
||||
|
||||
/* 次色 — 翠绿 */
|
||||
--brand-secondary: #009963;
|
||||
--brand-secondary-deep: #005c3b;
|
||||
--brand-secondary-darker: #00291a;
|
||||
--brand-secondary-light: #80ccb1;
|
||||
--brand-secondary-lighter: #4db892;
|
||||
--brand-secondary-text: #b3e0d0;
|
||||
--brand-secondary-mix: #33ad82;
|
||||
--brand-secondary-text: #2eb887;
|
||||
--brand-secondary-lighter: #baded1;
|
||||
--brand-secondary-light: #98cdba;
|
||||
--brand-secondary-mix: #dfece7;
|
||||
}
|
||||
|
||||
/* Element Plus 联动:把品牌色同步给 Element Plus 内置变量。
|
||||
@@ -49,10 +52,11 @@
|
||||
:root {
|
||||
/* 主色 → primary */
|
||||
--el-color-primary: var(--brand-primary);
|
||||
--el-color-primary-light-3: var(--brand-primary-text); /* text */
|
||||
--el-color-primary-light-5: var(--brand-primary-light); /* light */
|
||||
--el-color-primary-light-7: var(--brand-primary-lighter); /* lighter */
|
||||
--el-color-primary-light-9: var(--brand-primary-lighter); /* lighter */
|
||||
--el-color-primary-light-3: var(--brand-primary-text); /* text (中蓝可读) */
|
||||
--el-color-primary-light-5: var(--brand-primary-light); /* light (灰中) */
|
||||
--el-color-primary-light-7: var(--brand-primary-lighter); /* lighter (灰浅) */
|
||||
--el-color-primary-light-8: var(--brand-primary-lighter); /* lighter */
|
||||
--el-color-primary-light-9: var(--brand-primary-mix); /* mix (近白) */
|
||||
--el-color-primary-dark-2: var(--brand-primary-deep);
|
||||
|
||||
/* 次色 → success (绿色语义: 已批准 / 已完成) */
|
||||
@@ -61,6 +65,6 @@
|
||||
--el-color-success-light-5: var(--brand-secondary-light);
|
||||
--el-color-success-light-7: var(--brand-secondary-lighter);
|
||||
--el-color-success-light-8: var(--brand-secondary-lighter);
|
||||
--el-color-success-light-9: var(--brand-secondary-lighter);
|
||||
--el-color-success-light-9: var(--brand-secondary-mix);
|
||||
--el-color-success-dark-2: var(--brand-secondary-deep);
|
||||
}
|
||||
Reference in New Issue
Block a user