Features

Animations, downloads, icons, image generation, and negative values

Animations

Charts support CSS-based animations with staggered reveals. Enable globally or per-chart.

Global Enable

eleventyConfig.addPlugin(uncharted, {
  animate: true
});

Per-Chart Override

charts:
  # Disable for this chart
  static-chart:
    type: donut
    animate: false
    file: charts/data.csv

  # Enable for this chart (if global is false)
  animated-chart:
    type: stacked-bar
    animate: true
    file: charts/data.csv

Scroll-Triggered Animations

For animations that trigger when scrolled into view, add an Intersection Observer that toggles the .chart-animate class:

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('chart-animate');
    }
  });
}, { threshold: 0.2 });

document.querySelectorAll('.chart').forEach(chart => {
  observer.observe(chart);
});

Let users download the source CSV data for any chart.

Setup

Enable globally in plugin options:

eleventyConfig.addPlugin(uncharted, {
  downloadData: true,     // show download links
  dataPassthrough: true,  // copy CSV files to output
  dataPath: '/data/'      // URL path for files
});

This adds a download link below each chart that loads data from a file.

Per-Chart Override

charts:
  # Uses global setting
  revenue:
    type: stacked-bar
    file: charts/revenue.csv

  # Custom download label
  expenses:
    type: stacked-column
    file: charts/expenses.csv
    downloadData: "Download expense report"

  # Disable for this chart
  internal:
    type: donut
    file: charts/internal.csv
    downloadData: false

Without Passthrough

If dataPassthrough is false, ensure CSV files are available at the expected URLs. The plugin generates links based on dataPath + file:

/data/charts/revenue.csv

When image generation is enabled, you can also add download links for the generated PNG images:

eleventyConfig.addPlugin(uncharted, {
  image: { enabled: true },
  downloadImage: true
});

This adds a download link below each chart that has image generation enabled. Like downloadData, you can override per-chart:

charts:
  # Uses global setting
  hero:
    type: stacked-column
    file: data.csv

  # Custom download label
  infographic:
    type: donut
    file: stats.csv
    downloadImage: "Download chart image"

  # Disable for this chart
  internal:
    type: line
    file: metrics.csv
    downloadImage: false

Negative Values

Stacked column, line, and scatter charts support negative values. When present, a zero axis line appears automatically.

Stacked Columns

Positive values stack upward from zero, negative values stack downward:

quarter,Cost,Profit
Q1,20,10
Q2,25,-10
Q3,15,25
Q4,30,-10
Quarterly Performance
400-10
Q1Q2Q3Q4
CostProfit/Loss

The chart calculates the range from maximum positive stack to minimum negative stack automatically.

Line Charts

Points position above or below the zero line:

month,Change
Jan,5
Feb,-3
Mar,8
Apr,-2

Scatter Charts

Both X and Y axes can display negative values:

charts:
  scatter:
    type: scatter
    x:
      min: -100
      max: 100
    y:
      min: -50
      max: 50

Manual Scaling with Negatives

Set explicit ranges that include negative values:

charts:
  performance:
    type: stacked-column
    y:
      min: -50
      max: 100
    file: charts/performance.csv

Or using global defaults:

charts:
  performance:
    type: stacked-column
    min: -50
    max: 100
    file: charts/performance.csv

The zero line positions proportionally between min and max.

Icon Support

Line, time-series, and scatter charts can display Font Awesome icons instead of default circular dots. Icons inherit series colors automatically.

Prerequisites

Include Font Awesome in your site:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css">

Single Icon for All Series

Use a string to apply the same icon to all data points:

charts:
  stars:
    type: line
    file: data.csv
    icons: "fa-solid fa-star"

Per-Series Icons

Use an object to assign different icons to each series:

charts:
  development:
    type: line
    file: adoption.csv
    y:
      columns:
        prs: Pull Requests
        commits: Commits
    icons:
      prs: "fa-solid fa-code-merge"
      commits: "fa-solid fa-code-commit"

Scatter Charts

For scatter charts, icons are keyed by series value:

charts:
  metrics:
    type: scatter
    file: data.csv
    series:
      column: group
    icons:
      alpha: "fa-solid fa-circle"
      beta: "fa-solid fa-square"

Icons also appear in the legend, replacing the default colored dot marker.

Image Generation Beta

Generate PNG images of charts for use in RSS feeds, social sharing, or fallback content. Images are rendered using Puppeteer during the build process.

Note: This feature requires v1.0.0-beta.1 or later. The cacheDir option requires v1.0.0-beta.3.

Prerequisites

Install Puppeteer as a peer dependency:

npm install puppeteer

Plugin Configuration

Enable image generation globally:

eleventyConfig.addPlugin(uncharted, {
  image: {
    enabled: true,
    outputDir: '/images/charts/',  // URL path for images
    cacheDir: 'images/charts/',    // source directory for cached images
    width: 800,                    // default width in pixels
    height: 400,                   // default height in pixels
    scale: 2,                      // device scale (2 for retina)
    background: '#ffffff',         // background color
    skipDev: true                  // skip during --serve/--watch
  }
});

When enabled, charts automatically include data-chart-image and data-chart-alt attributes for use with the chartToImage filter.

Per-Chart Configuration

Override global settings for individual charts:

charts:
  hero-chart:
    type: stacked-column
    file: data.csv
    alt: "Quarterly revenue showing growth trend"
    image:
      enabled: true
      width: 1200
      height: 600

The alt option sets the chart's aria-label for accessibility. It's also used as image alt text when image generation is enabled. If not specified, the chart title or ID is used.

Some chart types (such as stacked bars and Sankey diagrams) may need larger width or height values to be fully visible in the generated image.

Getting Image URLs

Use the chartImageUrl shortcode to get the root-relative URL of a chart's generated image:

{% chartImageUrl "hero-chart" %}
<!-- outputs: /images/charts/hero-chart.png -->

For absolute URLs (required for Open Graph), prepend your site URL:

<meta property="og:image" content="{{ site.url }}{% chartImageUrl "hero-chart" %}">

RSS Feeds

Use the chartToImage filter to replace chart HTML with <img> tags in feed content:

{{ post.content | chartToImage }}

For absolute URLs in feeds, pass a base URL:

{{ post.content | chartToImage: "https://example.com" }}

This replaces any chart <figure> elements that have image data with simple <img> tags, which work in RSS readers that don't support complex HTML/CSS.

Caching for Vercel and Other Hosts

Puppeteer requires Chromium, which doesn't work in some build environments like Vercel. Use the cacheDir option to cache generated images in your repository.

When cacheDir is set:

  • Images are written to the cache directory (e.g., images/charts/)
  • Passthrough copies cached images to the output
  • If Puppeteer is unavailable, cached images are used silently

Generate images locally or in a CI step (like GitHub Actions) that has Puppeteer, then commit them. On Vercel (or any host without Puppeteer), the cached images are used automatically.

Accessibility

Charts are rendered as <figure> elements with proper semantic structure:

  • <figcaption> contains the title and subtitle
  • Chart data is represented in HTML, not canvas
  • Legend items are readable by screen readers

Use the alt option to add an accessible description to a chart:

charts:
  sales:
    type: stacked-column
    file: sales.csv
    alt: "Quarterly sales showing 25% growth year over year"

This sets aria-label on the chart's <figure> element. If not specified, the chart title or ID is used as a fallback.

For additional accessibility, consider:

  1. Providing a data table alternative for complex charts
  2. Ensuring sufficient color contrast in custom palettes