Article Documentation

An Article represents an event displayed on the timeline. Use it to define event content and dates, configure layout and stacking, style card states, and update articles at runtime.

Article Schema

An article object powers a single timeline entry: metadata, span on the timeline, and optional style overrides that plug into the article defaults defined in your timeline options.

At a glance: Required fields — id, title, from.

Schema
// Article Schema (clickable)
// Keys are clickable; annotations are NOT defaults.
{
  id: /* required: number|string */,
  title: /* required: string */,
  subtitle: /* optional: string */,
  lane: /* optional: number|string */,

  from: {
    year: /* required: number */,
    month: /* optional: 1–12 */,
    day: /* optional: 1–31 */,
    hour: /* optional: 0–23; default: 0 */, // new
    minute: /* optional: 0–59; default: 0 */, // new
    second: /* optional: 0–59; default: 0 */, // new
    millisecond: /* optional: 0–999; default: 0 */, // new
    precision: /* optional: inferred from supplied time fields; otherwise 'day' */,
  },

  to: { /* optional */
    year: /* required: number */,
    month: /* optional: 1–12 */,
    day: /* optional: 1–31 */,
    hour: /* optional: 0–23; default: 0 */, // new
    minute: /* optional: 0–59; default: 0 */, // new
    second: /* optional: 0–59; default: 0 */, // new
    millisecond: /* optional: 0–999; default: 0 */, // new
    precision: /* optional: same inference and precision strings as from */
  },
  isToPresent: /* optional: boolean; default: false */,

  imageUrl: /* optional: string (URL) */,
  rank: /* optional: number */,
  starred: /* optional: boolean; default: false */,
  hiddenByFilter: /* optional: boolean | function(Article): boolean; default: false */,
  hidePeriodLine: /* optional: boolean | function(Article): boolean; default: false */,
  offsetLeft: /* optional: number (px); default: 0 */,
  offsetTop: /* optional: number (px); default: 0 */,
  
  cardLayout: /* optional: 'portrait' | 'landscape' | string */,

  // Per-article style overrides (sparse)
  style: /* optional: ArticleStyle */,
  hoverStyle: /* optional: ArticleStyle */,
  activeStyle: /* optional: ArticleStyle */,
}

Per-article style, hoverStyle, and activeStyle are the most specific layer in the article style cascade. See: Article Style.

Precision defines the visible range. Omitted precision is inferred from the finest supplied time component: millisecond, second, minute, then hour. Zero counts as supplied. With no time components it defaults to 'day', including year-only and year/month objects. Explicit precision is authoritative, so fields finer than the selected precision are ignored: hour precision ignores minute through millisecond, for example. For a from-only article the inclusive range is exact for 'millisecond', ends in .999 for 'second', ends in :59.999 for 'minute', and ends in :59:59.999 for 'hour'. These are timezone-free calendar fields, not JavaScript Date timestamps. See Dates and Dmy for the shared date model and its relationship to precision.

Article Options

Configure how articles (event cards) look and behave: stacking, period lines, animations, and default styles for normal, hover, and active states.

These options live under options.article.*. Defaults are shown below.

For how defaultStyle, layoutStyles, lane styles, and per-article styles combine, read the Article Style cascade. For registering and selecting your own layout, read the Custom Card Layouts guide.

πŸ’‘

String selectors new

HistropediaJS 1.5.0 uses descriptive strings for selector options. Prefer values such as 'all', 'medium', 'screen', and 'day' in new code.

The exported DENSITY_*, RANGE_*, and PRECISION_* constants now resolve to these strings. Legacy numeric selector values still work, but are deprecated. Function exports such as ARTICLE_FROM_SORTER are still imported from ESM builds or read from the Histropedia global in UMD builds.

JavaScript
// Article options (defaults)
{
  density: 'all', // new descriptive string default
  rendering: { // new
    pixelSnap: 'device'
  },
  draggable: true,
  distanceToBaseline: { // changed
    value: 350,
    responsive: {
      active: true,
      lanesOnly: true,
      byCardLayout: {
        portrait: { ratio: 0.6, min: 310, max: 410 },
        landscape: { ratio: 0.6, min: 100, max: 160 }
      }
    }
  },
  // distanceToMainLine: 350, // deprecated Use distanceToBaseline.value
  collectOngoing: false,
  autoStacking: {
    active: true,
    rowSpacing: 50,
    range: 'all', // new descriptive string default
    fitToHeight: true,
    topGap: 10
  },
  periodLine: {
    position: 'lane', // new
    baselineGap: 0, // new
    spacing: 4,
    thickness: 10,
    stacking: {
      sorter: ARTICLE_FROM_SORTER,
      reverseOrder: false
    }
  },
  animation: {
    fade: {
      active: true,
      duration: 1500,
      easing: 'swing' // new values
    },
    move: {
      active: true,
      duration: 1500,
      easing: 'swing' // new values
    }
  },
  star: { // new
    visible: true
  },
  defaultData: { // new
    from: {
      precision: 'day'
    },
    to: {
      precision: 'day'
    },
    rank: 0,
    starred: false,
    hidePeriodLine: false,
    hiddenByFilter: false
  },
  defaultCardLayout: 'portrait', // new
  cardLayoutBreakpoints: [ // new
    { maxHeight: 320, layout: 'landscape' }
  ],
  defaultStyle:       {/* See: Article Default Style β€” Options */ },
  defaultHoverStyle:  {/* See: Article Default Hover Style β€” Options */ },
  defaultActiveStyle: {/* See: Article Default Active Style β€” Options */ },
  layoutStyles:       {/* See: Article Layout Styles β€” Options */ } // new
};

Image Options new

Configure built-in image loading, caching, and sanitization. This only affects images loaded automatically from the imageUrl property in each article's data. Images are queued for loading when required to render an article. Images are evicted from the cache when the configured image.maxCacheBytes limit has been exceeded, or an image's dimensions have changed.

These options live under options.image.*. The values shown below are the defaults.

JavaScript
// Image options (defaults)
{
  maxConcurrent: 6,
  maxCacheBytes: 64 * 1024 * 1024,
  requireCORS: false,
  decodeMode: 'auto',
  sanitizer: {
    allowedSchemes: ['http', 'https', 'data', 'blob'],
    // allowedOrigins: ['*.example.com'],
  },
  // customSanitizer: (url, options) => url,
};

Article Style

Article styles control the appearance of article cards on the timeline. You can define the default, hover, and active styles for all articles in Article Options, override them for a lane, or override them for individual articles in Article Data.

Styles can also be changed at runtime:

  • Timeline defaults: timeline.setOption()
  • Lane defaults: lane.setOption()
  • Individual articles: article.setStyle(), article.setHoverStyle(), article.setActiveStyle()

Article cards are rendered using a card layout, such as the built-in portrait and landscape layouts. Each card layout can provide its own default styles.

Styles can be defined at the timeline, lane, card layout, and individual article levels, with more specific styles overriding broader defaults.

Default Style

The object below lists the complete set of available properties for styling article cards. The values are Histropedia's base defaults, except height and borderRadius, which show the selected landscape layout defaults. Click any property to see its description.

These properties can be used anywhere an article style object is used, including defaultStyle, defaultHoverStyle, defaultActiveStyle, layout-specific styles, and per-article styles.

defaultStyle in the article options object.

JavaScript
// Default style
{
  color: '#e5e5e5',
  width: 150,
  height: 70, // landscape only; layout default
  backgroundColor: '#fff',
  topRadius: 3, // portrait only
  borderRadius: 4, // landscape only; layout default
  maxImageHeight: 400, // deprecated Use image.maxHeight instead
  image: { // new
    shape: 'natural',
    margin: 0,
    maxHeight: 200, // portrait only
    borderRadius: 0
  },
  header: {
    height: 50,
    text: {
      font: "normal 14px 'Segoe UI'",
      color: "#333",
      align: "left",
      baseline: "middle",
      margin: 10,
      lineHeight: 18,
      numberOfLines: 2,
      offsetY: 0 // new
    }
  },
  subheader: {
    height: 30,
    color: '#555',
    text: {
      font: "normal 11px 'Segoe UI'",
      color: "#eee",
      align: "left",
      baseline: "middle",
      margin: 10,
      lineHeight: 6,
      offsetY: 0 // new
    }
  },
  shadow: {
    x: 0,
    y: 0,
    amount: 0,
    color: '#000'
  },
  border: {
    color: '#ddd',
    width: 1
  },
  connectorLine: {
    visible: true,
    offsetX: 18,
    offsetY: -20,
    thickness: 1,
    arrow: { width: 16, height: 45 }
  },
  star: {
    width: 16,
    margin: 3
  }
}

Hover Style

Define hover styles as overrides to the normal style. All of the same properties as the main style are supported. See all fields with descriptions in the default style section above.

defaultHoverStyle in the article options object.

JavaScript
// Default hoverStyle
{
  color: "#a6c6e2"
}

Active Style

Define active styles as overrides to the normal style. All of the same properties as the main style are supported. See all fields with descriptions in the default style section above.

defaultActiveStyle in the article options object.

JavaScript
// Default activeStyle
{
  color: "#337ab7",
  header: { 
    text: { color: "#fff" }
  },
  subheader: { color: '#333' },
  shadow: { x: 3, y: 3, amount: 5, color: '#333' },
  border: { width: 2, color: "#2e6da4" },
  connectorLine: { thickness: 2 }
}

Layout Styles

A timeline or lane can use layoutStyles to define overrides that apply only when a particular card layout is selected. These layout-specific styles are part of the general style cascade, not a separate or globally higher-priority styling system.

At either scope, defaultStyle, defaultHoverStyle, and defaultActiveStyle are applied first, followed by the matching layout's style, hoverStyle, and activeStyle. Configure timeline-level layout styles with the layoutStyles key in the article options object; each layout name acts as a key and supports the same properties as the corresponding general article style.

The built-in portrait layout adds no layout defaults. The landscape layout supplies these defaults before any explicitly configured timeline, lane, or article styles:

JavaScript
// layoutStyles
{
  // "portrait" has no additional layout style by default
  landscape: {
    style: {
      width: 220,
      height: 70,
      borderRadius: 4,
      image: {
        shape: "square",
        margin: 4,
        borderRadius: 4
      },
      header: {
        text: {
          color: "#333",
          baseline: "alphabetic"
        }
      },
      subheader: {
        text: {
          color: "#777",
          baseline: "alphabetic"
        }
      }
    },
    hoverStyle: {
      border: {
        color: "#a6c6e2"
      }
    },
    activeStyle: {
      header: {
        text: {
          color: "#000"
        }
      },
      subheader: {
        text: {
          color: "#333"
        }
      }
    }
  }
}

Style Cascade

Every article uses the same style cascade, whether it uses a built-in or custom card layout:

Histropedia defaults β†’ card layout defaults β†’ timeline β†’ lane β†’ article

Styles are deep-merged at each stage, so later layers only need to specify the properties they want to override.

For the normal article style, the complete precedence order is:

  1. Histropedia's base article style;
  2. the selected card layout's registered defaultStyle;
  3. timeline article.defaultStyle;
  4. timeline article.layoutStyles[name].style;
  5. lane article.defaultStyle, when applicable;
  6. lane article.layoutStyles[name].style, when applicable;
  7. the individual article's style.

Within the timeline and lane scopes, the general style is applied first, followed by the matching layout-specific style. Each subsequent scope can still override eitherβ€”for example, a lane's general style can override a timeline layout-specific style, and an individual article always has the highest priority.

Hover and active styles follow the same cascade using their corresponding defaultHoverStyle/hoverStyle and defaultActiveStyle/activeStyle properties. These are then merged over the resolved normal style. If an article is both hovered and active, the active style takes precedence over the hover style.

Card Layouts

A card layout determines how an article card's content is arranged and how the card is measured and drawn. Article styles control its appearance; the selected card layout controls its structure.

Histropedia includes two card layouts:

  • portrait β€” a vertical card with the title and subtitle above the image. Its height follows the content.
  • landscape β€” a compact, fixed-height horizontal card with the image beside the title and subtitle.

Choose the timeline default with article.defaultCardLayout, use article.cardLayoutBreakpoints to select a layout from the available height, or override the layout for a lane or individual article.

To create layouts beyond the built-in cards, see the Custom Card Layouts guide for layout registration, drawing, sizing, and styling.

Article Methods

Control any individual article on your timeline with these focused helpers:

Tip: Retrieve articles with timeline.getArticleById, timeline.getActiveArticle, or by reading the timeline.articles array before calling these methods.

.setOption(option, value?)

Configuration

Set article data fields or read them by providing a dot-notation path.

Parameters

option string | object

Either a full article options object or a dot-notation path into the article options.

value any

Value to assign when using a string path. Omit to read the current value.

Returns

any – Current option value when reading via a string path without a value argument; otherwise void.

For broad inspection prefer the article.data object (e.g. article.data.style).

Use article.setOption("lane", laneId) to move an article to another lane. If the lane id does not already exist, HistropediaJS creates an implicit lane automatically.

// get an article to work with from your timeline
const article = myTimeline.getActiveArticle();

// set a group of options
article.setOption({
    title: 'New title',
    subtitle: '2005 - 2007',
    from: { year: 2005 },
    to: { month: 3, day: 16 }
});

// set a single field using a path string
article.setOption('from.year', 2005);

// move the article to another lane
article.setOption('lane', 'projects');

// read the current rank without changing it
const rank = article.setOption('rank');

.setStyle(option, value?)

Styling

Override the per-article style or query an override value.

Parameters

option string | object

Style overrides object or dot-notation path into the article style options.

value any

Value to apply when using a string path. Omit to read the current override.

Returns

any – Current article-specific style value when reading via a string path without a value argument; otherwise void.

This reads and writes only the article's individual overrides. Use article.style to inspect the final computed style after defaults are applied.

const article = myTimeline.getArticleById(1);

// update a single style property
article.setStyle('border.width', 3);

// update several properties at once
article.setStyle({
    color: '#9b1000',
    header: { height: 60 },
    shadow: { x: 5, y: 10, color: 'blue' }
});

// read a specific override
const borderColor = article.setStyle('border.color');

// inspect the computed style including defaults
const computedStyle = article.style;

.setHoverStyle(option, value?)

Styling

Customize hover state styling introduced in HistropediaJS 1.2.0 or read its overrides.

Parameters

option string | object

Hover style overrides object or dot-notation path into the hover style options.

value any

Value to apply when using a string path. Omit to read the current override.

Returns

any – Current hover-style value when reading via a string path without a value argument; otherwise void.

Use article.hoverStyle to inspect the computed hover appearance including defaults.

const article = myTimeline.getActiveArticle();

// change a single hover property
article.setHoverStyle('star.width', 25);

// apply multiple hover overrides
article.setHoverStyle({
    color: '#9b1000',
    subheader: { height: 60 },
    shadow: { x: 5, y: 10, color: 'green' }
});

// read a hover override
const hoverBorderColor = article.setHoverStyle('border.color');

// inspect the computed hover style
const computedHoverStyle = article.hoverStyle;

.setActiveStyle(option, value?)

Styling

Adjust the styling used while the article is active (selected) or read its overrides.

Parameters

option string | object

Active style overrides object or dot-notation path into the active style options.

value any

Value to apply when using a string path. Omit to read the current override.

Returns

any – Current active-style value when reading via a string path without a value argument; otherwise void.

Access article.activeStyle to inspect the fully computed style when the article is selected.

const article = myTimeline.getActiveArticle();

// tweak a single active-state property
article.setActiveStyle('border.width', 3);

// provide several active-state overrides
article.setActiveStyle({
    color: '#9b1000',
    header: { height: 60 },
    shadow: { x: 5, y: 10, color: 'blue' }
});

// read an active-state override
const activeBorderColor = article.setActiveStyle('border.color');

// inspect the computed active style
const computedActiveStyle = article.activeStyle;

.getCurrentStyle() new

Styling

Return the fully merged style for the article's current interaction state.

Returns

ArticleStyle – The current normal, hover, active, or active-hover style, including timeline, lane, card-layout, and per-article overrides.

Use this method in custom card-layout hooks so state changes are handled without duplicating HistropediaJS's style-selection logic. Use article.style, hoverStyle, activeStyle, or activeHoverStyle when you need a specific state.

Timeline.registerCardLayout({
  name: 'compact',
  draw(ctx) {
    const style = this.getCurrentStyle();
    ctx.fillStyle = style.backgroundColor;
    ctx.fillRect(this.position.left, this.position.top, style.width, style.height);
  }
});

.moveTo(position)

Layout

Place the article's event card at specific canvas coordinates.

Parameters

position object

Object with left and/or top numbers defining the card's new top-left coordinates. Omitted properties keep their current value.

Returns

void – Updates the stored position without drawing immediately.

Details

Use this to pin an event card anywhere on the canvas while it remains linked to its timeline date. Call timeline.redraw() (or requestRedraw) to render the new placement.

If timeline auto-stacking is enabled, the card will return to its stacked position when the user scrolls or zooms.

const article = myTimeline.getActiveArticle();

// move the card to the top-left corner
article.moveTo({ left: 0, top: 0 });
myTimeline.redraw();

// move horizontally only
article.moveTo({ left: 60 });
myTimeline.redraw();

// move vertically only
article.moveTo({ top: 100 });
myTimeline.redraw();

.moveToOffset(offset)

Layout

Shift the event card relative to its origin position.

Parameters

offset object

Object with left and/or top numbers describing the offset from the origin (directly above the start date at the default height). Omitted properties keep their current value.

Returns

void – Updates the stored offset without drawing immediately.

Details

Offset coordinates are relative to the article's origin position. left: 0 keeps the card centered above its date; top: 0 keeps it at the default height from article.distanceToBaseline.value, or the resolved responsive baseline distance when enabled.

Call timeline.redraw() (or requestRedraw) to show the new placement. With auto-stacking enabled the card may snap back after user interactions.

const article = myTimeline.getActiveArticle();

// return to the origin position
article.moveToOffset({ left: 0, top: 0 });
myTimeline.redraw();

// keep the connector vertical but raise the card
article.moveToOffset({ left: 0, top: 60 });
myTimeline.redraw();

// apply both horizontal and vertical offsets
article.moveToOffset({ left: 100, top: -250 });
myTimeline.redraw();

Need More Help?

If you can't find what you're looking for, browse the examples or contact us.