CSS Animations using Transitions with Conditional CSS, Stacked Rectangles

This is a somewhat elaborate example of how to use conditional CSS and transitions to create a fluid, responsive stack of rectangles that are polite enough to stack up when the screen is narrow. The idea is I’m working on is to have a menuing system that stacks when the screen shrinks.

There are three versions of this code, with menustack-onemotion.html being the simplest. I should have saved a much simpler version that didn’t have so much code, but I didn’t. You can fake it by editing all the “top”, “box-shadow”, and “transition” settings out.

To see it in action, load up one of the three pages, and then resize the window so it’s narrow. Firefox works the best. Chromium might not let you shrink the window enough, but you can zoom in and see the full effect. Konqueror doesn’t seem to support transitions, at least not with this code.

http://riceball.com/d/files/menustack-onemotion.html

http://riceball.com/d/files/menustack-progressive.html

http://riceball.com/d/files/menustack-sketch.html

<!DOCTYPE html>
<html>
    <head>
        <style type="text/css">
            body { 
                background-color: #e3e3e3;
            }
            .menu {
                border: 1px solid #ddd;
                width: 120pt;
                height: 400pt;
                background-color: white;
                position: absolute;
                margin-left: -1px;
                box-shadow: 0px 0px 0px #fff;
                transition: left 0.5s, top 0.5s, box-shadow 0.25s;
            }
            .L1 { 
                left: 5pt; 
                top: 5pt;
            }
            .L2 { 
                left: 125pt; 
                top: 5pt;
            }
            .L3 { 
                left: 245pt; 
                top: 5pt;
            }
            @media screen and (max-width: 380pt) {
                .menu {
                    border: 1px solid #eee;
                    box-shadow: 0px 1px 1px #ddd;
                }
                .L1 { 
                    left: 5pt; 
                    top: 9pt;
                }
                .L2 { 
                    left: 10pt; 
                    top: 6pt;
                    box-shadow: 0px 1px 2px #ddd;
                }
                .L3 { 
                    left: 130pt; 
                    top: 3pt;
                    box-shadow: 0px 1px 4px #ddd;
                }
            }
            @media screen and (max-width: 260pt) {
                .L1 { 
                    left: 5pt; 
                    top: 9pt;
                }
                .L2 { 
                    left: 10pt; 
                    top: 6pt;
                    box-shadow: 0px 1px 2px #ddd;
                }
                .L3 { 
                    left: 15pt; 
                    top: 3pt;
                    box-shadow: 0px 1px 4px #ddd;
                }
            }
        </style>
    </head>
    <body>
        <div class="menu L1"></div>
        <div class="menu L2"></div>
        <div class="menu last L3"></div>
    </body>
</html>

So, if you’re a programmer, this is going to look a little odd because there’s no logic that causes the magic to happen. You have to think more like an animator. Animators think in terms of “key frames”, and you can think of this animation as having three key frames.

Conditional CSS is used to define the positions of the rectangles.

@media screen and (max-width: 380pt) {...

That means if the width is less than 380pt, the following styles are applied. These styles override the styles that appeared above this rule.

Likewise, @media screen and (max-width: 260pt) {... causes additional CSS to be applied, overriding not both the above block and the original CSS.

It’s a little weird to work with CSS because the right way to code it uses this overriding behavior.

We could have written it (less elegantly) like this:


@media screen and (min-width: 380pt) {
  ... frame 1 ...
}
@media screen and (min-width: 281pt) and (max-width: 379pt) {
 ... frame 2 ...
}
@media screen and (min-width: 0pt) and (max-width: 280pt) {
 ... frame 3 ...
}

But that would be wrong.

It not only leads to more code – you’re more likely to mess up the code because you have to keep track of more things. It’s better to think like this:

– you start with one working layout that shows everything on a big screen.
– then you create a conditional layout that alters the original.
– as the screen space shrinks, you need to alter the layout more.

The logic of your code should be developed separate from your drawings or HTML sketches. Your HTML sketches can be messy, but the conditional CSS code should be crafted. It’s no different than writing computer code: the first version is the one you throw away.

More Tricks

The use of L1, L2, and L3 is somewhat incorrect – I could have used IDs. I didn’t because I was thinking this could be used for menus, and menus might have unique IDs, but two menus could share the same “depth” in the menu hierarchy.

It still feels like a hack to me. Maybe that’s more my problem than anything else.

The magical animation features are enabled with the “transition” line. The transition property causes the listed CSS styles to be transitioned rather than immediately applied.

When there’s a transition property, the browser takes the new value, and then calculates tween values and applies them over the specified intervals. In this example, changes to the styles are triggered by the conditional CSS. (You could also cause changes to styles by using Javascript code to add classes or styles to elements.)

The scope of a transition property is the element it’s on.

So, there you go. Not the greatest tutorial, but it’s a nice effect, and the code is pretty simple for what it does.