Web Designeditorial12 min read

AI Color Palette Tools: What They Get Wrong

Khroma, Coolors, and Firefly generate beautiful swatches. They still cannot ship your design system without human verification.

Marketing needed five campaign palettes by Friday. Someone opened Khroma, trained it on a mood board, exported hex codes, and pasted them into the staging branch before lunch. By Monday, the warning toast failed WCAG contrast on the light surface, the chart palette shared a hue angle with the primary button, and the complementary accent the tool suggested looked gorgeous in isolation and illegible at 12px on a data table. The palettes were not ugly. They were unverified—generated without semantic roles, without OKLCH sanity checks, and without the discipline that turns five swatches into a system.

AI color tools have improved dramatically since the first random-wheel generators. Khroma learns from your likes. Coolors locks directions and exports in seconds. Adobe Firefly suggests harmonies inside a creative suite millions of designers already inhabit. None of that progress changes the underlying contract. A design system does not need five colors that look good on a gradient strip preview. It needs named roles with contrast obligations, state variants that track a base without hue drift, and ramps where step 500 means the same perceived weight whether the hue is yellow or blue. Generators solve a preference-matching problem. Systems solve a geometry-and-governance problem. The gap between those two problems is where production teams get burned.

This article examines what Khroma, Coolors, and Firefly actually optimize for, walks through a real handoff failure in continuous narrative, and describes the verification layer that should sit between generate and merge. The tools are accelerators. They are not authors. Treating them as authors is how you ship beautiful hex codes that fail the moment they touch a settings page with twelve simultaneous UI regions.

The aesthetic engine versus the systems contract

Most AI-assisted palette generators begin with a signal. Sometimes that signal is your taste, collected through a short training flow where you approve and reject swatches until the model converges on your preferences. Sometimes it is a text prompt like fintech trustworthy or playful SaaS, interpreted probabilistically against a corpus of human-made palettes scraped from portfolios and brand galleries. Sometimes it is a reference image whose dominant hues get extracted and extrapolated into a harmony set. In every case, the optimization target is coherence inside the tool’s preview chrome: typography samples, gradient strips, mock hero layouts, the small theater that makes you want to export.

Design systems optimize against a different constraint surface entirely. A token named for its job, such as a muted text role on a raised surface, carries obligations that have nothing to do with whether the gray looked elegant in isolation. That role must maintain readable contrast against its specific background per WCAG 2.2 Contrast (Minimum). It must sit at a perceptual lightness step that feels consistent with other muted roles across hues. It must survive dark mode without becoming invisible or shouting. It must not collide with accent, danger, or chart series colors when those appear in the same viewport. Generators do not know your surface stack, your focus ring system, or your procurement language around Non-text Contrast. They know that certain hex combinations co-occurred in training data and scored well when rendered as large blocks.

The coordinate system mismatch compounds the role mismatch. Most generators export hex, which is sRGB notation. Hex is a fine interchange format at the boundary if you immediately convert into a perceptual authoring space. Teams that paste hex directly into tokens inherit the uneven ramps that Björn Ottosson’s Oklab was invented to fix. Yellow at the same HSL lightness as blue is a classic trap documented in Ottosson’s hue sweep plots and in browser support for oklch() per CSS Color Module Level 4. AI does not exempt you from perceptual geometry. It hides the geometry behind attractive previews.

There is also a repeatability problem. A prompt-driven generator may produce different outputs on consecutive runs from the same text. Khroma’s personalization reduces generic randomness but does not lock brand anchors. If your brand blue is fixed at a specific OKLCH coordinate, a harmonizing suggestion that drifts hue by four degrees fails brand compliance and splits your ramp across two incompatible anchors. Exploration tools reward divergence. Systems reward stable references that alias correctly in Design Tokens Format Module 2025.10 JSON. The handoff breaks when exploration output lands in a repository that expects decisions, not candidates.

Khroma, Coolors, and Firefly under production pressure

Khroma is genuinely distinctive in the category because it trains a browser-based model on your preferences during onboarding at khroma.co/train. You choose colors you like and block colors you dislike. The model then generates combinations informed by thousands of human-made palettes, viewable as typography, gradients, palette grids, or custom images. Search filters by hue, tint, value, color name, hex, and rgb. For mood boards and early directional work, that personalization matters. Designers who struggle to articulate warm but not orange can iterate until the generator converges on taste they recognize as their own.

What Khroma does not do is assign semantic roles. Exporting two hex values does not tell you which is a raised surface, which is a warning fill, or which is chart series three. You still map swatches to roles manually, and that mapping is where systems work actually lives. Khroma displays WCAG accessibility ratings for individual pairs in its collection UI, which is more than many generators offer. Those ratings apply to the pair Khroma happens to preview, not to muted text on a tinted input in your component stack, not to focus rings against adjacent panels, not to placeholder text on a surface-raised token your generator never heard of. Ratings inside a tool are a hint. They are not an audit.

Coolors predates the current AI wave and remains the throughput champion. Spacebar to generate, lock colors you like, export to CSS or PNG or PDF. Coolors has added AI-assisted features including palette generation from text prompts and image extraction, positioning it as a faster alternative to manual wheel picking. The workflow excels when you need twenty candidates in a minute. It falls short when you need a token graph. Coolors exports palettes, not roles. Harmony modes like analogous, complementary, and triadic describe hue geometry from art-school wheels. They do not describe UI proportion. A complementary pair at full saturation fails the moment both hues occupy equal area in a dashboard because wheel theory imported unmodified into product UI describes relationships between hues, not relationships between semantic jobs.

Adobe Firefly integrates generative AI across Creative Cloud. Palette and color suggestions appear in workflows tied to image generation, recolor features in Illustrator, and broader creative exploration rather than a standalone design-token pipeline. Adobe documents capabilities across helpx.adobe.com and the Adobe blog. Firefly’s suggestions are contextual to creative tasks: recoloring vector artwork, exploring variations on a generated scene, matching mood in a generative image session. That product shape differs from Khroma’s dedicated discovery or Coolors’ rapid generator. Suggestions live inside Adobe tools. Export to CSS custom properties requires manual or plugin-mediated steps. There is no native DTCG JSON output aligned with the 2025.10 color module. Firefly usage is governed by Adobe’s terms, which vary by subscription tier. Palette extraction for a marketing site is subject to the same policy diligence as any generated asset. Color values alone do not clear licensing.

Across all three tools, the structural failures recur after export. Generators output colors. Systems output decisions. Harmony labels learned from Dribbble shots reproduce statistical co-occurrence, not WCAG math or dashboard scan patterns. Four hues at equal saturation compete in a navigation bar. Complementary pairs vibrate on shared borders. Accent hues sit too close to danger for deuteranopic users. Hex-first export hides perceptual lies until a contrast checker or a production layout surfaces them. The tools are useful precisely because they are fast and visually persuasive. They are dangerous for the same reason if nobody verifies the output.

When marketing shipped palettes before Monday

The failure happened at a mid-size B2B SaaS company in late 2025, during a compressed campaign cycle that will sound familiar to anyone who has worked adjacent to a marketing org with a fixed launch date and a flexible definition of done. The product had a mature design system with OKLCH primitives, semantic aliases, and a signed contrast matrix maintained by a small design-ops team. The campaign was different. It needed five distinct palette directions for landing page variants testing positioning against verticals the company had not marketed to before. The design-ops queue was booked through the following sprint. Marketing had budget for paid media creative but not for a three-week systems review.

On Tuesday afternoon, a growth designer opened Khroma, completed the training flow in twenty minutes using screenshots from competitor sites and a handful of approved brand images, and generated four palette families that felt fresh without straying too far from the parent brand’s navy-and-coral personality. The tool’s typography previews made every combination look publication-ready. The designer exported hex codes into a shared spreadsheet with informal names like campaign-accent-2 and chart-gold. By Wednesday morning, a front-end contractor on a short engagement had pasted those values into a feature branch as CSS custom properties with no semantic naming convention, because the ticket said ship landing page colors and the spreadsheet was the spec.

The first sign of trouble appeared in QA on Thursday, not in the hero sections where the palettes looked intentional, but in the pricing table where nobody had imagined the campaign colors would appear. Warning callouts reused a yellow from the Khroma export at full chroma. Muted helper text sat on a tinted surface that was two steps lighter in hex but not in perceived lightness. The yellow callout drew the eye before the primary CTA. The helper text failed contrast against its background when viewed on a calibrated monitor in the design-ops review, though it had looked acceptable on the designer’s laptop in bright office lighting. The spreadsheet had no row for text-muted on surface-raised. Khroma had never been asked to model that pair.

Friday’s escalation involved the chart palette. The growth team had assigned five exported hues to five series in a small embedded analytics widget on one landing variant. Two of those hues mapped, after conversion to OKLCH, within eight degrees of the campaign primary button hue. On the live preview link, users could not tell which blue line corresponded to the legend entry for revenue versus the legend entry for pipeline without reading the labels twice. A color vision simulation later showed that deuteranopic viewers confused the coral accent with the danger token from the parent system when both appeared in the same viewport during a demo recording. Nobody had run simulation because the ticket scope was landing pages, not in-app components. The in-app widget was reused from an existing template without a color review gate.

The Monday meeting was tense in the specific way cross-functional color meetings become tense when each side believes the other moved a goalpost. Marketing argued the palettes were on-brand for exploratory campaigns and had been approved visually by the director of growth. Design-ops argued that visual approval in a hero mockup is not the same as WCAG evidence on named pairs, and that campaign tokens had leaked into shared components because the contractor followed existing patterns that referenced the nearest custom property. Engineering sat in the middle with a diff that touched forty-seven files and a launch date that had not moved. Legal was not involved yet, but accessibility procurement language in an enterprise renewal loomed in the background. The rollback cost more than generating the palettes had saved.

What changed afterward was not a ban on AI tools. The company adopted a fixed verification pipeline for any color that bypassed design-ops. Campaign work could still start in Khroma or Coolors. Export was explicitly labeled draft. A single design-ops reviewer converted every accepted swatch to OKLCH, compared lightness across hues at the intended step, assigned semantic roles before hex spread, and ran contrast on real pairs using the same checker the main system used. Campaign tokens lived in a namespaced layer that could not be imported by shared components without a lint rule failing CI. The Monday failure became a case study internally: the tools had done their job as accelerators. The organization had skipped the job that only humans with a token graph and a contrast matrix could do.

Converting generated swatches into a verified token graph

The pipeline that emerged from that Monday meeting is not exotic. It is tedious in the way correct handoffs are tedious. Every AI palette enters as raw material with documented provenance: which tool, which prompt or training session, which date. Brand anchor hues are locked before invocation so harmonizing suggestions cannot drift the primary. Three to five candidates are generated; the first acceptable result does not merge. Each accepted swatch converts from hex to OKLCH using algorithms from CSS Color Module Level 4, the same math browsers use when resolving oklch() values. Lightness is compared across hues at the same intended step. Chroma tapers at extremes where full saturation looks fluorescent on tinted surfaces. The ramp discipline described in Your HSL Palette Lies to You applies to AI output exactly as it applies to hand-picked swatches.

Role assignment happens before hex spreads through a codebase. Each accepted swatch maps to exactly one semantic job in a signed table with the same discipline as a Figma variables handoff. Orphans do not ship. If you cannot name the role, the color stays in the spreadsheet. Hover, active, focus, and muted variants derive from base tokens via OKLCH arithmetic or color-mix() in OKLCH per CSS Color Module Level 5, not from a second AI session that drifts hue on Wednesday. A second session is how Monday’s palette diverges from Wednesday’s hover fix.

The contrast pass runs on pairs that exist in production, not pairs the generator previewed. Text on surface, muted text on raised surface, accent label on accent fill, focus ring against adjacent card backgrounds. Thresholds match whatever the statement of work cites, whether that is WCAG 2.2 Level AA or a procurement spec referencing APCA. Failures log in the token repository issue tracker rather than in individual component pull requests so the fix stays at the source. Our contrast checker accepts the pairs you export from any generator; the generator does not run those checks for you.

The following pattern illustrates the gap between what AI exports and what engineering needs. The left column is typical generator output. The right column is the same palette after verification and role assignment.

/* Generator export — unnamed, hex-first */
--color-1: #3b5bdb;
--color-2: #fcc419;
--color-3: #12b886;
--color-4: #fa5252;
--color-5: #7950f2;

/* After OKLCH verification and role assignment */
--text-primary: oklch(0.22 0.02 260);
--text-muted: oklch(0.45 0.02 260);
--surface: oklch(0.98 0.01 260);
--accent: oklch(0.55 0.18 264);
--danger: oklch(0.52 0.20 25);

Without that middle layer, color-2 becomes warning yellow in one component and chart gold in another. The hex values are identical. The system behavior is not.

A single reference table can document target ranges per role after conversion. The numbers are examples, not universal constants; every brand tapers differently.

Role Target OKLCH L Target OKLCH C (max)
Surface 0.97–0.99 0.01–0.02
Text primary 0.20–0.25 0.02–0.03
Accent 0.52–0.58 0.14–0.20
Warning fill 0.72–0.78 0.12–0.16

Adjust until steps feel even across hues, not until the AI preview looks pretty. Simulation for protanopia, deuteranopia, and tritanopia runs on status colors when more than one semantic hue appears in the same strip. AI does not know your success token sits beside your accent in a KPI row. You do.

Where AI generators earn their place

Use Khroma, Coolors, and Firefly when the deliverable is direction, not production CSS. Early rebrand exploration before tokens freeze is ideal. Breaking fixation when a team cycles the same safe blue-gray defaults is ideal. Personalizing mood for a designer whose taste is hard to verbalize is what Khroma was built for. Rapid client workshops where the output is a mood board, not a merge request, are ideal. Do not use them when procurement requires WCAG evidence on named token pairs, when brand guidelines lock OKLCH anchors and deviations need audit trails, when dark mode pairs must preserve perceived weight across themes, or when email and PDF exports need sRGB-safe pre-computed hex with no gamut surprises.

Khroma learns what you like. Coolors generates what you lock. Firefly suggests inside a creative suite governed by terms you must read yourself. None of them maintain your token graph, derive your focus rings, or sign your accessibility report. The workflow that survived the Monday rollback treated every export as draft material through a fixed human verification layer. Generate freely. Convert to OKLCH. Assign roles. Run contrast on your pairs. Namespace campaign tokens so they cannot leak into shared components. Then merge once the numbers match what users’ eyes and assistive technology require.

The disappointment teams feel toward AI palette tools is often misplaced. The tools were never designed to ship design systems. They were designed to make beautiful swatches quickly, and they do that well. The disappointment is real when organizations skip the verification layer and expect preference matching to substitute for geometry, governance, and contrast evidence. The fix is not a better generator. The fix is a disciplined handoff that treats AI output as the first sketch, not the final token file.