Color Legend Element

A Custom Element suitable for use as a legend in data visualizations.

Built with Lit/Lit-Element and D3JS. Inspired by the Color Legend on Observable by Mike Bostock 🙏.

Copyright 2021, Chris Henrick, under the MIT License.

View on Github.

This website was built using Eleventy. It's hosted on Github Pages.

# Installation

# Dependencies

The <color-legend> assumes D3JS is available as a dependency. At the very least this should include the following modules from the D3JS library: d3-scale, d3-array, d3-format, d3-interpolate, and d3-scale-chromatic (if using one of d3's color scheme interpolators).

# NPM

Install via npm:

npm install color-legend-element

You may then import the <color-legend> in the desired ES Module:

import "color-legend-element";

# Script

To use without a frontend build tool, add the <color-legend> via a <script> tag in your HTML document.

<script
type="module"
src="color-legend-element/build/color-legend-element.js"
>
</script>

If you prefer to not use the ESM build, you may instead use the UMD build:

<script src="color-legend-element/build/color-legend-element.umd.js"></script>

# Windows OS Install

Note that Windows OS users may experience a problem with module bundlers where the D3JS dependencies are not found by the CLE. To work around this, it is recommended to be sure to use the ESM build:

import "color-legend-element/build/color-legend-element.js";

# Usage

The following examples demonstrate how to configure the <color-legend> for representing various types of data such as continuous, categorical, or discrete.

Note: most <color-legend> configuration options may be set as either HTML attributes or properties via JavaScript. Unless otherwise noted this is the case, and the word "property" is used interchangeably with "attribute" for brevity.

# Continuous

With no additional configuration, the <color-legend> will render a continuous legend using the default values for its properties. The color gradient is created using the d3.interpolateHcl color interpolator and color values from the range property.

<color-legend></color-legend>

To alter the color gradient, pass an array of strings equivalent to valid HTML colors for the range property. To alter the values in the axis ticks, set values for the domain, tickFormat, and/or tickValues properties.

<color-legend
range='["#ffffb2","#fecc5c","#fd8d3c","#f03b20","#bd0026"]'
domain="[100, 500]"
tickFormat=".0f"
tickValues="[100, 300, 500]"
>

</color-legend>

# Continuous with an interpolator

The continuous legend may also be altered by providing an interpolator function, such as one from d3-scale-chromatic, by setting the interpolator property in JavaScript. Note that there is no equivalent HTML attribute for the interpolator property as it must be a function and cannot be parsed as JSON.

<color-legend
class="continuous-with-interpolator"
titletext="Temperature (°C)"
scaletype="continuous"
tickFormat=".0f"
domain="[0, 100]"
>

</color-legend>
document.querySelector(
"color-legend.continuous-with-interpolator"
).interpolator = d3.interpolateTurbo;

# Discrete

A discrete legend may be rendered by setting the scaleType property to "discrete" and passing two values for the domain and two or more colors for the range. The domain will be divided equally by the number of values in the range.

<color-legend
titleText="Unemployment Rate (%)"
tickFormat=".1f"
scaleType="discrete"
domain="[0.1, 1]"
range='["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"]'
>

</color-legend>

# Threshold

Threshold legends may be rendered by setting the scaleType property to "threshold", and by setting the domain to an array of two or more sequential numbers. In order to render correctly, the length of the range colors array should be one less than the length of the domain array.

<color-legend
titleText="Number of Incidents"
scaleType="threshold"
tickFormat=".0f"
domain="[0, 11, 22, 33, 50, 100]"
range='["#fee5d9", "#fcae91", "#fb6a4a", "#de2d26", "#a50f15"]'
>

</color-legend>

# Categorical

Categorical legends may be rendered by setting the scaleType property to "categorical". This assumes an equal number of values in both the domain and range properties. The markType property is used to symbolize each category and may be set to one of "circle", "rect", or "line". The default markType value is "circle".

<color-legend
titleText="Business Sectors"
scaleType="categorical"
domain='["Agriculture","Business services","Construction","Education and Health","Finance","Government"]'
range='["#4e79a7","#f28e2c","#e15759","#76b7b2","#59a14f","#edc949"]'
>

</color-legend>

# Categorical with markType set to rect

<color-legend
titleText="Business Sectors"
scaleType="categorical"
domain='["Agriculture","Business services","Construction","Education and Health","Finance","Government"]'
range='["#4e79a7","#f28e2c","#e15759","#76b7b2","#59a14f","#edc949"]'
markType="rect"
>

</color-legend>

# Categorical with markType set to line

<color-legend
width="350"
titleText="Business Sectors"
scaleType="categorical"
domain='["Agriculture","Business services","Construction","Education and Health","Finance","Government"]'
range='["#4e79a7","#f28e2c","#e15759","#76b7b2","#59a14f","#edc949"]'
markType="line"
>

</color-legend>

# Hidden

The <color-legend> may be hidden applying the boolean hidden attribute:

<color-legend hidden></color-legend>

# Styling using CSS

The <color-legend>'s styles are encapsulated using the Shadow DOM and thus will not bleed out to pollute the style of neigboring DOM elements. Its default styles may be customized by overriding one or more of its CSS variables (custom properties). All CSS variable names are namespaced with cle. For example, --cle-font-family will set the font-family property for categorical legend items and axis ticks.

<color-legend class="styled"></color-legend>
color-legend.styled {
--cle-font-family: serif;
--cle-font-family-title: Impact;
--cle-letter-spacing-title: 0.5px;
--cle-color: white;
--cle-background: #222;
--cle-border-radius: 6px;
--cle-padding: 0.25rem 0.25rem 0.75rem;
}

Or for example, to change the number of columns and/or the swatch size in a categorical legend:

<color-legend
class="columns"
width="400"
height=""
titleText="Business Sectors"
scaletype="categorical"
marktype="line"
domain='["Agriculture", "Business services", "Construction", "Education and Health", "Finance", "Government"]'
range='["#4e79a7", "#f28e2c", "#e15759", "#76b7b2", "#59a14f", "#edc949"]'
/>
color-legend.columns {
--cle-columns: 3;
--cle-swatch-size: 14px;
}

You may choose to hide the <color-legend> until it loads using the CSS :defined pseudo class:

color-legend-element:not(:defined) {
display: none;
}

color-legend-element:defined {
display: inline-block;
}

# Adding Child Content via Slots

Child content may be placed within the <color-legend> via its two slots, named "subtitle" and "footer" which render above and below the primary legend content respectively.

Some subtitle text here perhaps?

= No data

<color-legend>
<small slot="subtitle">
Some subtitle text here perhaps?
</small>
<p slot="footer" class="no-data">
= No data
</p>
</color-legend>

Note that any slotted elements are considered part of the "light DOM" and can be styled by CSS external from the <color-legend>.

# Bugs / Suggestions

To report a bug or make a suggestion, please open an issue in the Github repository or send me a Tweet. And feel free to let me know if it's helped you in a project 🙂 Thanks!