API Reference¶
Everything you can do with CM-Colors (the non-scary version)
This is your complete guide to all the functions in CM-Colors. Don’t worry - you probably only need the first one, but the rest are here if you get curious!
- class cm_colors.CMColors[source]¶
Bases:
objectCMColors provides a comprehensive API for color accessibility and manipulation. All core functionalities are exposed as methods of this class.
The main CM-Colors class. Create one of these, then use it to tune your colors!
The One You Actually Need¶
Start here. This is probably all you’ll ever use.
- CMColors.tune_colors(text, bg, large_text: bool = False, details: bool = False)[source]¶
Adjusts the text color to meet WCAG contrast requirements against a background.
- Parameters:
text (str|tuple) – Text color in any supported format (hex string, rgb(a) string, named color, or RGB tuple).
bg (str|tuple) – Background color in any supported format (hex string, rgb(a) string, named color, or RGB tuple).
large_text (bool) – True when text is considered large (18pt+ or 14pt+ bold); affects required WCAG level.
details (bool) – If True, return a detailed report instead of the simple result tuple.
- Returns:
- tuple: (tuned_text_rgb_str, is_accessible)
tuned_text_rgb_str (str): Adjusted text color as an ‘rgb(…)’ string. is_accessible (bool): True if the adjusted pair meets at least WCAG AA, False otherwise.
- If details is True:
- dict: Detailed report with keys:
text: original text color input
tuned_text: adjusted text color as an ‘rgb(…)’ string
bg: background color input
large: value of the large_text parameter
wcag_level: resulting WCAG compliance level (‘AAA’, ‘AA’, or ‘FAIL’)
improvement_percentage: percentage improvement in contrast
status: True if wcag_level != ‘FAIL’, False otherwise
message: human-readable status message
- Return type:
If details is False
What it does: Takes your pretty colors and makes tiny adjustments so everyone can read them.
When to use it: Always! This is the magic function that fixes accessibility problems.
What you get back:
Simple mode (default): Just the tuned color and whether it’s accessible
Details mode (
details=True): Full report with improvement stats and messages
Examples:
# Simple - just get the fixed color text = "rgb(100, 100, 100)" # Gray text background = "rgb(255, 255, 255)" # White background tuned_text, is_accessible = cm.tune_colors(text, background) print(f"Tuned color: {tuned_text}") #"rgb(98, 98, 98)" print(f"Is accessible: {is_accessible}") #True
# Detailed - get the full report result = cm.tune_colors(text, background, details=True) print(f"Tuned color: {result['tuned_text']}") print(f"WCAG level: {result['wcag_level']}") print(f"Message: {result['message']}") print(f"Improvement: {result['improvement_percentage']:.1f}%")
# Large text has different requirements large_tuned_text, large_accessible = cm.tune_colors(text, background, large_text=True)
Color Checking Functions¶
For when you want to test your colors before tuning them
- CMColors.contrast_ratio(text_color, bg_color) float[source]¶
Compute the WCAG contrast ratio between two colors.
- Parameters:
text_color – Text color in any supported format (hex, “rgb(…)”, “rgba(…)”, 3-tuple, named color, etc.).
bg_color – Background color in any supported format.
- Returns:
The computed contrast ratio between the text and background colors.
- Return type:
float
- Raises:
ValueError – If either color cannot be parsed or the color pair is invalid.
What it does: Gives you a number that tells you how readable your text is.
The magic numbers:
Under 4.5 = Hard to read (needs tuning)
4.5-7.0 = Pretty readable (AA level)
Over 7.0 = Super readable (AAA level)
Example:
score = cm.contrast_ratio((80, 80, 80), (255, 255, 255)) print(f"Readability score: {score:.1f}") # Higher numbers = easier to read
—
- CMColors.wcag_level(text_color, bg_color, large_text: bool = False) str[source]¶
Determine the WCAG contrast compliance level for a text/background color pair, considering large-text rules.
- Parameters:
text_color – Text color in any supported format (hex, rgb/rgba string, (r,g,b) tuple, named color, etc.). RGBA colors will be composited as needed.
bg_color – Background color in any supported format.
large_text (bool) – True when text is considered large (18pt+ or 14pt+ bold), False otherwise.
- Returns:
‘AAA’, ‘AA’, or ‘FAIL’ indicating the WCAG compliance level.
- Return type:
str
- Raises:
ValueError – If one or both colors cannot be parsed or are otherwise invalid.
What it does: Tells you if your colors pass the readability test.
What the results mean:
“FAIL” = People can’t read this 😞
“AA” = Most people can read this fine ✅ (This is what you want)
“AAA” = Everyone can read this easily ⭐
Examples:
# Normal text result = cm.wcag_level((100, 100, 100), (255, 255, 255)) print(f"Your colors: {result}") # "AA", "AAA", or "FAIL" # Large text (18pt+ or 14pt+ bold) has different requirements large_result = cm.wcag_level((100, 100, 100), (255, 255, 255), large_text=True) print(f"Large text level: {large_result}")
Color Difference Functions¶
For perfectionists who want to know exactly how much colors changed
- CMColors.delta_e(color1, color2) float[source]¶
Compute the Delta E 2000 color difference between two colors.
Accepts color inputs in any supported format (hex, rgb/rgba strings, tuples, named colors, etc.). RGBA inputs will be composited as needed before comparison.
- Parameters:
color1 – First color (text or sample) in any supported format.
color2 – Second color (background or reference) in any supported format.
- Returns:
The Delta E 2000 distance. Values below about 2.3 are typically imperceptible to the average observer.
- Return type:
float
What it does: Measures how different two colors look to human eyes.
The magic numbers:
Under 1.0 = You literally can’t tell the difference
1.0-2.3 = Barely noticeable difference
2.3+ = You can clearly see the difference
Example:
original = (100, 100, 100) adjusted = (85, 85, 85) difference = cm.delta_e(original, adjusted) print(f"Visual difference: {difference:.2f}") # Lower = more similar looking
Color Format Functions¶
For working with different color formats
- CMColors.parse_to_rgb(color: str) Tuple[int, int, int][source]¶
Convert a color string in common formats to an RGB triple.
Accepts hex (#RRGGBB, #RGB), functional rgb()/rgba() (alpha composited over white), and CSS color names. Parsing is case-insensitive and will composite RGBA into an opaque RGB when an alpha channel is provided.
- Parameters:
color (str) – Color value in hex, rgb(a) function notation, or named color.
- Returns:
(R, G, B) with each component as an integer in the range 0–255.
- Return type:
tuple
What it does: Converts hex codes, rgb strings, or other formats to RGB tuples.
When to use it: When you have colors in different formats and need them as RGB tuples.
Example:
# Convert hex to RGB rgb = cm.parse_to_rgb("#7B2DC8") print(f"RGB: {rgb}") # (123, 45, 200) # You can also pass different formats directly to tune_colors tuned_text, accessible = cm.tune_colors("#7B2DC8", "#FFFFFF")
Color Conversion Functions¶
For when you need to work with different color systems
- CMColors.rgb_to_oklch(rgb: Tuple[int, int, int]) Tuple[float, float, float][source]¶
Converts an RGB color to the OKLCH color space. OKLCH is a perceptually uniform color space, making it ideal for color manipulation.
- Parameters:
rgb (Tuple[int, int, int]) – The RGB tuple (R, G, B).
- Returns:
- The OKLCH tuple (Lightness, Chroma, Hue).
Lightness is 0-1, Chroma is 0-~0.4, Hue is 0-360.
- Return type:
Tuple[float, float, float]
What it does: Converts regular RGB colors to OKLCH (a fancy color system that matches human vision).
Why you might need this: OKLCH is better for making color adjustments that look natural.
What you get: Three numbers - Lightness (0-1), Chroma (0-~0.4), and Hue angle (0-360°).
Example:
rgb = (255, 128, 64) # Orange color l, c, h = cm.rgb_to_oklch(rgb) print(f"Lightness: {l:.2f}, Chroma: {c:.2f}, Hue: {h:.0f}°")
—
- CMColors.oklch_to_rgb(oklch: Tuple[float, float, float]) Tuple[int, int, int][source]¶
Converts an OKLCH color back to the RGB color space.
- Parameters:
oklch (Tuple[float, float, float]) – The OKLCH tuple (Lightness, Chroma, Hue).
- Returns:
The RGB tuple (R, G, B).
- Return type:
Tuple[int, int, int]
What it does: Converts OKLCH colors back to regular RGB.
When to use it: After you’ve adjusted colors in OKLCH space and need them for CSS.
Example:
# Convert back to RGB for use in your website oklch_color = (0.7, 0.15, 45.0) rgb = cm.oklch_to_rgb(oklch_color) print(f"RGB: {rgb}") # Ready for CSS!
—
- CMColors.rgb_to_lab(rgb: Tuple[int, int, int]) Tuple[float, float, float][source]¶
Converts an RGB color to the CIELAB (LAB) color space.
- Parameters:
rgb (Tuple[int, int, int]) – RGB components (R, G, B) with values 0–255.
- Returns:
LAB tuple (L, a, b) where L is perceptual lightness.
- Return type:
Tuple[float, float, float]
What it does: Converts RGB to LAB color space (used in professional color work).
When you need it: Mostly for advanced color calculations or if you’re doing print design.
Example:
rgb = (255, 128, 64) l_star, a_star, b_star = cm.rgb_to_lab(rgb) print(f"LAB: L*={l_star:.1f}, a*={a_star:.1f}, b*={b_star:.1f}")
Quick Reference Card¶
Just want readable colors?
# Simple way
tuned_text, is_accessible = cm.tune_colors(your_text, your_background)
# With details
result = cm.tune_colors(your_text, your_background, details=True)
Want to check colors first?
level = cm.wcag_level(your_text, your_background)
if level == "FAIL":
tuned_text, _ = cm.tune_colors(your_text, your_background)
Want to see how much changed?
original = (100, 100, 100)
t, _ = cm.tune_colors(original, background)
difference = cm.delta_e(original, tuned_text)
# Under 2.3 = barely noticeable
Working with different color formats?
# Parse any format
rgb = cm.parse_to_rgb("#FF8040")
# Or use directly
tuned_text, _ = cm.tune_colors("#FF8040", "#FFFFFF")
Large text (18pt+ or 14pt+ bold)?
# Large text has relaxed contrast requirements
tuned_text, accessible = cm.tune_colors(text, bg, large_text=True)
level = cm.wcag_level(text, bg, large_text=True)
Function Return Values Quick Guide¶
tune_colors() returns:
details=False (default):
(tuned_color_string, is_accessible_boolean)details=True: Dictionary with keys:
'tuned_text'- The tuned color'status'- True if accessible, False if failed'wcag_level'- “AA”, “AAA”, or “FAIL”'improvement_percentage'- How much contrast improved'message'- Human-readable status message
Other functions return:
contrast_ratio()- Float (higher = more readable)wcag_level()- String (“AA”, “AAA”, or “FAIL”)delta_e()- Float (lower = more similar)parse_to_rgb()- RGB tuple (r, g, b)Color conversions - Tuples in respective color spaces