Skip to content

D3.js Brush — Interactive Selection and Filtering

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about D3.js Brush. We cover key concepts, practical examples, and best practices to help you master this topic.

D3.js brush creates interactive rectangular selection regions on SVG elements, enabling users to select and filter data ranges for coordinated visualizations.

What You'll Learn

By the end of this guide, you will create brush selections on X, Y, and XY axes, handle brush events to filter data, clear and programmatically set brushes, coordinate multiple charts through brushing, and build an interactive dashboard.

Basic XY Brush

var brush = d3.brush()
    .extent([[0, 0], [width, height]])
    .on('brush', function(event) {
        var selection = event.selection;
        if (selection) {
            var [[x0, y0], [x1, y1]] = selection;
            console.log('Brushed area:', x0, y0, x1, y1);
        }
    })
    .on('end', function(event) {
        if (!event.selection) {
            console.log('Brush cleared');
        }
    });

svg.append('g').call(brush);

X-Only Brush

var brush = d3.brushX()
    .extent([[0, 0], [width, height]])
    .on('end', function(event) {
        if (event.selection) {
            var [x0, x1] = event.selection;
            var selectedData = data.filter(function(d) {
                return xScale(d.date) >= x0 && xScale(d.date) <= x1;
            });
            updateDetailChart(selectedData);
        }
    });

svg.append('g').call(brush);

Coordinated Brushing

var brush = d3.brushX()
    .extent([[0, 0], [width, height]])
    .on('brush', function(event) {
        if (event.selection) {
            var [x0, x1] = event.selection;
            var domain = [xScale.invert(x0), xScale.invert(x1)];
            detailXScale.domain(domain);
            renderDetailChart();
        }
    });

Clearing the Brush

d3.select('#clear-brush').on('click', function() {
    svg.select('.brush').call(brush.move, null);
});

Common Mistakes

1. Brush Not Visible

Brush extent must match the chart area dimensions. If extent is wrong, the brush rectangle appears off-screen.

2. Forgetting Brush Handle

Brush handles show on the edges. Without them, users cannot resize the selection. Handles are added automatically.

3. Not Handling Null Selection

When the brush is cleared (clicking outside), event.selection is null. Always check before processing.

4. Brush on Top of Data

The brush overlay captures mouse events. Render data elements after the brush group so they remain interactive.

5. Performance With Large Data

Filtering thousands of data points on every brush event can be slow. Debounce the brush handler.

Practice Questions

Q1: What is the difference between d3.brush, d3.brushX, and d3.brushY? A: d3.brush creates a 2D rectangle. brushX and brushY constrain selection to one axis.

Q2: What does event.selection contain? A: An array of coordinates: [[x0, y0], [x1, y1]] for 2D brush, [x0, x1] for 1D.

Q3: How do you filter data based on brush selection? A: Invert the pixel coordinates back to data values using the scale's invert method.

Q4: How do you programmatically set brush selection? A: Use selection.call(brush.move, [[x0, y0], [x1, y1]]).

Q5: What is the difference between brush and brush event? A: The brush is the behavior. The brush event fires during interaction with the selection.

Challenge: Build a time series chart with brush selection. Below it, a detail chart shows the brushed region at full width. The detail chart updates as the brush moves.

FAQ

Can I style the brush selection?

Yes. Use CSS on .selection class: svg .selection { fill: #4ecdc4; fill-opacity: 0.3; }

How do I make a non-interactive brush?

Call .on('brush', null) to disable interaction but keep the visual selection.

Can I have multiple brushes on one SVG?

Yes. Create separate brush groups with different classes.

How do I limit brush extent?

Set .extent() to the chart area. The brush cannot go beyond these bounds.

Does brush work on touch?

Yes. d3.brush handles touch input for mobile devices.

Try It Yourself

Build a scatter plot with XY brush that filters points and shows selected count.

<!DOCTYPE html>
<html>
<head>
    <title>Brush Selection Demo</title>
    <style>
        body { font-family: sans-serif; padding: 20px; background: #f5f5f5; }
        svg { background: white; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
        .dot { fill: #4ecdc4; stroke: #fff; stroke-width: 1; }
        .dot.selected { fill: #ff6b35; }
        .selection { fill: #4ecdc4; fill-opacity: 0.15; stroke: #4ecdc4; }
        #info { margin-top: 10px; font-size: 14px; color: #666; }
        #clear { padding: 6px 12px; cursor: pointer; background: #ff6b35; border: none; color: white; border-radius: 4px; margin-left: 10px; }
    </style>
</head>
<body>
<h2>Brush to Select Points</h2>
<svg width="600" height="400" id="chart"></svg>
<div id="info">Drag to select points <button id="clear">Clear</button></div>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
var width = 600, height = 400;
var svg = d3.select('#chart');
var data = d3.range(100).map(function() {
    return { x: Math.random() * width, y: Math.random() * height };
});

svg.selectAll('circle')
    .data(data).enter()
    .append('circle').attr('class', 'dot')
    .attr('cx', function(d) { return d.x; })
    .attr('cy', function(d) { return d.y; })
    .attr('r', 4);

var brush = d3.brush()
    .extent([[0, 0], [width, height]])
    .on('end', function(event) {
        if (!event.selection) {
            svg.selectAll('.dot').attr('class', 'dot');
            d3.select('#info').text('No selection');
            return;
        }
        var [[x0, y0], [x1, y1]] = event.selection;
        svg.selectAll('.dot')
            .attr('class', function(d) {
                return (d.x >= x0 && d.x <= x1 && d.y >= y0 && d.y <= y1)
                    ? 'dot selected' : 'dot';
            });
        var count = svg.selectAll('.selected').size();
        d3.select('#info').text('Selected: ' + count + ' points');
    });

svg.append('g').call(brush);

d3.select('#clear').on('click', function() {
    svg.select('.brush').call(brush.move, null);
});
</script>
</body>
</html>

What's Next

Implement drag and drop behavior.

Drag Drop — Drag and drop in D3.js. Color Scales — Color scales and schemes.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro