Colour format cheat sheet

A reference for what each format expects, because the ranges and orderings are where the bugs are. Every format here can be pasted into the picker and converted to every other.

Hex

FormMeaningExample
#rgbEach digit doubled#f00 is #ff0000
#rgbaDoubled, alpha last#f008
#rrggbbTwo digits per channel#ff0000
#rrggbbaaAlpha last, CSS ordering#ff000080
0xRRGGBBC-style literal0xFF0000
0xAARRGGBBAlpha first0xFFFF0000

The eight-digit ambiguity is the thing to watch. CSS puts alpha last; Android, Flutter and .NET put it first. Both readings are offered when you paste one.

CSS colour functions

FunctionChannelsRanges
rgb()red, green, blue0–255 or 0%–100%
hsl()hue, saturation, lightness0–360, 0%–100%, 0%–100%
hwb()hue, whiteness, blackness0–360, 0%–100%, 0%–100%
lab()L, a, b0%–100%, roughly ±125
lch()L, chroma, hue0%–100%, 0–150, 0–360
oklab()L, a, b0%–100%, roughly ±0.4
oklch()L, chroma, hue0%–100%, 0–0.4, 0–360
color(space …)space-dependentusually 0–1

Modern syntax separates channels with spaces and alpha with a slash:rgb(255 0 0 / 50%). The older comma form with rgba() still works everywhere.

color() accepts srgb, srgb-linear,display-p3, a98-rgb, prophoto-rgb,rec2020, xyz-d50 and xyz-d65. Note thatsrgb-linear gives you exactly the linear values a shader wants.

Shader vectors

LanguageTypesRange
GLSLvec3, vec40–1 float
GLSLivec3, uvec30–255 integer
HLSLfloat3, float4, half40–1 float
Unity ShaderLabfixed3, fixed40–1 float
WGSLvec3f, vec4f, vec3<f32>0–1 float

None of these say anything about the colour space, which is the whole problem. Avec3 may hold display (sRGB) or linear values and only context tells you which. See sRGB vs linear for how to tell and why it matters.

A single argument splats: vec3(0.5) is the same asvec3(0.5, 0.5, 0.5).

Engine and framework constructors

PlatformConstructorSpaceRange
Unitynew Color(r, g, b, a)display0–1
Unitynew Color32(r, g, b, a)display0–255
UnrealFLinearColor(r, g, b, a)linear0–1
UnrealFColor(r, g, b, a)display0–255
GodotColor(r, g, b, a)display0–1
FlutterColor(0xAARRGGBB)displaypacked ARGB
FlutterColor.fromARGB(a, r, g, b)display0–255
AndroidColor.rgb(r, g, b)display0–255
SwiftUIColor(red:green:blue:)display0–1
UIKitUIColor(red:green:blue:alpha:)display0–1

The Unreal pair is the one to be careful with. FLinearColor andFColor are not the same numbers scaled differently — they are different colour spaces. See Unity Color vs Color32 andUnreal FLinearColor vs FColor for when to use each.

Bare numbers

Three or four numbers with no wrapper are genuinely ambiguous, and this site treats them that way rather than guessing:

Percentages, square brackets, curly braces and semicolons are all tolerated, so pasting straight out of source code generally works.

Other packed forms

FormMeaning
Decimal integer16711680 is #ff0000 — Java's getRGB(), Discord role colours
0x with 6 digitsPlain RGB literal

Direct conversions

Each of these has its own page with an explanation of what changes in that particular conversion. Or paste into the picker and read off whichever row you need.

Questions

Is an eight-digit hex code RGBA or ARGB?

It depends on where it came from, which is exactly why it causes bugs. CSS orders it RGBA, so #ff000080 is half-transparent red. Android, Flutter and .NET order it ARGB, so 0xFF0000FF is opaque blue. The prefix is your best clue: a hash usually means RGBA, a 0x usually means ARGB.

Why does rgb(0.8, 0.2, 0.1) come out black?

Because CSS defines rgb() channels as 0–255 or percentages, so 0.8 means 0.8 out of 255, which rounds to 1. If you meant normalised floats you want a shader vector or a bare triple instead.

What is the difference between HSV and HSB?

Nothing. They are two names for the same model. Photoshop calls it HSB, most code calls it HSV. Both differ from HSL, which uses a different third axis.