You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求基于参考色生成互补色、色调的React/CSS Modules计算公式

动态生成互补色与色调:告别手动维护颜色集合

兄弟,我太懂你手动写一堆颜色对象的痛苦了——不仅工作量大,遇到新的参考色还要手动找互补色,完全没法灵活适配所有场景。其实咱们可以利用颜色模型的数学公式,从单一Hex/RGB参考色动态生成互补色、色调变体,彻底解放双手!

核心思路:用HSL模型处理颜色

互补色在色轮上是相差180度的颜色,而HSL(色相Hue、饱和度Saturation、亮度Lightness)模型的色相值是0-360度的数值,调整起来比Hex或RGB直观太多。所以核心步骤是:

  1. 将Hex/RGB转换为HSL
  2. 调整色相值生成互补色(H±180°),或调整饱和度/亮度生成色调变体
  3. 转换回Hex/RGB供React和CSS Modules使用

一、必备的颜色转换工具函数

先写几个通用的转换函数,这些都是标准的颜色模型转换公式,直接用就行:

1. Hex转RGB

处理3位(如#fff)和6位(如#ffffff)Hex格式:

function hexToRgb(hex) {
  // 统一转换为6位Hex
  const normalizedHex = hex.length === 4 
    ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` 
    : hex;
  
  const r = parseInt(normalizedHex.slice(1, 3), 16);
  const g = parseInt(normalizedHex.slice(3, 5), 16);
  const b = parseInt(normalizedHex.slice(5, 7), 16);
  return [r, g, b];
}

2. RGB转HSL

把RGB值转为HSL的色相、饱和度、亮度:

function rgbToHsl(r, g, b) {
  r /= 255;
  g /= 255;
  b /= 255;

  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  let h, s, l = (max + min) / 2;

  if (max === min) {
    h = s = 0; // 灰度色,无色相和饱和度
  } else {
    const d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch (max) {
      case r: h = (g - b) / d + (g < b ? 6 : 0); break;
      case g: h = (b - r) / d + 2; break;
      case b: h = (r - g) / d + 4; break;
    }
    h /= 6;
  }

  return {
    h: h * 360, // 转为0-360度的色相值
    s: s * 100, // 转为0-100%的饱和度
    l: l * 100  // 转为0-100%的亮度
  };
}

3. HSL转RGB

调整后的HSL值转回RGB:

function hslToRgb(h, s, l) {
  h /= 360;
  s /= 100;
  l /= 100;

  let r, g, b;

  if (s === 0) {
    r = g = b = l; // 灰度色
  } else {
    const hue2rgb = (p, q, t) => {
      if (t < 0) t += 1;
      if (t > 1) t -= 1;
      if (t < 1/6) return p + (q - p) * 6 * t;
      if (t < 1/2) return q;
      if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
      return p;
    };

    const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
    const p = 2 * l - q;
    r = hue2rgb(p, q, h + 1/3);
    g = hue2rgb(p, q, h);
    b = hue2rgb(p, q, h - 1/3);
  }

  return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}

4. RGB转Hex

把RGB值转回Hex格式:

function rgbToHex(r, g, b) {
  const componentToHex = (c) => {
    const hex = c.toString(16);
    return hex.length === 1 ? `0${hex}` : hex;
  };
  return `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
}

二、生成互补色的函数

把上面的工具函数组合起来,一行代码生成互补色:

function getComplementaryColor(hex) {
  const [r, g, b] = hexToRgb(hex);
  const { h, s, l } = rgbToHsl(r, g, b);
  // 互补色相:原色相加180度,超过360则取模
  const complementaryHue = (h + 180) % 360;
  const [newR, newG, newB] = hslToRgb(complementaryHue, s, l);
  return rgbToHex(newR, newG, newB);
}

测试示例:输入#c80eff(紫色),会生成#00ff31(黄绿色)——标准的互补色!


三、扩展:生成自定义色调变体

如果需要不同亮度/饱和度的颜色(比如你示例里的#fab81e、#00ff9c这类变体),可以写一个通用函数:

// 生成指定亮度(0-100)和饱和度(0-100)的颜色变体
function generateColorVariant(hex, lightness = 50, saturation = 100) {
  const [r, g, b] = hexToRgb(hex);
  const { h } = rgbToHsl(r, g, b);
  const [newR, newG, newB] = hslToRgb(h, saturation, lightness);
  return rgbToHex(newR, newG, newB);
}

比如:

  • 生成更亮的互补色:generateColorVariant(complementaryColor, 70)
  • 生成低饱和度的参考色:generateColorVariant(baseColor, 50, 50)

四、在React + CSS Modules中落地

最优雅的方式是用CSS变量,把动态计算的颜色注入到全局或组件级变量中,CSS Modules直接引用即可:

1. React组件代码

import { useEffect } from 'react';
import styles from './App.module.css';

// 把上面的所有工具函数放在这里,或者单独抽成utils文件
function hexToRgb(hex) { /* ... */ }
function rgbToHsl(r, g, b) { /* ... */ }
function hslToRgb(h, s, l) { /* ... */ }
function rgbToHex(r, g, b) { /* ... */ }
function getComplementaryColor(hex) { /* ... */ }
function generateColorVariant(hex, lightness, saturation) { /* ... */ }

function App({ baseColor = '#c80eff' }) {
  const complementaryColor = getComplementaryColor(baseColor);
  // 生成底部组件的浅色调互补色
  const bottomWidgetColor = generateColorVariant(complementaryColor, 75);
  // 生成右侧组件的低饱和度参考色变体
  const rightWidgetColor = generateColorVariant(baseColor, 60, 70);

  useEffect(() => {
    // 将颜色设置为根元素的CSS变量,全局可用
    document.documentElement.style.setProperty('--toolbar-color', baseColor);
    document.documentElement.style.setProperty('--center-widget-color', complementaryColor);
    document.documentElement.style.setProperty('--bottom-widget-color', bottomWidgetColor);
    document.documentElement.style.setProperty('--right-widget-color', rightWidgetColor);
  }, [baseColor]);

  return (
    <div className={styles.app}>
      <div className={styles.toolbar}>Toolbar</div>
      <div className={styles.centerWidget}>Center Widget</div>
      <div className={styles.bottomWidget}>Bottom Widget</div>
      <div className={styles.rightWidget}>Right Widget</div>
    </div>
  );
}

export default App;

2. CSS Modules代码(App.module.css)

.app {
  min-height: 100vh;
  display: grid;
  grid-template-areas:
    "toolbar toolbar toolbar toolbar"
    "center center center right"
    "bottom bottom bottom bottom";
  gap: 1rem;
  padding: 1rem;
}

.toolbar {
  grid-area: toolbar;
  background-color: var(--toolbar-color);
  color: white;
  padding: 1rem;
  border-radius: 4px;
}

.centerWidget {
  grid-area: center;
  background-color: var(--center-widget-color);
  padding: 2rem;
  border-radius: 4px;
}

.bottomWidget {
  grid-area: bottom;
  background-color: var(--bottom-widget-color);
  padding: 1rem;
  border-radius: 4px;
}

.rightWidget {
  grid-area: right;
  background-color: var(--right-widget-color);
  padding: 2rem;
  border-radius: 4px;
}

现在,只要改变baseColor,所有组件的颜色都会自动更新,完全不用手动维护颜色集合了!


内容的提问来源于stack exchange,提问作者toto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:07:27