One rather neat little user interface “pattern” that comes up a lot, especially in mobile apps, is a side panel which slides in to get at extra stuff. There are approximately 1.5 million people explaining how to do this, most of which do two things: use jQuery, and animate the position of the side panel. An interesting alternative is to do neither of those things.
First, pure CSS. I’m by no means the first person to suggest this, but
it’s a neat trick: the CSS :target
pseudo-selector lets you style the
thing that the URL hash fragment is referencing. So if you’ve got your
panel as id="panel"
, then #panel:target { whatever }
in your CSS
sets the styles for it when the URL is thispage.html#panel
, which
means that you can summon your side panel with pure CSS, excellent.
(Then dismissing it is clicking a link to some fragment other than
#panel
, so <a href="#">
is fine.)
The second part is a bit different, though. The way people normally have
the panel be hidden and then showing is to position it off screen.
Simple way to do this (remembering that the “default state” of our panel
is “offscreen”, and #panel:target
is “on screen”):
#panel {
position: absolute;
top: 0;
bottom: 0;
right: -200px;
width: 200px;
transition: right 0.3s ease-in-out;
}
#panel:target {
right: 0;
}
Of course, we are good people and we know that you should only animate transform properties and opacity if you want smooth animations, so the obvious response is to change that to
#panel {
position: absolute;
top: 0;
bottom: 0;
right: 0;
width: 200px;
transform: translateX(200px);
transition: transform 0.3s ease-in-out;
}
#panel:target {
transform: translateX(0);
}
However, then we have a thing: you’ll get a horizontal scrollbar now
because there’s stuff off the right-hand-side of the screen. You can of
course avoid that by setting overflow: hidden
on the container, but
that’s potentially annoying, and hiding stuff with overflow always ends
up screwing me up at some point. One alternative approach is to not move
the panel around at all, but instead to scale it down to almost nothing
(animating a scale is fast, because it’s a transform property) and then
scale it up. Like this:
#panel {
position: absolute;
top: 0;
bottom: 0;
right: 0;
width: 200px;
transform: scaleX(0.00001);
transform-origin: 100% 50%;
transition: transform 0.3s ease-in-out;
}
#panel:target {
transform: scaleX(1);
}
See the jsbin for a simple demo.
Note that people will expect to be able to swipe the panel away on a mobile screen. You need JS for that, so this is no panacea. Similarly, scaling may have an odd appearance depending on what’s in your side panel, and so this idea might not actually work for what you’re doing. Have an experiment with the approach and tell me about it.