On giving fluid interfaces an anchor
I saw this fluid interface concept from @mrncst and, as a feature, it’s a realllllly nice idea. There’s something really satisfying about a container adapting to what it needs to show, and letting the transition between steps feel like one continuous thing.
But it also brought up a concern I’ve had with similar interfaces elsewhere. When the content changes size, the actions move with it, and if you’re taking several steps in a row you have to keep finding the next thing to press.
That’s the bit I’d want to spend more time on. I like the fluidity, and I think there’s a way to keep it whilst making the interaction more predictable.
Following the next action
In the recording, one question asks which channels to cover, with six options and Back, Skip, and Next underneath. The next question asks for a sentence describing the target audience. It needs a shorter panel, so the footer moves upwards with the bottom edge, taking Next with it. Someone working through those questions has to move their pointer to the new position before continuing.
<video
controls
playsInline
preload="metadata"
aria-label="Original question-flow recording by @mrncst"
style={{ width: "100%", maxHeight: "680px" }}
Watch the original question-flow recording.
Each layout might look perfectly reasonable on its own. The text has enough room, the button has a sensible relationship to the content, and the container fits what it contains. Once you put those layouts into a sequence, though, you’ve given someone a little extra job every time they progress: find the action again. It’s related to what I wrote about in On affordances; working out where a control went uses attention someone could have spent on the task itself.
And if they’re moving quickly, they might already be aiming at the place it was a moment ago. They could tap empty space, or another control that’s moved into that position. Neither needs to happen for the concern to be worth exploring; the changing target is enough reason to try the sequence at the pace somebody would actually use it.
The thing is, people don’t always give dialogues their full attention, even when we think the content deserves it. Think about how often you just press “Done” on an OS prompt without really reading or thinking about it. You recognise the shape of the interaction, know roughly what you want to do, and get on with it.
We can write better copy and make an important decision clearer, but we still need to account for that ordinary behaviour. A sequence of small steps is especially likely to develop a rhythm. Someone learns where to go next, and then the interface changes the answer.
Choosing where the growth happens
I think the useful design decision here is choosing which part of the interface stays put as everything else changes.
In my 10 Principles for Fluid UI, I talk about preserving spatial context and helping people follow layout changes. This is where those principles become quite practical: decide what someone needs to find again, and give the changing content a stable relationship to it.
If the footer contains the actions someone will keep using, I’d give it a stable position and let the content expand away from it. On a bottom-aligned surface, that could mean growing upwards. In another layout, it might mean keeping the actions in a separate area, with the changing content above them. Either way, the length of the next paragraph doesn’t decide where the next tap goes.
It’s also worth paying attention to what happens inside that action area. Keeping the footer in place won’t help much if the primary action swaps sides, or an extra button pushes it across the row. The thing someone is trying to find needs to retain a recognisable position across the steps where it serves the same purpose.
And animating the button smoothly to its new location doesn’t fully resolve this. In On layout choreography, I explored how animation helps people follow items as a layout rearranges. That helps explain where something went, but following it is still something you’re asking the person to do. If they’ve already started moving their thumb or pointer, a lovely transition can still put the target somewhere they weren’t expecting.
I think this helps explain the appeal of tying an expanding surface to a chat input. The input gives the interaction an existing place to return to, and the content can grow upwards from there whilst the controls stay close to that origin. There’s an obvious relationship between the thing you’re doing and the place you started it.
How we handle it in Search Assist
I initially built Search Assist with the actions pinned to the bottom of the answer container. The early tests included shorter expanded answers, and it felt okay; the controls didn’t have very far to go, so I wasn’t really feeling the problem yet.
Then I tried longer answers and tested it on mobile, and I spent far too much time chasing the actions as the answer grew. It led to a horrible UX. The length of the answer was deciding how far away the controls ended up, and something that had seemed quite reasonable with a short response became really frustrating to use.
So we keep the actions pinned to the origin now. An answer can vary in length when it expands, and that variation doesn’t mean you have to chase the actions around the changing content.
In the mobile recording, More sits below the initial summary. Once the answer expands, the Stop and Resume states occupy that same area, and the additional answer grows beneath it. The control stays near the content that was already there, even as the card gets much taller.
<video
controls
playsInline
preload="metadata"
aria-label="Search Assist on mobile"
style={{ width: "100%", maxHeight: "680px" }}
Watch Search Assist on mobile.
That’s the part I wanted to show with the Search Assist recording. The answer gets more room, and the controls retain their relationship to where the interaction began. We still get to have a dynamic surface; we’ve chosen where the movement can happen around the actions.
For me, this is a useful thing to decide early, because it affects the structure of the component. If the buttons simply follow the content in the layout, each new state inherits that movement. Once you decide that the actions should stay anchored, you can build the expansion around that constraint and spend your time making it feel good. I used a similar starting point in On unfurling interfaces, where the smaller surfaces on this site open from the edge or control that caused them. Choosing the origin gives the movement a relationship to preserve.
I’d want to try it with a short answer, a much longer one, larger text, and several consecutive interactions. A demo with carefully chosen content can make almost any transition look lovely. The lengths you didn’t choose are where you find out whether the placement still works.
I’m really interested in seeing more fluid interfaces like this. I’d just like us to spend as much time on the second and third tap as we do on the first expansion. By then, someone’s trying to get through the thing, and knowing where to press next is a pretty important part of how it feels.