<color-contrast
foreground="AliceBlue, AntiqueWhite, Aqua, Aquamarine, Azure, Beige, Bisque, Black, BlanchedAlmond, Blue, BlueViolet, Brown, BurlyWood, CadetBlue, Chartreuse, Chocolate, Coral, CornflowerBlue, Cornsilk, Crimson, Cyan, DarkBlue, DarkCyan, DarkGoldenRod, DarkGray, DarkGreen, DarkKhaki, DarkMagenta, DarkOliveGreen, DarkOrange, DarkOrchid, DarkRed, DarkSalmon, DarkSeaGreen, DarkSlateBlue, DarkSlateGray, DarkTurquoise, DarkViolet, DeepPink, DeepSkyBlue, DimGray, DodgerBlue, FireBrick, FloralWhite, ForestGreen, Fuchsia, Gainsboro, GhostWhite, Gold, GoldenRod, Gray, Green, GreenYellow, HoneyDew, HotPink, IndianRed, Indigo, Ivory, Khaki, Lavender, LavenderBlush, LawnGreen, LemonChiffon, LightBlue, LightCoral, LightCyan, LightGoldenRodYellow, LightGray, LightGreen, LightPink, LightSalmon, LightSeaGreen, LightSkyBlue, LightSlateGray, LightSteelBlue, LightYellow, Lime, LimeGreen, Linen, Magenta, Maroon, MediumAquaMarine, MediumBlue, MediumOrchid, MediumPurple, MediumSeaGreen, MediumSlateBlue, MediumSpringGreen, MediumTurquoise, MediumVioletRed, MidnightBlue, MintCream, MistyRose, Moccasin, NavajoWhite, Navy, OldLace, Olive, OliveDrab, Orange, OrangeRed, Orchid, PaleGoldenRod, PaleGreen, PaleTurquoise, PaleVioletRed, PapayaWhip, PeachPuff, Peru, Pink, Plum, PowderBlue, Purple, RebeccaPurple, Red, RosyBrown, RoyalBlue, SaddleBrown, Salmon, SandyBrown, SeaGreen, SeaShell, Sienna, Silver, SkyBlue, SlateBlue, SlateGray, Snow, SpringGreen, SteelBlue, Tan, Teal, Thistle, Tomato, Turquoise, Violet, Wheat, White, WhiteSmoke, Yellow, YellowGreen"
background="AliceBlue, AntiqueWhite, Aqua, Aquamarine, Azure, Beige, Bisque, Black, BlanchedAlmond, Blue, BlueViolet, Brown, BurlyWood, CadetBlue, Chartreuse, Chocolate, Coral, CornflowerBlue, Cornsilk, Crimson, Cyan, DarkBlue, DarkCyan, DarkGoldenRod, DarkGray, DarkGreen, DarkKhaki, DarkMagenta, DarkOliveGreen, DarkOrange, DarkOrchid, DarkRed, DarkSalmon, DarkSeaGreen, DarkSlateBlue, DarkSlateGray, DarkTurquoise, DarkViolet, DeepPink, DeepSkyBlue, DimGray, DodgerBlue, FireBrick, FloralWhite, ForestGreen, Fuchsia, Gainsboro, GhostWhite, Gold, GoldenRod, Gray, Green, GreenYellow, HoneyDew, HotPink, IndianRed, Indigo, Ivory, Khaki, Lavender, LavenderBlush, LawnGreen, LemonChiffon, LightBlue, LightCoral, LightCyan, LightGoldenRodYellow, LightGray, LightGreen, LightPink, LightSalmon, LightSeaGreen, LightSkyBlue, LightSlateGray, LightSteelBlue, LightYellow, Lime, LimeGreen, Linen, Magenta, Maroon, MediumAquaMarine, MediumBlue, MediumOrchid, MediumPurple, MediumSeaGreen, MediumSlateBlue, MediumSpringGreen, MediumTurquoise, MediumVioletRed, MidnightBlue, MintCream, MistyRose, Moccasin, NavajoWhite, Navy, OldLace, Olive, OliveDrab, Orange, OrangeRed, Orchid, PaleGoldenRod, PaleGreen, PaleTurquoise, PaleVioletRed, PapayaWhip, PeachPuff, Peru, Pink, Plum, PowderBlue, Purple, RebeccaPurple, Red, RosyBrown, RoyalBlue, SaddleBrown, Salmon, SandyBrown, SeaGreen, SeaShell, Sienna, Silver, SkyBlue, SlateBlue, SlateGray, Snow, SpringGreen, SteelBlue, Tan, Teal, Thistle, Tomato, Turquoise, Violet, Wheat, White, WhiteSmoke, Yellow, YellowGreen"
algorithm="wcag21"
min="4.5"
></color-contrast>
body {
padding: 2rem;
}
import { attr, html, css, FASTElement, repeat, observable } from "https://unpkg.com/@microsoft/fast-element@2.0.0/dist/fast-element.min.js"
import Color from "https://colorjs.io/dist/color.js";
const styles = css`
table {
font-family: system-ui;
font-feature-setting: tnums;
border: 1px solid #ccc;
}
thead th {
border-bottom: 1px solid #ccc;
background: canvas;
position: sticky;
top: 0;
z-index: 2;
}
th, td {
text-align: start;
padding: 0.5rem 1rem;
}
td {
white-space: nowrap;
}
td.pass::before {
content: '✅ '
}
td.fail::before {
content: '❌ '
}
tbody th {
border-right: 1px solid #ccc;
background: canvas;
position: sticky;
left: 0;
}
`
const trTemplate = (rootEl) => {
return html`${el => {
let fg = new Color(el)
return html`
<tr style="color: ${el}">
<th>${el}</th>
${repeat(rootEl.backgroundColors, bgColor => tdTemplate(rootEl, fg) )}
</tr>
`
}}`
}
const tdTemplate = (rootEl, fgColor) => {
return html`${bgColor => {
let bg = new Color(bgColor)
let contrastRatio = fgColor.contrast(bg, rootEl.algorithm).toFixed(2)
let className = contrastRatio >= parseInt(rootEl.min, 10) ? 'pass': 'fail'
return html`
<td class="${className}"
style="background-color: ${bgColor}; opacity: ${rootEl.hideFails && className === 'fail'? 0 : 1 }"
>
${contrastRatio}
</td>`
}}`
}
const template = html`
<table>
<thead>
<tr>
<th> </th>
${repeat((el) => el.backgroundColors, html`<th>${x => x}</th>`)}
</tr>
</thead>
<tbody>
${repeat((el) => el.foregroundColors, (rootEl) => trTemplate(rootEl))}
</tbody>
</table>
`
class ColorContrast extends FASTElement {
@attr
public foreground = ''
@attr
public background = ''
@attr
public algorithm = ''
@attr
public min = 4.5
@attr({ mode: 'boolean', attribute: 'hide-fails' })
public hideFails: false
@observable
foregroundColors = []
@observable
backgroundColors = []
connectedCallback() {
super.connectedCallback()
this.foregroundColors = this.foreground?.split(",").map(c => c.trim())
this.backgroundColors = this.background?.split(",").map(c => c.trim())
}
}
/* Roll it up to get it on the page */
const definition = ColorContrast.compose({
name: 'color-contrast',
styles,
template
})
definition.define(globalThis.customElements)
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.