Html – How to use transform:translateX to move a child element horizontally 100% across the parent

csscss-transformscss-transitionshtml

All,

I'd like to be able to use translateX to animate a child element 100% of the way across it's parent (i.e., from the left edge to the right edge).

The challenge is that percentages in translateX refer to the element itself, not the parent.

So, for example, if my html looks like this:

<div id="parent">
    <div id="child">
</div>

And my CSS like this (vendor-prefixes omitted):

#parent {
    position: relative;
    width: 300px;
    height: 100px;
    background-color: black;
}
#child {
    position: absolute;
    width: 20px;
    height: 100px;
    background-color:red;
    transform: translateX(100%);
}

This doesn't work – the child only moves 20px (100% of itself), not all the way across the parent. (You can see this on jsfiddle):

enter image description here

I can do this:

#child {
    position: absolute;
    width: 20px;
    height: 100px;
    background-color:red;
    -webkit-transform: translateX(300px) translateX(-100%);
    transform: translateX(300px) translateX(-100%);
}

This works (seen here again on jsfiddle), because it first moves the child 300px (the full width of the parent), minus 20px (the width of the child). However, this depends on the parent having a fixed, known pixel dimension.

enter image description here

However, in my responsive design – I don't know the width of the parent, and it will change.

I know that I can use left:0 and right:0, but the animation performance of left/right is much worse than translateX (Thanks Paul Irish!).

Is there a way to do this?

Thanks in advance.

Best Answer

I didn't post my idea originally, because it involves creating an additional HTML layer, and expected better solutions to come.

Since that hasn't happened, I explain my comment. What I meant was this:

#parent {
    position: relative;
    width: 300px;
    height: 100px;
    background-color: black;
}
#wrapper {
    position: absolute;
    width: 100%;
    height: 100px;
    border: solid 1px green;
    transition: all 1s;
}
#wrapper:hover {
    -webkit-transform: translateX(100%);
    transform: translateX(100%);
}
#child {
    position: absolute;
    width: 20px;
    height: 100px;
    background-color:red;
}
#wrapper:hover #child {
    -webkit-transform: translateX(-100%);
    transform: translateX(-100%);
}

Since the wrapper is 100% width of the parent, translating it 100% works as expected.

fiddle

Note that the wrapper is being translated 100% as you stated. However, seems that what you really want is to move the element 100% - width. To achieve this, you have to translate the child also 100% (now this applies to the child width) in the opposite direction.

Correction: the child should share the transition property of the wrapper:

#parent {
    position: relative;
    width: 300px;
    height: 100px;
    background-color: black;
}
#wrapper {
    position: absolute;
    width: 100%;
    height: 100px;
    border: solid 1px green;
    transition: all 5s;
}
#wrapper:hover {
    transform: translateX(100%);
}
#child {
    position: absolute;
    width: 50px;
    height: 100px;
    background-color:red;
    transition: inherit;
}
#wrapper:hover #child {
    transform: translateX(-100%);
}
<div id="parent">
    <div id="wrapper">
        <div id="child"></div>
    </div>
</div>