Privacy choices

Hue Codex uses local settings and privacy-aware measurement.

Required storage keeps tools and your local workspace working. Analytics helps improve popular tools; stricter consent regions stay opt-in unless you allow it. Marketing and personalized ads stay off until you choose them.

Abstract color mixing and gradient methodology workspace with source swatches, midpoint samples, gradient stop controls, opacity layers, interpolation paths, and sampled outputs.

Short answer

Hue Codex exposes the interpolation model, mixes channels or model components deterministically, composites opacity with source-over math, and treats gradient text contrast as sampled guidance rather than full-layout proof.

  • sRGB, HSL, Lab, and OKLab mixes follow different paths and can produce visibly different midpoints.
  • sRGB mode mixes encoded 8-bit sRGB channel values, not linear-light sRGB values.
  • Opacity tools composite a foreground over a background before contrast and export values are calculated.
  • Gradient tools keep stop positions, midpoint hints, interpolation space, and fallback CSS explicit.
  • Overlay text on a gradient must be checked at the final placement, not only against sampled stops.

Standards status

These badges identify which parts of this methodology are standards-backed, draft-track, source-origin references, Hue Codex-specific, approximate, or dependent on browser behavior.

Draft standardStandardHue Codex heuristicApproximationBrowser-dependent
Draft standardDraft, candidate, or preview specification material, such as CSS Color 5 features; not treated as final authority.
StandardStable standard or standards-backed behavior used as authority, such as WCAG 2.2 and broadly implemented CSS Color 4 behavior.
Hue Codex heuristicHue Codex ranking, role hints, bands, labels, or workflow guidance rather than an external standard.
ApproximationModel or estimate with known limits, including CMYK, color-vision simulation, image palette extraction, or CSS duotone output.
Browser-dependentOutput depends on browser APIs, rendering, color management, canvas pixels, clipboard, download, or CSS support.

Formulas, choices, heuristics, and limits

This separates standards-based formulas from Hue Codex implementation decisions, product heuristics, and known limitations for this methodology.

Standards-based formulas

Formula, threshold, syntax, or data behavior taken from a cited standard. Primary and model sources can inform implementation, but they are not automatically standards.

  • Alpha compositing uses source-over channel math before contrast checks.
  • CSS Color 4 color spaces provide the stable conversion context for sRGB, Lab, and OKLab mixing modes.

Implementation choices

How Hue Codex chooses to parse, normalize, round, export, or sequence calculations.

  • Hue Codex exposes the chosen interpolation model instead of hiding mix-space differences.
  • Color Mixer weight is the percentage of Color A. A 0 percent A mix resolves to Color B, a 100 percent A mix resolves to Color A, and intermediate values use A * weightA + B * (1 - weightA).
  • The Color Mixer sRGB mode interpolates encoded 8-bit sRGB channel values directly; it does not linearize channels before mixing.
  • Opacity Calculator composites resolved HEX colors in encoded 8-bit sRGB channel space; it does not linearize channels before source-over alpha math.
  • Color Mixer retains endpoint alpha, interpolates alpha linearly, and uses alpha-premultiplied weighting for sRGB, HSL, Lab, and OKLab component interpolation before serializing the result.
  • Color Mixer CSS color-mix() exports preserve the concrete authored endpoint values, select one supported interpolation space, and use explicit complementary percentages that always sum to 100 percent.
  • HSL mode converts both inputs to RGB-derived HSL, uses the shorter signed hue path with a -180 degree tie, linearly interpolates saturation and lightness, then converts back to sRGB.
  • Gradient tools record stops, midpoint hints, direction, repeating state, and fallback CSS. The sRGB fallback gradient preserves the same HEX stops and positions, then removes the modern interpolation clause.
  • Gradient palette extraction samples normalized stop positions according to the selected mode.

Hue Codex heuristics

Product rankings, bands, labels, suggestions, or role hints that are useful guidance but not external standards.

  • Gradient text guidance, extracted role hints, and review notes are sampled Hue Codex guidance.
  • The selected fallback pattern and support caveat text are product handoff choices.

Known limitations

Caveats, edge cases, browser dependencies, approximations, or contexts the method does not prove.

  • CSS Color 5 color-mix() and related modern interpolation features are draft-standard context.
  • Hue Codex does not parse an arbitrary color-mix() expression as input or generate forms with omitted percentages, more than two colors, currentColor, contextual colors, or leftover percentage alpha.
  • Internal component interpolation uses each endpoint’s resolved sRGB fallback channels, so an authored out-of-sRGB endpoint may differ from a color-managed browser interpolation of its original wide-gamut syntax.
  • Sampled gradient contrast does not test every pixel or every final text position.
  • Encoded sRGB mixes differ from linear-light sRGB mixes; Hue Codex labels the mode so users can choose the interpolation model intentionally.
  • Encoded sRGB opacity compositing can differ from linear-light or color-managed rendering pipelines; Hue Codex reports the resolved fallback it calculates rather than claiming to reproduce every renderer.
  • Achromatic HSL inputs have powerless hue; Hue Codex currently carries the derived numeric fallback hue 0 through HSL interpolation rather than preserving an authored missing-hue marker.
  • Browser support and rendering differ across gradient syntax, interpolation spaces, and wide-gamut output.

Representative automated fixture coverage

Hue Codex imports versioned JSON fixtures and tests the corresponding pure production functions directly. The groups below are the representative regression evidence most relevant to this methodology.

  • Parsing fixtures: Accepted CSS color syntax, alpha behavior, clamping, invalid input, and out-of-gamut fallback cases. View the JSON fixtures.
  • Conversion fixtures: sRGB, XYZ, Lab/LCH, OKLab/OKLCH conversion values, round trips, and precision boundaries. View the JSON fixtures.
  • Export fixtures: Displayed-versus-exported values, parseable CSS and JSON, and safe allowlisted SVG output. View the JSON fixtures.

What a pass means. A passing group confirms the named vectors and tested properties still match the documented implementation. It does not prove every possible input, final browser rendering, full accessibility conformance, profile-aware print output, or every downstream export consumer.

Mixing models

Draft standardStandardHue Codex heuristic

The Color Mixer offers sRGB channel mixing, HSL shorter-hue mixing, Lab component mixing, and OKLab component mixing. The selected mode determines the midpoint and the exported CSS color-mix space where applicable.

HSL mixing interpolates hue along the shorter path and mixes saturation and lightness. Lab and OKLab mixing interpolate Cartesian components. sRGB mixing interpolates encoded channel values for predictable browser-oriented handoff.

Red/blue 50% midpoint visual test cases

StandardDraft standardHue Codex heuristicBrowser-dependent

These swatches use the same endpoints and weight as the numeric vectors later on this page: Color A #FF0000, Color B #0000FF, weightA = 0.5, weightB = 0.5. The visual difference is intentional because each interpolation model follows a different path through color space.

The linear-light sRGB swatch is shown as a comparison case only. Hue Codex sRGB mode uses encoded 8-bit sRGB channel mixing, so its expected midpoint remains #800080.

50% red/blue mix by space

Use this row as a quick visual regression check for the 50 percent red/blue mix examples.

Endpoints

Color A#FF0000Input red
Color B#0000FFInput blue

Hue Codex midpoint outputs

sRGB encoded#800080Average encoded channels
HSL shorter hue#FF00FFShort hue path through magenta
Lab components#C10088Cartesian Lab midpoint
OKLab components#8C53A2Cartesian OKLab midpoint

Comparison case

Linear-light sRGB#BC00BCNot Hue Codex sRGB mode

sRGB mixing domain

Hue Codex heuristicStandard

Hue Codex sRGB mode interpolates encoded sRGB channel values after HEX input has been resolved to 8-bit RGB channels. It does not convert channels to linear-light sRGB before mixing, and it does not convert a linear-light result back to encoded sRGB.

For each channel, the formula is channel = round(clamp(A8 * weightA + B8 * (1 - weightA), 0, 255)). This makes 50 percent Color A #FF0000 and Color B #0000FF resolve to #800080. A linear-light sRGB mix of those same endpoints would be much lighter, approximately #BC00BC, so the domain choice is intentionally visible.

Encoded sRGB versus linear-light sRGB at the same endpoints.
Mode/domainFormula domain50% #FF0000 / #0000FF result
Hue Codex sRGB modeEncoded 8-bit sRGB channels#800080
Linear-light sRGB comparisonLinearized sRGB channels converted back to encoded sRGBApproximately #BC00BC; not used by Hue Codex sRGB mode

HSL hue interpolation

StandardHue Codex heuristic

HSL mode first converts each resolved sRGB input to RGB-derived HSL. Hue angles are normalized into [0, 360), saturation and lightness are percentages, and the result is converted back through HSL-to-RGB with final channel rounding and clamping.

Hue travels the shorter signed path from Color A to Color B as Color A weight decreases. The signed delta is ((hueB - hueA + 540) % 360) - 180, so the range is [-180, 180). A perfect 180-degree tie resolves to -180, meaning it travels in the decreasing-hue direction from Color A.

Achromatic inputs have powerless hue because saturation is zero. Hue Codex currently uses the derived RGB-to-HSL fallback hue 0 for those colors during HSL mixing, while saturation and lightness still interpolate normally.

Exact HSL interpolation rules.
AreaRule
Hue sourcehueA and hueB come from rgb_to_hsl(hex_to_rgb(input)); achromatic colors return h = 0 and s = 0
Hue deltadelta = ((hueB - hueA + 540) % 360) - 180
Hue resulthue = normalize_degrees(hueA + delta * (1 - weightA))
180deg tieBecause delta is in [-180, 180), exactly opposite hues use delta = -180
Hue wrapnormalize_degrees returns a value in [0, 360), so paths can cross 0deg cleanly
Saturations = saturationA * weightA + saturationB * (1 - weightA)
Lightnessl = lightnessA * weightA + lightnessB * (1 - weightA)
Powerless hueIf one or both inputs are grayscale, their derived h = 0 participates in hue math even though that hue is non-authoritative

Alpha-premultiplied color mixing

StandardDraft standardHue Codex heuristic

Color Mixer accepts concrete translucent endpoints. It interpolates endpoint alpha linearly, converts the visible Color A weight into an alpha-premultiplied component weight, interpolates the selected sRGB, HSL, Lab, or OKLab components with that weight, and attaches the mixed alpha to the result.

For opaque endpoints, the adjusted weight equals the visible slider weight. If one endpoint is more transparent, it contributes proportionally less to the mixed components while its alpha still contributes to the resulting opacity.

The internal mixer uses resolved sRGB fallback channels as the starting coordinates. The CSS color-mix() handoff preserves the authored endpoint syntax so a capable color-managed browser may retain more wide-gamut information than the internal fallback preview.

Alpha policy for Lab and OKLab mixing.
ContextAlpha behaviorPremultiplication?
Hue Codex internal sRGB/HSL/Lab/OKLab mixerEndpoint alpha is preserved and interpolated linearlyYes. Component weight is adjusted by alpha before interpolation
Hue Codex Color Mixer CSS exportPreserves concrete authored endpoints with weights that sum to 100%The browser applies the selected CSS interpolation space and alpha rules
Arbitrary CSS Lab/OKLab interpolation with alphaBrowser applies CSS color interpolation rules for non-opaque colorsYes. Rectangular components are premultiplied by alpha before interpolation
Opacity CalculatorComposites a resolved foreground over a resolved background after color choiceSeparate source-over compositing step, not Lab/OKLab interpolation

Weight orientation

Hue Codex heuristicDraft standard

Color Mixer weight is the influence of Color A, the first input. The normalized value is weightA = clamp(weightPercent, 0, 100) / 100, and weightB = 1 - weightA.

For numeric channels or Cartesian components, Hue Codex uses result = A * weightA + B * (1 - weightA). Therefore 0 percent A returns Color B, 50 percent A returns an equal A/B mix, and 100 percent A returns Color A. Exported CSS follows the same orientation: color-mix(in space, A weightPercent%, B (100 - weightPercent)%).

Endpoint orientation for Color A and Color B.
UI weightFormula weightsExpected endpoint
0% AA * 0 + B * 1Color B, the second input
50% AA * 0.5 + B * 0.5Equal mix
100% AA * 1 + B * 0Color A, the first input

CSS color-mix handoff

Draft standardHue Codex heuristicBrowser-dependent

CSS Color 5 defines color-mix() with percentage normalization. CSS can treat omitted or over-specified percentages as normalized mix weights, and if the specified percentages sum to less than 100 percent the resulting color can carry reduced alpha.

Hue Codex Color Mixer avoids those ambiguous percentage cases. It accepts two concrete colors, calculates an alpha-aware resolved sRGB fallback internally, and emits CSS in the form color-mix(in space, A weightA%, B weightB%) where weightA + weightB is always exactly 100 percent.

The visible Color Mixer weight control is an integer-percentage slider. CSS export uses the same clamped control value that drives the internal mix; it does not apply a separate rounding step that could make exported color-mix() drift from the calculated result.

The exported CSS is therefore a reproducible handoff for the selected two-color mix, not a parser or simulator for every valid color-mix() expression. Hue Codex does not generate leftover-percentage-alpha output, omitted-percentage output, more-than-two-color color-mix(), currentColor, system colors, or other contextual source values.

How Color Mixer output maps to CSS color-mix().
Hue Codex modeInternal calculationCSS handoff spacePercentage behavior
Default sRGBEncoded 8-bit sRGB channel interpolationsrgbA weight is explicit; B weight is 100 - A
HSL shorter hueRGB-derived HSL with shorter-hue interpolationhsl shorter hueA weight is explicit; B weight is 100 - A
LabLab component interpolationlabA weight is explicit; B weight is 100 - A
OKLabOKLab component interpolationoklabA weight is explicit; B weight is 100 - A

Core formulas

StandardHue Codex heuristic

These compact formulas are the reproducible core for Hue Codex encoded sRGB mixing and opacity compositing. In the mixing formulas, w is the normalized Color A weight in [0, 1]. In the opacity formula, alpha is the normalized foreground opacity in [0, 1].

Both the sRGB mix formula and the opacity formula below operate on encoded 8-bit sRGB channel values after HEX parsing. Hue Codex does not convert those channels to linear-light RGB before mixing or compositing.

Encoded sRGB mix and encoded-sRGB source-over opacity
Given weight w in [0, 1]:

sRGB encoded mix:
R = round(Ra * w + Rb * (1 - w))
G = round(Ga * w + Gb * (1 - w))
B = round(Ba * w + Bb * (1 - w))

Source-over opacity in encoded sRGB channel space:
effective = foreground * alpha + background * (1 - alpha)

Per-channel opacity:
Re = round(Rf * alpha + Rbg * (1 - alpha))
Ge = round(Gf * alpha + Gbg * (1 - alpha))
Be = round(Bf * alpha + Bbg * (1 - alpha))

No srgb_to_linear() or linear_to_srgb() transfer step is applied.

Opacity compositing

StandardHue Codex heuristicApproximation

Opacity Calculator resolves a transparent foreground over a chosen background with source-over channel math: effective channel equals foreground channel times alpha plus background channel times one minus alpha.

The channel space is encoded 8-bit sRGB from the resolved HEX values. Hue Codex does not linearize to linear-light RGB for opacity compositing, and it rounds the resulting encoded channels back to HEX.

This means #000000 at 50 percent alpha over #FFFFFF resolves to #808080 in Hue Codex. A linear-light compositing comparison would be much lighter, approximately #BCBCBC, so the channel-space choice is intentionally documented as a Hue Codex implementation choice.

Contrast checks run against the effective composited color, not the original transparent declaration. Suggestion helpers can search for a source color whose composited result reaches the selected contrast target.

Gradient generation and sampling

Draft standardApproximationBrowser-dependentHue Codex heuristic

Gradient Generator accepts concrete CSS color literals, including alpha HEX, fixed named colors, RGB, HSL, HWB, Lab/LCH, OKLab/OKLCH, and supported color() profiles. It records those authored source colors with stop positions, optional midpoint hints, direction, shape, repeating state, and interpolation syntax, then creates a modern gradient plus a broader sRGB fallback.

Gradient Generator overlay text guidance samples the source stop colors plus each adjacent midpoint hint. Each sample is composited over the tool's declared white review canvas before contrast is scored. Midpoint alpha uses source-over-compatible premultiplied-alpha interpolation in encoded sRGB, so this remains a contrast heuristic rather than a full rendered-pixel proof for every interpolation mode and backdrop.

Gradient Palette Extractor samples along normalized stop positions and can interpolate in sRGB, HSL, Lab, or OKLab depending on the selected mode. It labels extracted swatches by their source position and provides contrast and role hints.

Gradient sample positions used by Hue Codex tools.
Tool/outputSample positionsHow colors are resolved
Gradient Generator overlay textEvery source stop plus every midpoint hint. Default 3-color setup: stops 0%, 52%, 100%; midpoint hints 26%, 76%. For other color counts, default stops are evenly spaced and hints are halfway between adjacent stops.Authored stop syntax and alpha remain in the gradient. Review samples resolve to sRGB, use premultiplied-alpha encoded-sRGB midpoint mixing, then composite over white for contrast.
Gradient Palette Extractor, 5 swatches0%, 25%, 50%, 75%, 100%Each position is resolved through the selected interpolation mode and current stop/hint state.
Gradient Palette Extractor, 7 swatches0%, 16.6667%, 33.3333%, 50%, 66.6667%, 83.3333%, 100%Each position is resolved through the selected interpolation mode and current stop/hint state. Display labels round to whole percentages.
Gradient Palette Extractor, 9 swatches0%, 12.5%, 25%, 37.5%, 50%, 62.5%, 75%, 87.5%, 100%Each position is resolved through the selected interpolation mode and current stop/hint state.

Gradient fallback generation

Draft standardHue Codex heuristicBrowser-dependent

When the selected gradient interpolation is modern syntax, Hue Codex creates a fallback by generating the same gradient with the interpolation override set to sRGB. In CSS output this means the modern "in oklab", "in display-p3", "in hsl shorter hue", or similar interpolation clause is removed for the fallback declaration.

Stop colors are not re-sampled through the modern interpolation path. The modern declaration retains each validated authored color literal. For the fallback declaration, every stop is converted to its resolved sRGB channels while preserving alpha as exact slash notation when needed. Stop positions, midpoint hints, type, repeating flag, linear direction, radial shape/size/position, and conic angle/position are preserved.

The fallback block is layered for the CSS cascade: first a solid background-color, then the sRGB fallback gradient, then the modern gradient only when it differs from the fallback. Browsers that cannot parse the modern interpolation declaration can keep the earlier sRGB gradient declaration.

The support caveat shown by the tool is: "Default gradient syntax is the broadest CSS option for production." for sRGB gradients, and "{Color space label} is modern gradient syntax; keep the sRGB gradient fallback for broader support." for non-sRGB interpolation modes.

Gradient fallback-generation rules.
ItemFallback rule
Stop colorsKeep validated authored color literals in the modern declaration; use resolved sRGB channels with preserved alpha in the broader fallback
Stop positionsPreserve every stop percentage exactly as normalized by the stop controls
Midpoint hintsPreserve hint percentages exactly; hints remain CSS color-hint positions between stops
Interpolation clauseFallback uses interpolation override srgb, which emits no "in ..." interpolation text
Solid fallbackUse the encoded-sRGB color sampled at 50% as background-color before any gradient image
Cascade orderbackground-color first, fallback background-image second, modern background-image third when different
sRGB-selected modeModern and fallback CSS are identical, so only one background-image declaration is emitted
Non-sRGB-selected modeReadiness displays "{label} + sRGB fallback" with a warning status

Limits

Draft standardApproximationBrowser-dependent
  • Sampled gradient contrast does not test every pixel in the final component.
  • Gradient-list share state preserves supported concrete CSS source strings and exact parsed decimal alpha. Older links that already contain eight-digit HEX retain that exact 8-bit alpha value when reopened.
  • CSS interpolation support varies by browser and syntax; fallbacks are included for broader compatibility.
  • Different mix spaces can be equally valid for different goals, so Hue Codex reports mode choice rather than hiding it.
  • Composited values depend on the selected background; changing the backdrop changes the final color and contrast.

Validation checks

Hue Codex heuristicBrowser-dependent
Mixing and gradient QA checks.
CheckExpected behavior
0 percent A mix endpointFor Color A #FF0000 and Color B #0000FF, output is #0000FF
100 percent A mix endpointFor Color A #FF0000 and Color B #0000FF, output is #FF0000
Color Mixer CSS export at 30 percent AFor Color A #FF0000 and Color B #0000FF in sRGB mode, CSS handoff is color-mix(in srgb, #FF0000 30%, #0000FF 70%)
Color Mixer avoids leftover-alpha color-mix outputHue Codex does not emit color-mix(in srgb, #FF0000 30%, #0000FF 30%); B is exported as 70%, not 30%, so exported percentages sum to 100% and no color-mix alpha is introduced
Color Mixer does not rely on over-100 normalizationHue Codex does not emit color-mix(in srgb, #FF0000 80%, #0000FF 80%); exported weights are explicit complements from the slider
50 percent A sRGB mixFor Color A #FF0000 and Color B #0000FF, encoded channels average to #800080
50 percent A linear-light sRGB comparisonThe same endpoints would be approximately #BC00BC in linear-light sRGB; Hue Codex sRGB mode does not use that path
50 percent A HSL shorter-hue mixFor Color A #FF0000 and Color B #0000FF, hue travels through 300deg and output is #FF00FF
HSL 180-degree tie from red to cyanFor Color A #FF0000 and Color B #00FFFF at 50 percent A, tie delta is -180 and output is #8000FF
HSL 180-degree tie from cyan to redFor Color A #00FFFF and Color B #FF0000 at 50 percent A, tie delta is -180 from cyan and output is #80FF00
HSL hue wrapFor hue 350deg to hue 10deg at 50 percent A, normalized midpoint hue is 0deg
HSL grayscale fallback hueFor Color A #808080 and Color B #FF0000 at 50 percent A, grayscale h=0 and s=0 produce #BF4040
Alpha 100 percentEffective color equals the foreground
Alpha 0 percentEffective color equals the background
Gradient stop orderingSmart spacing keeps stop positions ordered
Gradient Generator 3-color overlay samplesDefault source stops are 0%, 52%, 100% and overlay guidance also checks midpoint hints at 26% and 76%
Gradient Generator 5-color overlay samplesDefault source stops are 0%, 25%, 50%, 75%, 100% and overlay guidance also checks hints at 12.5%, 37.5%, 62.5%, 87.5%
Gradient fallback for OKLab interpolationModern CSS keeps "in oklab"; fallback CSS removes the interpolation clause and preserves the same HEX stops, stop percentages, hints, direction, and gradient type
Gradient fallback cascade orderFallback export emits background-color, then fallback background-image, then modern background-image when the modern CSS differs from the fallback
Gradient fallback for sRGB interpolationModern CSS and fallback CSS are identical, so only one background-image declaration is emitted after background-color
Gradient support caveat for modern interpolationTool copy says "{Color space label} is modern gradient syntax; keep the sRGB gradient fallback for broader support."
Gradient support caveat for sRGB interpolationTool copy says "Default gradient syntax is the broadest CSS option for production."
Gradient Palette Extractor 5 swatchesSample positions are 0%, 25%, 50%, 75%, 100%
Gradient Palette Extractor 7 swatchesSample positions are 0%, 16.6667%, 33.3333%, 50%, 66.6667%, 83.3333%, 100%; visible labels round to 0%, 17%, 33%, 50%, 67%, 83%, 100%
Gradient Palette Extractor 9 swatchesSample positions are 0%, 12.5%, 25%, 37.5%, 50%, 62.5%, 75%, 87.5%, 100%

Mixing and gradient pseudocode

StandardDraft standardHue Codex heuristicApproximationBrowser-dependent

Hue Codex treats the selected interpolation space as part of the result. The pseudocode below makes percentage orientation, hue handling, stop hints, and sample positions explicit.

Color mixing weight orientation and interpolation space
weight_a_from_percent(weight_percent):
  # The UI weight is Color A's percentage.
  # 0 percent A returns Color B; 100 percent A returns Color A.
  return clamp(weight_percent, 0, 100) / 100

mix_number(a, b, weight_a):
  # weight_a is the fraction of Color A.
  # weight_b = 1 - weight_a is the fraction of Color B.
  # Formula: result = (a * weight_a) + (b * (1 - weight_a)).
  return a * weight_a + b * (1 - weight_a)

shortest_hue_mix(hue_a, hue_b, weight_a):
  # Hue values are normalized to [0, 360).
  # delta is in [-180, 180). A 180 degree tie becomes -180.
  delta = ((hue_b - hue_a + 540) % 360) - 180
  return normalize_degrees(hue_a + delta * (1 - weight_a))

mix_hex(a, b, weight_a, mode):
  if mode == rgb:
    rgb_a = hex_to_encoded_srgb_8bit(a)
    rgb_b = hex_to_encoded_srgb_8bit(b)
    # This is encoded sRGB channel interpolation, not linear-light sRGB.
    # No srgb_to_linear() or linear_to_srgb() transfer step is applied.
    return rgb_to_hex(
      r = mix_number(rgb_a.r, rgb_b.r, weight_a),
      g = mix_number(rgb_a.g, rgb_b.g, weight_a),
      b = mix_number(rgb_a.b, rgb_b.b, weight_a)
    )
  if mode == hsl:
    hsl_a = rgb_to_hsl(hex_to_rgb(a))
    hsl_b = rgb_to_hsl(hex_to_rgb(b))
    # Achromatic RGB values have s = 0 and derived hue h = 0.
    # Hue is powerless in those cases, but this mixer uses the derived 0 value.
    h = shortest_hue_mix(hsl_a.h, hsl_b.h, weight_a)
    s = mix_number(hsl_a.s, hsl_b.s, weight_a)
    l = mix_number(hsl_a.l, hsl_b.l, weight_a)
    return rgb_to_hex(hsl_to_rgb(h, s, l))
  if mode == lab:
    # weight_a has already been adjusted for endpoint alpha.
    return rgb_to_hex(lab_to_rgb(mix L, a, b components))
  if mode == oklab:
    # weight_a has already been adjusted for endpoint alpha.
    return rgb_to_hex(oklab_to_rgb(mix L, a, b components))
Alpha-premultiplied mixer weight
premultiplied_mix_weight(color_a, color_b, weight_a):
  alpha = alpha_a * weight_a + alpha_b * (1 - weight_a)
  component_weight_a =
    if alpha > 0 then (alpha_a * weight_a) / alpha
    else weight_a

  return { alpha, component_weight_a }

alpha_aware_internal_mix(color_a, color_b, weight_a, mode):
  weights = premultiplied_mix_weight(color_a, color_b, weight_a)
  base_hex = mix_hex(
    opaque_srgb_channels(color_a),
    opaque_srgb_channels(color_b),
    weights.component_weight_a,
    mode
  )
  return attach_alpha(base_hex, weights.alpha)
Opacity compositing channel space
composite_hex_encoded_srgb(foreground_hex, background_hex, alpha):
  # Hue Codex opacity tools use encoded 8-bit sRGB channels from HEX.
  # They do not linearize to linear-light RGB before compositing.
  fg = hex_to_encoded_srgb_8bit(foreground_hex)
  bg = hex_to_encoded_srgb_8bit(background_hex)
  a = clamp(alpha, 0, 1)

  return rgb_to_hex(
    r = round(fg.r * a + bg.r * (1 - a)),
    g = round(fg.g * a + bg.g * (1 - a)),
    b = round(fg.b * a + bg.b * (1 - a))
  )

linear_light_comparison_only(foreground_hex, background_hex, alpha):
  fg = srgb_to_linear(hex_to_srgb_unit(foreground_hex))
  bg = srgb_to_linear(hex_to_srgb_unit(background_hex))
  mixed = fg * alpha + bg * (1 - alpha)
  return linear_to_srgb(mixed)
Color Mixer CSS color-mix() export mapping
css_space_for_mode(mode):
  if mode == rgb:   return "srgb"
  if mode == hsl:   return "hsl shorter hue"
  if mode == lab:   return "lab"
  if mode == oklab: return "oklab"

color_mix_export(color_a_source, color_b_source, weight_percent, mode):
  # Hue Codex preserves concrete authored endpoint syntax, including alpha,
  # and emits explicit complementary weights.
  # The visible Color Mixer slider is step=1, so normal UI state is integer percent.
  # If restored/imported state supplies a fractional control value, export that
  # same clamped value so the CSS handoff matches the internal mix.
  weight_a = clamp(weight_percent, 0, 100)
  weight_b = 100 - weight_a
  space = css_space_for_mode(mode)
  return "color-mix(in {space}, {color_a_source} {weight_a}%, {color_b_source} {weight_b}%)"

css_color_mix_normalization_context(percent_a, percent_b):
  total = percent_a + percent_b
  if total < 100:
    # CSS can multiply the mixed color alpha by total / 100.
    # Hue Codex Color Mixer does not emit this form.
    return "leftover-alpha color-mix form; not generated"
  if total > 100:
    # CSS can normalize the percentages back to a 100% total.
    # Hue Codex does not rely on this branch because output already sums to 100.
    return "over-specified color-mix form; not generated"
  return "Hue Codex export form"
Gradient sample positions, hints, and interpolation
sample_positions(count):
  if count == 1: return [0]
  return [index / (count - 1) for index in 0..count-1]

gradient_generator_default_stops(source_color_count):
  if source_color_count <= 1:
    stop[0] = 0
  else if source_color_count == 3:
    # Gradient Generator's 3-color fixture uses an intentional center bias.
    stop = [0, 52, 100]
  else:
    stop[index] = index / (source_color_count - 1) * 100
  hint[index] = (stop[index] + stop[index + 1]) / 2

gradient_generator_overlay_samples(source_colors, stops, hints):
  # Used for suggested overlay text in the Gradient Generator.
  # Samples are source stop colors plus one 50/50 preview mix per adjacent pair.
  samples = []
  for index, hex in source_colors:
    samples.push({ position: stops[index], hex: hex })
    if index < source_colors.length - 1:
      samples.push({
        position: hints[index],
        hex: mix_hex(hex, source_colors[index + 1], 0.5, rgb)
      })
  return samples

gradient_palette_extractor_positions(count):
  # UI choices are 5, 7, or 9 samples.
  # 5 => [0, .25, .5, .75, 1]
  # 7 => [0, .1666667, .3333333, .5, .6666667, .8333333, 1]
  # 9 => [0, .125, .25, .375, .5, .625, .75, .875, 1]
  return sample_positions(count)

gradient_palette_default_stops(source_color_count):
  stop[index] = source_color_count <= 1 ? 0 : index / (source_color_count - 1) * 100
  hint[index] = (stop[index] + stop[index + 1]) / 2

hinted_progress(raw_progress, local_hint):
  h = clamp(local_hint, 0.001, 0.999)
  if raw_progress <= h:
    return 0.5 * (raw_progress / h)
  return 0.5 + 0.5 * ((raw_progress - h) / (1 - h))

sample_gradient(source_colors, position_0_to_1, mode, stops, hints):
  p = clamp(position_0_to_1 * 100, 0, 100)
  if p <= first_stop: return first_color
  if p >= last_stop: return last_color

  segment = first index where p <= stop[index + 1]
  start = stop[segment]
  end = stop[segment + 1]
  raw = clamp((p - start) / (end - start), 0, 1)
  local_hint = (hint[segment] - start) / (end - start)
  progress = hinted_progress(raw, local_hint)

  # mix_hex weight is fraction of the segment start color.
  return mix_hex(source_colors[segment],
                 source_colors[segment + 1],
                 1 - progress,
                 mode)
Gradient fallback CSS generation
gradient_interpolation_method(interpolation, hue_method):
  if interpolation is empty or interpolation == srgb:
    return ""
  if interpolation is polar and hue_method is present:
    return " in " + interpolation + " " + hue_method + " hue"
  return " in " + interpolation

gradient_css(data, interpolation_override = data.interpolation):
  interpolation_text = gradient_interpolation_method(
    interpolation_override,
    data.hue_method
  )
  stop_list = join([
    color[index] + " " + stop[index] + "%"
    plus hint[index] + "%" between adjacent stops
  ])

  if data.type == linear:
    head = data.direction_keyword or data.angle + "deg"
  if data.type == radial:
    head = data.radial_shape + " " + data.radial_size +
           " at " + data.position_x + "% " + data.position_y + "%"
  if data.type == conic:
    head = "from " + data.angle + "deg at " +
           data.position_x + "% " + data.position_y + "%"

  return gradient_function(data.type, data.repeating) +
         "(" + head + interpolation_text + ", " + stop_list + ")"

gradient_fallback_css(data):
  # Source colors are already resolved six-digit sRGB HEX values.
  # The fallback does not resample the modern gradient path.
  # It preserves colors, stop positions, midpoint hints, type, direction,
  # radial/conic placement, and repeating state.
  data.fallback_css = gradient_css(data, srgb)
  data.modern_css = gradient_css(data, data.interpolation)
  data.solid_fallback = encoded_srgb_midpoint_at_50_percent(data)

  declarations = [
    "background-color: " + data.solid_fallback,
    "background-image: " + data.fallback_css
  ]

  if data.modern_css != data.fallback_css:
    declarations.push("background-image: " + data.modern_css)

  return declarations

Reproducible test vectors

StandardDraft standardHue Codex heuristicApproximation

These vectors show why Hue Codex names the active mix space. The same endpoints and percentage produce different midpoint colors in different models.

Mixing, compositing, and gradient midpoint vectors.
InputExpected outputNotes
#FF0000 and #0000FF, 50/50 sRGB mix#800080Encoded RGB channels are averaged and rounded
#FF0000 and #0000FF, 50/50 linear-light comparisonApproximately #BC00BC; not used by Hue Codex sRGB modeLinear-light mixing would linearize channels before interpolation and convert back to encoded sRGB
#FF0000 and #0000FF, 50/50 HSL shorter-hue mix#FF00FFHue travels the shorter path through 300deg
#FF0000 and #00FFFF, 50/50 HSL 180deg tie#8000FFTie resolves to delta -180, so hue travels from 0deg to 270deg at midpoint
#00FFFF and #FF0000, 50/50 HSL 180deg tie#80FF00Reversing inputs starts at 180deg and travels through 90deg at midpoint
HSL hue 350deg to 10deg, 50/500degHue wrap crosses 360deg/0deg on the shorter path
#808080 and #FF0000, 50/50 HSL mix#BF4040Gray resolves to h=0, s=0; saturation and lightness are interpolated
#FF0000 and #0000FF, 50/50 Lab mix#C10088Lab components are averaged, then converted back to sRGB
#FF0000 and #0000FF, 50/50 OKLab mix#8C53A2OKLab components are averaged, then converted back to sRGB
#FF0000 and #0000FF, 50/50 Lab mix with implicit alpha#C10088 and alpha remains 1Opaque endpoints make premultiplied weighting equivalent to ordinary component interpolation
#FF0000 and #0000FF, 50/50 OKLab mix with implicit alpha#8C53A2 and alpha remains 1Opaque endpoints make premultiplied weighting equivalent to ordinary component interpolation
20% alpha red and 80% alpha blue, 50/50 sRGB mix#3300CC80Alpha becomes 0.5; encoded sRGB channels use premultiplied weights before 8-bit HEX serialization
#000000 at 50% alpha over #FFFFFF#808080; raw contrast on #FFFFFF = 3.9494396480491156Hue Codex source-over compositing uses encoded 8-bit sRGB channels before contrast
#000000 at 50% alpha over #FFFFFF, linear-light comparisonApproximately #BCBCBC; not used by Hue Codex opacity toolsLinear-light compositing would linearize channels before source-over math and encode back to sRGB
#000000 to #FFFFFF gradient sampled at 50% in sRGB#808080Midpoint sample for a simple two-stop encoded sRGB gradient

Sources and standards

These references anchor the public standards, model origins, source records, and formats used by Hue Codex. Status badges distinguish stable standards, drafts, primary sources, model sources, Hue Codex heuristics, approximations, and browser-dependent behavior.

Tools using this methodology

These Hue Codex tools link to this methodology because they depend on the formulas, assumptions, limits, or data policy described here.

Report a calculation issue

If a result does not match the documented formula or fixture, send the exact input, tool settings, displayed result, expected result, precision mode, and browser details. Please do not include private images, personal information, or secrets.