Color Legend Element

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

Lightweight: 27kb bundle size, 9kb Gzipped!

Built with Lit 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 peer 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.

You may also view an interactive version of these docs on ObservableHQ.com.

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. For a list of all properties including their type, default value, and description see the README.

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 its value must be a function and thus 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 will be styled by any global CSS belonging to the page in which the <color-legend> is rendered in.

Bugs / Suggestions

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