Sliders, an unsolved UI problem.

November 28, 2016

Everybody loves sliders, and for good reasons. They are easy to understand, they provide useful hints regarding sensible ranges for values, they can display values both numerically and spatially at the same time, and —provided they are wide enough— allow one to change a value both slightly and drastically with the same amount of effort.

Text fields where numbers must be entered using the keyboard, up-down controls where every change requires a click, and dropdown lists where values can be selected from a finite set are far more cumbersome to use. I suspect the only reason we still see them a lot is because they each do one specific thing better than a slider. To wit, sliders have problems with:

  • Incrementing/decrementing values by the smallest possible amount.
  • Setting very specific values.
  • Selecting values from a non-equally spaced set.
  • Selecting values without lower and upper limits.

Today I decided that it was time to start work on the core slider class in Grasshopper 2.0, which is going to be a rather  ubiquitous interface element, as indeed it is in the current version, so I need to get this right.

I’m not going to wax on about implementation, or show off any solutions yet (it has only been a day, the GH2 sliders are barely functional), but here is a list of problems I expect good slider design to solve.

  1. It must be easy to set a specific value. This problem has been solved in GH1 already, just start typing whenever a slider is selected (or double click a slider if you’re on the canvas) and it is replaced by a text field into which an exact value can be typed.
    The only improvement upon this I can think of is the ability to use voice recognition or stylus OCR to set the value.
  2. It must be easy to move a slider to the next or previous allowed value. A slider has a fixed number of decimals, and it is entirely possible that the distance between 0.506 and 0.507 is less than one pixel. Possible solutions include zooming in (not always possible, depends on the UI context in which the slider appears), using arrow keys to nudge the slider left and right, or —again— voice/gestures. A more traditional approach may be to remap the mouse coordinates so that a one pixel motion translates to exactly one epsilon.
  3. It must be possible to have preset values along the slider domain that can be snapped to. These presets must support custom names, so that a slider can be dragged from left to right while displaying {…, 0.48, 0.49, half, 0.51, 0.52, …} where “half” would be a named preset.
  4. When dragging a slider across a preset value, it must always come to rest at it, so even when there are multiple presets very close together, dragging the slider grip across them must result in each one being visited. This is turning out to be a lot harder than it sounds.
  5. Sliders that use small grips without numeric display, must still display the numeric values during dragging, and possibly on mouse-hover.
  6. Slider grips must come in various shapes; small without numeric value, box containing numeric value, bar containing numeric value. Furthermore various positions of the box and bar will result in numeric values that do not take up the same amount of horizontal pixels. Specifically when minus signs or preset names are involved, or when using a font which does not have tabular digits, ie. 11.1 is a lot narrower than 88.8.
    While dragging, the width of the grip must never change so it must be big enough to contain the widest possible value.
  7. When two or more sliders are stacked vertically, the width of their grips must be identical, or it just looks plain ugly. So it must be possible to bundle sliders together into aggregates and have them be aware of each other’s dimensions.
  8. Sliders should have a uniform appearance across the UI, but it must be possible to override specific visual properties, such as fill, background, or font without having to then do all the drawing in a custom function.
  9. Value change events need to be specific about whether the change is intermediate or final. If a slider value change is going to kick off a lengthy calculation, developers listening to the slider may want to ignore intermediate events that would occur during slider drags.
  10. The user must be able to drag a slider without it broadcasting events all over the place, for example by holding down the alt-key while dragging. Such a ‘silent’ drag must be visually distinct from a ‘loud’ drag.
  11. It must be easy for the developer to provide a bunch of meaningful defaults for a slider, and to offer undo/redo support.

The UI kits I’ve worked with in the past written by others meet 3, maybe 4 of these demands. I have yet to see software which treats sliders with the respect and gravity they demand, how is it that something as fundamental as this is still not working as it should in 20 fucking 16?

8 Responses to “Sliders, an unsolved UI problem.”

  1. briandavidgillespie Says:

    It’s interesting that you consider it a requirement that developer be smart about responding to sliders (9) and that users be able to use a slider even when that doesn’t happen (10). I guess (9) isn’t really reliable since a complex definition can result in long calculations without any one developer being able to know that their component is the culprit.

    • David Rutten Says:

      I’m not even talking about the specific use of sliders in Grasshopper, I’m just talking sliders in general. True, sometimes you don’t/can’t know the repercussions of a method invoke, but at other times you can. And if you don’t want to respond to slider events that are generated during drag operations, you either need a way to figure out whether the slider is currently in drag mode or the event needs to carry this information.

  2. Ben Doherty Says:

    Addressing point 2: I was sitting on the sofa at Christmas, eating snacks and drinking quite a lot while watching a movie.

    Being a clumsy oaf I nudged the progress slider a few times, and the struggle to get it back to the exact point that we’d been at precipitated this exact conversation.

    We came up with a few okish solutions, bit the one we really liked was a constrained rubber band.

    To make things a bit tangible, let’s imagine a slider between 0 and 10.

    If you click on the slider at 4 and drag up, a window, say between 3 and 5 becomes pulled out and magnified. I think of it as a rubber band, but more geometrically it’s a cone. The domain of the window is then stretched across the top of the cone.

    That would mean that if the pixel distance between 3 and 5 on the slider is 20px it might be 400px at the widest point of the cone.

    If you exited the cone through the side, it would slide the point of the cone along.

    This would need a bit of ui research to see if it actually worked, bit it feels quite intuitive in my imagination. Closer to the slider, more effect, further- less.

    Also, Rob Woodbury is doing some work on sliders at the moment. Quite what I’m not really sure.

    • David Rutten Says:

      Ben, is what you’re describing roughly equivalent to the YouTube timeline scrubber? The further away from the timeline the mouse cursor moves the more ‘zoomed in’ the scrolling region becomes. Though note it only works on long videos.

      • Ben Doherty Says:

        That’s pretty much it! They’ve limited it to a certain distance. I’d like to go out all the way until I can slowly step through frames!
        There doesn’t seem to be much in the way of visual support for the idea that you’ve zoomed. Perhaps their user testing showed that people just got it anyway.

  3. nickjcurtis Says:

    I often intuitively want the ability to plug integer/double values into the min/max values of a slider. I know this can be done using the domain node but somehow wish it was an integral option of the slider itself. Just discovered your blog, great work.

  4. Daniel Says:

    Hey David

    In reference to no.2, have you seen the way that changing values is addressed in houdini? They use what they call a value ladder, which lets you change a slider value by any increment, depending on where the mouse sits on the ladder. Personally I’m quite a fan of this approach.

    I do really like the idea of no.10, being able to silently change the value of the slider without the intermediary changes.

  5. for 9/10 – would that make sense to be a seperate component? “if mouse button is depressed and incoming values are changing, keep braodcasting old value until mouse button released or values are stable for 1 second”

    for 2 – I would use the old caliper method – big toggle for big movements, then little wheel to step through fine detail: https://imgur.com/xEcTKXW

    for 3/4 preset values – One option is the rate of change of the value slows down around presets – a sort of gravity well effect to give people more time to find the preset.
    Another option might be skethup Ui inspired – if you hover the slider around the preset for a few seconds, it auto snaps. If you then move the mouse again, it’ll try autosnapping to next nearby preset.

    (but I say all this as someone who uses panels for all infrequently changing inputs, because I started as a coder and I get fed up with accidentally clicking on a slider when I’m trying to move or tidy up components.)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: