← All work

2025

Data visualization

Climate

Internal Displacement

Mapping human movement caused by climate and natural hazards

Role

Sole designer, data to interface

Timeline

6 weeks, 2025

Services

Data Visualization · Interaction Design · Accessibility

Tools

Figma, D3.js, HTML, CSS, Anime.js

Industry

Humanitarian data

Status

Live

Visit live site ↗

World map of disaster displacement with coloured circles by hazard and the five most affected countries highlighted

Overview

The Internal Displacement Monitoring Centre publishes disaster displacement figures every year as a national-level table. It is accurate, public, and almost nobody reads it.

I rebuilt the 2023 dataset as a scroll-driven piece: a rotating globe you can filter and interrogate, then a close read of the five countries that carried the heaviest burden, then a ranked chart for the next ten. The sequence is the argument. Scale has to register before ranking means anything.

Challenge

152 countries, five hazard types, one table. A reader scanning it learns that the numbers are large and learns nothing else.

The obvious fix fails in the opposite direction. Plot every country on one map and the top five are unreadable against the bottom hundred, because a bubble sized for 5.6 million and a bubble sized for 5,000 cannot share a scale that resolves both. Plot only the top five and you have discarded the finding, which is that this happens everywhere, not in a handful of places people already associate with disaster.

So the real question was not which chart. It was sequencing: what does a reader have to see first for the second thing to carry weight.

Process

I built the piece as three passes over the same data rather than one view that tries to serve every question.

The globe establishes that displacement is global. You can filter by hazard type, hover any country for its breakdown, and drag to rotate. It answers where, and deliberately refuses to answer how much, ranked.

The transition asks the question the globe raises: if it is everywhere, who carried it. A counter animates up to the top-five total while the copy narrows the frame.

The cards answer at country level, each with a per-hazard split, so a reader can see that Türkiye’s 4.9 million is almost entirely one earthquake while China’s 5.6 million is spread across storms, floods, and seismic events. Same magnitude, different story.

The second transition widens back out, and the ranked chart covers countries six through fifteen with a toggle between total volume and hazard composition.

Three technical decisions shaped the build. One fixed canvas serves all seven sections, re-projecting as you scroll, rather than mounting a globe per section. Bubble area uses a square-root scale so magnitude reads as area rather than as radius, clamped at six million so the largest country does not flatten everything under it, with countries below 200 displaced suppressed because at that scale they render as noise a reader cannot resolve. And the headline figures in the transitions are computed from the dataset at runtime, not written into the markup, so the numbers on screen cannot drift from the numbers behind them.

Decisions & Tradeoffs

Mandatory scroll-snap over free scrolling.

Every section is a full viewport that the browser locks to, so a reader lands on one idea at a time and cannot scroll past a transition mid-sentence. The cost is control. On a trackpad the page feels like it is steering you, and that is a real tax. I kept it because the reveal only works if the widening-out lands after the close read, and free scrolling let readers arrive at the ranked chart without ever seeing the globe. Below 768px I dropped to proximity snapping, where mandatory snap on a touch device reads as the page fighting the reader.

Exploration inside the map, sequence everywhere else.

The globe takes drag, momentum, hazard filtering, and hover, but only within its own section. Outside it the canvas ignores pointer input entirely. Letting a reader rotate the globe during the ranked chart would have put two interactive targets in competition, and the chart would have lost. Auto-rotation stops the moment you grab the globe and resumes after 2.5 seconds idle, so the page moves when you do not and holds still when you do.

Redundant encoding at the top of the scale.

Countries above a million displaced carry an animated pulse ring in addition to bubble size and hazard colour. Colour alone would have failed readers with a colour-vision deficiency. Size alone compresses badly past four million, where the square-root scale is doing its job but the eye stops reading the difference. Three carriers cost some visual noise on five countries and made the severity read survive both failure modes.

Result

A live, self-contained piece covering all 152 countries in the IDMC 2023 dataset across five hazard types, built on a single animation loop rather than seven, with the data source and its methodology limits stated in the footer rather than buried.

The part I would point an interviewer at is not the globe. It is the footer, which says plainly that the figures cover sudden-onset events and that chronic slow-onset displacement is underrepresented. The visualization makes a confident visual claim, and the reader is told exactly where that confidence ends.

What I’d Do Next

The piece has no reduced-motion handling, and it should. Mandatory scroll-snap, blur-and-rise reveals, an animated film-grain overlay, and a continuously rotating globe are precisely the stack that triggers vestibular symptoms. A reader who has set that preference at the operating-system level currently gets the full treatment anyway. The fix is not a redesign. One media query that disables the grain, drops snap to proximity, and swaps the blur reveals for straight opacity would cover it. It is the first thing I would ship on a second pass, and I am naming it here because an accessibility claim you cannot fail is not a claim.

The second lesson is cheaper and more embarrassing. The figures I computed from the dataset stayed correct through every revision. The figures I typed into the copy drifted, and by the end the page stated its global total three different ways. Anything a reader can cross-check should be derived, not written. I now treat a hardcoded number in a data piece as a defect waiting to happen.

Next project →

Contact

Open to product design and UX research roles

I’m looking for roles where the interface has to carry real complexity. If that’s what you’re hiring for, I’d like to hear about it.

Based in San Jose, CA

© 2026 Chaitanya Sai Botta

Contact

Open to product design and UX research roles

I’m looking for roles where the interface has to carry real complexity. If that’s what you’re hiring for, I’d like to hear about it.

Based in San Jose, CA

© 2026 Chaitanya Sai Botta

Contact

Open to product design and UX research roles

I’m looking for roles where the interface has to carry real complexity. If that’s what you’re hiring for, I’d like to hear about it.

Based in San Jose, CA

© 2026 Chaitanya Sai Botta

Create a free website with Framer, the website builder loved by startups, designers and agencies.