Choose Higher Contrast Text Color
by ktsn
HTML
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
<ul>
<li
v-for="(color, i) in colors"
:key="i"
:style="{ backgroundColor: toCssColor(color), color: textColor(color) }"
>
{{ toCssColor(color) }}
</li>
</ul>
</div>
CSS
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
li {
padding: 10px 20px;
}
JavaScript
new Vue({
el: '#app',
data() {
const lightness = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
const hue = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330]
const colors = []
hue.forEach(h => {
lightness.forEach(l => {
colors.push(hslToRgb(hsl(h, 1, l)))
})
})
return {
colors
}
},
methods: {
toCssColor(color) {
const r = Math.round(color.red)
const g = Math.round(color.green)
const b = Math.round(color.blue)
return `rgb(${r}, ${g}, ${b})`
},
textColor(background) {
// Procedure 1.
const toRgbItem = item => {
const i = item / 255
return i <= 0.03928 ? i / 12.92 : Math.pow((i + 0.055) / 1.055, 2.4)
}
const R = toRgbItem(background.red)
const G = toRgbItem(background.green)
const B = toRgbItem(background.blue)
const Lbg = 0.2126 * R + 0.7152 * G + 0.0722 * B
// Procedure 2.
// White or black can be text color
// Relative luminance of white is 1, black is 0
const Lw = 1
const Lb = 0
// Procedure 3.
// White is always lighter than other colors
// while black is always darker.
const Cw = (Lw + 0.05) / (Lbg + 0.05)
const Cb = (Lbg + 0.05) / (Lb + 0.05)
// Use the color which the contrast is higher with background
return Cw < Cb ? 'black' : 'white'
}
}
})
function hslToRgb(hsl) {
const c = (1 - Math.abs(2 * hsl.lightness - 1) * hsl.sarturation)
const h = hsl.hue / 60
const x = c * (1 - Math.abs(h % 2 - 1))
let rgb
if (0 <= h && h <= 1) {
rgb = [c, x, 0]
} else if (1 < h && h <= 2) {
rgb = [x, c, 0]
} else if (2 < h && h <= 3) {
rgb = [0, c, x]
} else if (3 < h && h <= 4) {
rgb = [0, x, c]
} else if (4 < h && h <= 5) {
rgb = [x, 0, c]
} else if (5 < h && h <= 6) {
rgb = [c, 0, x]
} else {
rgb = [0, 0, 0]
}
m = hsl.lightness - c / 2
return {
...