Color Coding with Elm
Tessa Kelly
NoRedInk
slides.com/tessak/color-coding-with-elm/live
tesk9/accessible-html
Accessible by law!
Generating colors with JS and CSS Custom Properties
at NordicJs 2018
A Colorful History
On Colors
TODO: image here
Opticks
A treatise of the reflections, refractions, inflections and colours of light
3-color printing
Additive Colors
Subtractive Colors
(Paint)
(Colored flashlights)
Modeling color
Albert Munsell
What did Munsell realize about human perception of color?
SharkD [CC BY-SA 3.0 (https://creativecommons.org/licenses/by-sa/3.0), from Wikimedia Commons
Using color systems
Web Color Modeling
RGB cube
(1,0,0)
(0,1,0)
(0,0,1)
(255,0,0)
(0,255,0)
(0,0,255)
"#00F"
"#0F0"
"#F00"
Hex cube
A Hex on Hex
linear-gradient( #F00, #FF7F00, #FF0, #0F0, #00F, #8B00FF )
Working with Colors
-- Is a red by another name just as red?
rgb (255, 0, 0) == hex "#F00"
-- Does red + green = yellow?
add (hex "#F00") (rgb (0, 255, 0))
-- ... Does red always look red?
Color Placement
Color Wheel
RGB & HSL
HSL Color Space
By HSL_color_solid_cylinder.png: SharkDderivative work: SharkD Talk - HSL_color_solid_cylinder.png, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=9801661
A Rainbow Gradient
Color Donut
Shades, Tints, and Tones
What we've discussed so far:
- Historical color modeling
- Color modeling on the web
- RGB
- Hex
- HSL
- Color perception & color delivery
Colorful Elm Packages
elm-lang/core
-- Color library API
{- arguments should be integers in [0, 255] -}
rgb : Int -> Int -> Int -> Color
rgba : Int -> Int -> Int -> Float -> Color
{- the hue is in radians and the saturation and lightness in [0,1] -}
hsl : Float -> Float -> Float -> Color
hsla : Float -> Float -> Float -> Float -> Color
{- Produces a gray -- 0 is white, 1 is black -}
greyscale : Float -> Color
complement : Color -> Color
-- Color library API
toRgb :
Color
-> { red : Int
, green : Int
, blue : Int
, alpha : Float
}
toHsl :
Color
-> { hue : Float
, saturation : Float
, lightness : Float
, alpha : Float
}
-- Color library API
linear :
( Float, Float )
-> ( Float, Float )
-> List ( Float, Color )
-> Gradient
radial :
( Float, Float )
-> Float
-> ( Float, Float )
-> Float
-> List ( Float, Color )
-> Gradient
avh4/elm-color
rgb255 : Int -> Int -> Int -> Color
fromRgba :
{ red : Float
, green : Float
, blue : Float
, alpha : Float
}
-> Color
fromHsla :
{ hue : Float
, saturation : Float
, lightness : Float
, alpha : Float
}
-> Color
{- Produced string matches: rgba(rr.rr%,gg.gg%,bb.bb%,a.aaa) -}
toCssString : Color -> String
rtfeldman/elm-css
-- Internal modeling of colors
type alias Color =
ColorValue { red : Int, green : Int, blue : Int, alpha : Float }
-- Css library API
rgb : Int -> Int -> Int -> Color
rgba : Int -> Int -> Int -> Float -> Color
{- saturation and lightness should be between 0 and 1 -}
hsl : Float -> Float -> Float -> Color
hsla : Float -> Float -> Float -> Float -> Color
hex : String -> Color
mdgriffith/elm-ui
-- Internal modeling of Color
type Color = Rgba Float Float Float Float
-- External elm-ui API
rgba : Float -> Float -> Float -> Float -> Color
rgb : Float -> Float -> Float -> Color
rgba : Float -> Float -> Float -> Float -> Color
rgba255 : Int -> Int -> Int -> Float -> Color
fromRgb : { red : Float, green : Float, blue : Float, alpha : Float}
-> Color
fromRgb255 : { red : Int, green : Int, blue : Int, alpha : Float }
-> Color
-- External elm-ui API
toRgb :
Color
-> { red : Float
, green : Float
, blue : Float
, alpha : Float
}
-- avh4/elm-color
div [ style "color" (Color.toCssString (Color.rgb 1 0 0)) ]
[ text "Hello, world!" ]
-- rtfeldman/elm-css
div [ css [ Css.color (Css.rgb 255 0 0 ) ] ] [ text "Hello, world!" ]
-- mdgriffith/elm-ui
Element.el [ Font.color (Element.rgb255 255 0 0) ]
(Element.text "Howdy!")
What more is there?
- Contrast
- Blending
- Adjustments
- Generation
- Palettes
Luminance and Contrast
Luminance
luminance : (Float, Float, Float) -> Float
luminance ( r, g, b ) =
let
red = fromSRGB (r / 255)
green = fromSRGB (g / 255)
blue = fromSRGB (b / 255)
fromSRGB srgb =
if srgb <= 0.03928 then
srgb / 12.92
else
((srgb + 0.055) / 1.055) ^ 2.4
in
(0.2126 * red) + (0.7152 * green) + (0.0722 * blue)
Contrast
contrast : Color -> Color -> Float
contrast color1 color2 =
let
luminance1 = Color.luminance color1
luminance2 = Color.luminance color2
in
if luminance1 > luminance2 then
(luminance1 + 0.05) / (luminance2 + 0.05)
else
(luminance2 + 0.05) / (luminance1 + 0.05)
Accessibility
-- noahzgordon/elm-color-extra
contrastRatio : Color -> Color -> Float
luminance : Color -> Float
-- tesk9/palette
contrast : Color -> Color -> Float
luminance : Color -> Float
-- noahzgordon/elm-color-extra
maximumContrast : Color -> List Color -> Maybe Color
-- tesk9/palette
sufficientContrast : WCAGLevel
-> { fontSize : Float , fontWeight : Int }
-> Color -> Color -> Bool
Blending Colors
Color.Blending.difference
lightBlue
orange
Color.Blending.multiply
lightBlue
orange
Blend.add lightBlue orange
Blend.subtract lightBlue orange
Blend.multiply lightBlue orange
Blend.divide lightBlue orange
subtractive a b =
let ( ra, ga, ba ) =
Color.toRGB a
( rb, gb, bb ) =
Color.toRGB b
in
Color.fromRGB
( abs (255 - (ra + rb))
, abs (255 - (ga + gb))
, abs (255 - (ba + bb))
)
import Color.Blend
exposing (
add
)
Adjusting & Generating Colors
Adjusting Saturation
viewShades : Color -> Html msg
viewShades color =
viewPalette color
[ Color.Generator.shade 10 color
, Color.Generator.shade 20 color
, Color.Generator.shade 30 color
, Color.Generator.shade 40 color
]
viewTints : Color -> Html msg
viewTints color =
viewPalette color
[ Color.Generator.tint 10 color
, Color.Generator.tint 20 color
, Color.Generator.tint 30 color
, Color.Generator.tint 40 color
, Color.Generator.tint 50 color
]
viewTones : Color -> Html msg
viewTones color =
viewPalette color
[ Color.Generator.tone -100 color
, Color.Generator.tone -80 color
, Color.Generator.tone -60 color
, Color.Generator.tone -40 color
, Color.Generator.tone -20 color
]
Generation
Through Interpolation
Generation
Through the Color Wheel
-- tesk9/palette
-- module Color.Generator
complementary : Color -> Color
-- tesk9/palette
-- module Color.Generator
triadic : Color -> ( Color, Color )
-- tesk9/palette
-- module Color.Generator
tetratic : Float -> Color -> ( Color, Color, Color )
Full Color Palettes
Building Towards Palettes
dawehner/elm-colorbrewer
Sequential data
Diverging data
Qualitative data
terezka/line-charts
Palette.X11
Palette.Cubehelix
Palette.Cubehelix
-- using tesk9/palette
import Color
import Palette.Cubehelix as Cubehelix
Cubehelix.generateAdvanced colorCount
{ startingColor =
Color.fromHSL ( 20, 100, 0 )
, rotationDirection = Cubehelix.RGB
, rotations = 0.9
, gamma = 1.0
}
-- using tesk9/palette
import Color
import Palette.Cubehelix as Cubehelix
Cubehelix.generateAdvanced colorCount
{ startingColor =
Color.fromHSL ( 20, 60, 0 )
, rotationDirection = Cubehelix.BGR
, rotations = 1.5
, gamma = 0.5
}
Elm State
🧡
(@t_kelly9)
Packages
References
Read more about cubehelix in this article and read Green's paper. Play with ColorBrewer colors on a map. Learn about the Tango project. Read the Wikipedia article on web colors. Reference the relative luminance algorithm and the contrast success criteria from WCAG. Read Goethe's Theory of Colors or Newton's Opticks on Project Gutenberg. Dig up some fun-with-colors with Munsell's Soil Book of Colors.
Thank you!
Color Coding with Elm
By Tessa K
Color Coding with Elm
- 1,616