How to use CSS3 transition to enable diagonal movement of inline-block elements?

Problem

I have a particular problem that I want to solve with CSS3 transitioning. So I have a container with inline-block elements, and once I select one of the elements, everything else will be hidden and that selected element should move smoothly to the top-left corner of the container.

For example, I have my container as below containing 8 elements wrapped in 2 lines:

= = = = =
A B C D
E F G H
= = = = =

And now I select G, everything else is hidden and G is moved to the top left corner:

= = = = =
G
= = = = =

My current approach is to set the width and height of all of G's siblings to 0, CSS3 transition works perfectly and I can see G move to the left edge smoothly. However, since G is in a 2nd line, it jumps up a line when everything on the first line shrinks. This movement is sudden and undesirable. I would like the effect to be like G moves smoothly diagonally to the top left corner.

I also looked at translate(x,y) but it is no good either, since I don't want to calculate how much pixels I have to move the box to the top left. It would be ideal if I can just make use of (position: absolute; left: 0; top: 0) somehow to automatically be at the top left, but as soon as I set the position to absolute the element would instantly jump.

Can any CSS3 master suggest a nice approach?

Problem courtesy of: Xavier_Ex

Solution

Not perfect, but here is my solution:

this is the html:

<div class="base">
<div class="container"><div class="child"></div><div class="child"></div><div class="child"></div><div class="child"></div><div class="child"></div><div class="child"></div><div class="child"></div><div class="child"></div><div class="child2"></div><div class="child"></div>

Since you are using inline-block, and I want your divs to colapse nicely, I need to have no spaces between them.

And the CSS is:

.container, .base {
    width: 500px;
    height: 400px;
}

.base {
    border: solid 1px black;
}
.container {
    -webkit-transition: 1s all linear;
}
.child, .child2 {
    width: 120px;
    height: 80px;
    display: inline-block;
    margin: 10px;
}
.child {
    -webkit-transition-duration: 1s;
    -webkit-transition-property: height, width, margin;
    -webkit-transition-timing-function: linear;
    background-color: lightblue;
}
.child2 {
    -webkit-transition: 1s all linear;
    background-color: lightgreen;
}
.base:hover .container {
    width: 20px;
}
.base:hover .child {
    width: 5px;
    height: 0px;
    margin: 0px;
    background-color: silver;
}
.base:hover .child2 {
    margin-right: -120px;
}

The idea is to have an extra div between your container and the children, that is resized at about the same pace that the children. This way, we keep the same layout for all the transition, in this case 3 divs per row, and we avoid all the elements going to the same row and colapsing the top of the visible div.

There is a problem in this approach when the container is smaller than the div that is not shrinking; to avoid it we set the margin-right of the visible element to a negative value that will allow it to fit well inside the container.

I have a problem in the final state, where there is a space between the rows (and the elemennt doesn't get to the topmost position). This problem doesn't show when I have the same code outside the fiddle; I don't know what is causing that.

demo

Solution courtesy of: vals

Discussion

There is currently no discussion for this recipe.

This recipe can be found in it's original form on Stack Over Flow.