This tutorial will walk you through the main features of jon/color-tools
with practical examples.
First, add the library to your project and require it:
(require '[jon.color-tools :as color])
Colors can be represented in many ways. This library supports the most common formats:
;; HEX - Web standard, strings starting with #
"#ff5733" ; Full 6-digit
"#f53" ; Short 3-digit (expanded to #ff5533)
;; RGB - Red, Green, Blue values 0-255
[255 87 51]
;; RGBA - RGB with Alpha channel 0-1
[255 87 51 0.8]
;; HSL - Hue (0-360), Saturation (0-100), Lightness (0-100)
[9 100 60]
;; HSV - Hue (0-360), Saturation (0-100), Value (0-100)
[9 80 100]
Converting between formats is straightforward:
;; HEX to RGB
(color/hex->rgb "#ff5733")
;=> [255 87 51]
;; RGB to HEX
(color/rgb->hex [255 87 51])
;=> "#ff5733"
;; RGB to HSL for color manipulation
(color/rgb->hsl [255 87 51])
;=> [9 100 60]
;; Chain conversions
(-> "#3498db"
color/hex->rgb
color/rgb->hsl)
;=> [204 70 53]
Always validate colors when accepting user input:
(color/valid-hex? "#ff5733") ;=> true
(color/valid-hex? "invalid") ;=> false
(color/valid-rgb? [255 87 51]) ;=> true
(color/valid-rgb? [300 87 51]) ;=> false (out of range)
(color/valid-hsl? [204 70 53]) ;=> true
Adjust the lightness of colors:
(def blue "#3498db")
;; Make it 20% lighter
(color/lighten blue 0.2)
;=> "#5dade2"
;; Make it 30% darker
(color/darken blue 0.3)
;=> "#2471a3"
;; Chain operations
(-> blue
(color/lighten 0.1)
(color/darken 0.05))
;=> "#4fa3d6"
Control the intensity of colors:
(def orange "#ff8c00")
;; More vivid
(color/saturate orange 0.2)
;=> "#ff7700"
;; More muted
(color/desaturate orange 0.4)
;=> "#cc9633"
;; Complete desaturation = grayscale
(color/desaturate orange 1.0)
;=> "#999999"
Rotate colors around the color wheel:
(def red "#e74c3c")
;; Shift 60 degrees toward orange
(color/adjust-hue red 60)
;=> "#e7e73c"
;; Complement (180 degrees)
(color/adjust-hue red 180)
;=> "#3ce7e7"
;; Or use the convenience function
(color/complementary red)
;=> "#3ce7e7"
WCAG defines minimum contrast ratios for accessibility:
;; Check contrast ratio
(color/contrast-ratio "#000000" "#ffffff")
;=> 21.0 ; Perfect contrast
(color/contrast-ratio "#3498db" "#ffffff")
;=> 3.14 ; Not enough for AA normal text
(color/contrast-ratio "#2c3e50" "#ffffff")
;=> 12.63 ; Excellent contrast
(def background "#f8f9fa")
(def text-color "#6c757d")
;; Check different standards
(color/accessible? background text-color :aa)
;=> false
(color/accessible? background text-color :aa-large)
;=> true
(color/accessible? background text-color :aaa)
;=> false
Automatically find accessible alternatives:
(def bg "#3498db")
(def desired-text "#e74c3c")
;; Find an accessible version of the text color
(color/find-accessible-color bg desired-text :aa)
;=> "#b71c1c" ; Darker red that meets AA standards
;; For large text (lower requirements)
(color/find-accessible-color bg desired-text :aa-large)
;=> "#c62828" ; Slightly lighter option
Generate harmonious color combinations based on color theory:
(def base-color "#e74c3c")
;; Complementary (opposite on color wheel)
(color/complementary base-color)
;=> "#3ce7e7"
;; Triadic (three colors forming triangle)
(color/triadic base-color)
;=> ["#4ce73c" "#3c4ce7"]
;; Split complementary (base + two colors near complement)
(color/split-complementary base-color)
;=> ["#3ce77b" "#3c7be7"]
;; Analogous (adjacent colors)
(color/analogous base-color 4 30) ; 4 colors, 30° apart
;=> ["#e7743c" "#e7ac3c" "#e7e43c" "#afe73c"]
Create palettes using variations of a single hue:
(color/monochromatic "#3498db" 5)
;=> ["#2980b9" "#3498db" "#5dade2" "#85c1e9" "#aed6f1"]
Use the palette generator for different strategies:
;; Generate a triadic theme
(color/generate-palette :triadic "#e74c3c")
;=> ["#4ce73c" "#3c4ce7"]
;; Generate analogous theme with custom options
(color/generate-palette :analogous "#3498db" {:count 5 :angle 20})
;=> ["#3498db" "#34b8db" "#34dbd8" "#34dbaf" "#34db87"]
;; Random palette for experimentation
(color/generate-palette :random nil {:count 3})
;=> ["#a47f3c" "#2e8b57" "#ff6347"]
Analyze color characteristics:
(def navy "#2c3e50")
(def coral "#ff6b6b")
;; Brightness (perceived luminance)
(color/brightness navy) ;=> 60 (dark)
(color/brightness coral) ;=> 122 (medium)
;; Boolean checks
(color/dark? navy) ;=> true
(color/light? coral) ;=> false
(color/warm? coral) ;=> true (red family)
(color/cool? navy) ;=> true (blue family)
(def vibrant "#ff1744") ; Hot pink
(def muted "#8d6e63") ; Brown grey
(color/vibrant? vibrant) ;=> true
(color/muted? muted) ;=> true
;; Custom thresholds
(color/vibrant? "#ff6b6b" 70) ; 70% saturation threshold
;=> false
Compare colors mathematically:
;; Euclidean distance in RGB space
(color/color-distance "#ff0000" "#ff0011")
;=> 17.0
;; Check similarity within threshold
(color/similar? "#ff0000" "#ff0011" 20)
;=> true
(color/similar? "#ff0000" "#00ff00" 50)
;=> false ; Too different
(defn generate-app-theme [primary-color]
(let [complementary (color/complementary primary-color)
analogous (color/analogous primary-color 2 30)]
{:primary primary-color
:secondary (first analogous)
:accent (second analogous)
:danger "#e74c3c"
:success "#27ae60"
:warning "#f39c12"
:info "#3498db"
:light (color/lighten primary-color 0.4)
:dark (color/darken primary-color 0.3)}))
(generate-app-theme "#9b59b6")
;=> {:primary "#9b59b6"
; :secondary "#59b69b"
; :accent "#5959b6"
; :danger "#e74c3c"
; ...}
(defn check-color-accessibility [bg-color text-colors]
(for [text-color text-colors]
(let [ratio (color/contrast-ratio bg-color text-color)]
{:color text-color
:ratio ratio
:aa-normal (>= ratio 4.5)
:aa-large (>= ratio 3.0)
:aaa-normal (>= ratio 7.0)})))
(check-color-accessibility "#ffffff"
["#000000" "#333333" "#666666" "#999999"])
;=> ({:color "#000000", :ratio 21.0, :aa-normal true, :aa-large true, :aaa-normal true}
; {:color "#333333", :ratio 12.63, :aa-normal true, :aa-large true, :aaa-normal true}
; {:color "#666666", :ratio 5.74, :aa-normal true, :aa-large true, :aaa-normal false}
; {:color "#999999", :ratio 2.85, :aa-normal false, :aa-large false, :aaa-normal false})
(defn create-color-scale [start-color end-color steps]
(for [i (range steps)]
(let [ratio (/ i (dec steps))]
(color/mix start-color end-color ratio))))
(create-color-scale "#3498db" "#e74c3c" 5)
;=> ("#3498db" "#5d7bc9" "#855fb7" "#ad42a4" "#e74c3c")
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
Ctrl+k | Jump to recent docs |
← | Move to previous article |
→ | Move to next article |
Ctrl+/ | Jump to the search field |