Why a simple scroll bar was hard to build

Figma users had requested horizontal scrolling in the Layers panel for a long time before it shipped with UI3. Nested frames that push content out of view seem like an obvious case for a scroll bar. But what looked like a straightforward addition turned out to be a subtle design and engineering problem.

The Layers panel is a heavily used, utilitarian surface. It also isn’t a static list: layers can be hidden, locked, collapsed, or expanded, so the panel’s contents are constantly changing. Adding horizontal scrolling complicates how those states behave. Virtualization adds another constraint—only the layers currently in view are rendered for performance, which means the panel doesn’t always know the length of the text in off-screen rows.

Three prototypes that didn’t make the cut

Product Designer Giorgio Caviglia worked with Software Engineers Amy Shan and Grant Phelps to explore the design space. Caviglia prototyped directly in JavaScript, HTML, CSS, and React, reasoning that a dynamic feature like scrolling can’t be evaluated from static mockups. “You can’t anticipate all states when you’re designing statically,” he says.

Edge-aligned indicators

One early concept treated the white space symmetrically. When a layer scrolled out of view at the top-left edge of the panel, an icon would stick to that edge, and a matching icon would appear at the bottom-right edge, so users could track their position in the hierarchy.

The engineering reality was messier. Pinning icons to the panel edges was easy, but the icons needed opaque backgrounds to cover layer names while scrolling. That conflicted with the structure of layer rows. “In various situations during horizontal scrolling, the background should appear to be sliding under some layer elements while truncating others,” says Shan, “which is difficult to do when the component we’re styling doesn’t have exact knowledge of where the elements on top are placed.”

Visually, the approach also failed. Scrolling right left the layer names forming a ragged text edge at the top left. “This is a clear example of a solution introducing a new problem,” Caviglia says. The experiment did surface a useful question: what should happen to the empty space above the visible layers?

Auto-scrolling to a selected layer

Another prototype tested automatic scrolling. When a user selected a layer on the canvas that was out of view in the Layers panel, the scroll bar would move to center it. The idea was sensible in theory but disorienting in practice. One internal tester described clicking a deeply nested item as “jarring because the layer tree scrolls to it horizontally and vertically. I’ve lost all context of the parent items at that point.”

Caviglia compares the effect to a navigation app that jumps to a new location without warning—the user loses their mental model of the hierarchy. “If you’re disoriented, you start to doubt yourself,” he says. “You want the tool to support you, not work against you.”

Expanding the rename box

Horizontal scrolling also raised a question about renaming. If a user clicked a layer to edit its text box and then scrolled away, should the typed text be committed as the new name? The team decided scrolling wasn’t a strong enough signal to confirm a change.

They tried an alternative: a text box that expanded to the right as the user scrolled. The UI flickered at the far edge because JavaScript had to resize elements on the fly. “There was no way to get around the lag caused by resizing the panel horizontally,” says Phelps. Resizing caused choppiness on whichever side wasn’t fixed, and continuous typing could cause the scroll bar to jump back to keep the text visible—a behavior the auto-scroll experiment had already ruled out.

What shipped

The failed explorations clarified three decisions in the final version. The white space above the visible layers is left completely blank, matching the bottom of the panel. Renaming a layer and then scrolling simply resets the name, even if it had been edited beforehand.

For auto-scrolling, the team developed heuristics to control when and how far the panel shifts. If a selected layer’s icon and text extend beyond the left edge by 50 pixels or more, the scroll bar moves left just enough to show the additional context—without disrupting the user’s flow. Virtualization made this tricky: when a clicked layer isn’t rendered, the panel doesn’t know the row’s text length, so it can’t calculate the correct scroll offset. Shan and Phelps solved this by performing “an invisible render of the row before we move it,” Shan explains, then measuring that row to align the scroll precisely.

The iteration process was about deciding what to automate, what to leave under user control, and where simplicity mattered most. “We needed to ship something that felt like an evolution, not a regression,” says Caviglia. “Solutions that feel just right don’t start that way. They’re often born out of madness.”