HAHS.
Back to Catalog

Click to Select

interaction

Also known as: tap to select, pick, point selection, mark selection

Enable explorationProvide detailFilter / focus CategoricalNumericalTemporalGeographic

Description

Click-to-select is a persistent selection mechanism: the user clicks (or taps) a data mark, and that mark remains visually distinguished until it is explicitly deselected. Unlike hover highlight, which is transient and disappears on mouseout, a click-based selection commits the viewer’s attention and enables downstream operations such as comparison, filtering, annotation, or data export.

In Brehmer and Munzner’s (2013) multi-level task typology, selection is a foundational “manipulate” action that modifies the visualization state without changing the data or the visual encoding. It is the gateway to most analytical workflows: you select something, then you act on it. This is why selection affordances are nearly universal across visualization tools — from simple bar chart dashboards to complex geospatial analysis platforms.

Multi-select (holding Shift or Ctrl/Cmd) is a natural extension, allowing the user to build up a set of items of interest. This set can then be compared, highlighted across linked views, or used as input to a filter. The key design principle is that selection must be visually unambiguous — the user must always be able to tell which items are selected and which are not, even in dense displays.

Click To Select — try it yourself

When to Use

  • When the user needs to persistently mark items for comparison or closer inspection.
  • When selected items should propagate across multiple linked views.
  • When the selection set will be used as input to another operation (filter, export, annotate).
  • When the chart is sparse enough that individual marks can be reliably clicked.
  • As the mobile/touch alternative to hover-based interactions.

When NOT to Use

  • When all the viewer needs is a quick glance at a value — a tooltip is lower-cost.
  • In extremely dense plots (tens of thousands of overlapping points) where clicking individual marks is impractical — use brush selection instead.
  • When selection state would confuse the viewer because no downstream action is available for selected items.
  • In guided/narrative visualizations where the author controls focus rather than the viewer.

How It Works

  1. The user clicks on a data mark. The mark enters the “selected” state, indicated by a visual change (bold stroke, brighter fill, an outline ring, or a check badge).
  2. Non-selected marks are de-emphasized (reduced opacity or desaturated color) to create figure-ground contrast.
  3. Optionally, a detail panel or tooltip locks open showing full information about the selected item(s).
  4. For multi-select, the user holds Shift (or Ctrl/Cmd) while clicking additional marks. Each newly clicked mark joins the selection set.
  5. To deselect, the user clicks a selected mark again (toggle) or clicks on the chart background to clear all selections.
  6. In linked views, selection state is shared — selecting a bar in a bar chart highlights the corresponding points in a scatterplot.

Variations

  • Toggle select: Clicking a mark toggles it in/out of the selection set. Most common pattern.
  • Single select: Only one mark can be selected at a time. A new click replaces the previous selection.
  • Lasso select: Free-form drawing to select multiple marks at once. Often combined with click-to-select for individual additions.
  • Legend select: Clicking a legend item selects/deselects an entire category or series.
  • Click-to-lock tooltip: Click pins a tooltip in place; subsequent clicks add more pinned tooltips for comparison.
  • Click-to-drill: Clicking a mark triggers a drill-down into that category rather than just selecting it.

Code Reference

// D3.js click-to-select with toggle and visual feedback
const selected = new Set();

svg.selectAll("circle")
  .on("click", function (event, d) {
    if (selected.has(d.id)) selected.delete(d.id);
    else selected.add(d.id);

    svg.selectAll("circle")
      .attr("stroke", c => selected.has(c.id) ? "#e63946" : "none")
      .attr("stroke-width", c => selected.has(c.id) ? 2.5 : 0)
      .style("opacity", c =>
        selected.size === 0 ? 0.8 : selected.has(c.id) ? 1 : 0.15
      );
  });