Css3 Transform Reverts Position: Fixed

css3 transform reverts position: fixed

You could use a work around like this one. It involves toggling a left value (via a class) for both the fixed element and the container.

.global-wrapper {
position: relative;
-webkit-transition: 300ms;
transition: 300ms;
}
.global-wrapper.expanded,
.global-wrapper.expanded .navbar {
left: 200px;
}
.navbar {
-webkit-transition: 300ms;
transition: 300ms;
position: fixed;
width: 100px;
height: 100%;
top: 0px;
left: 0px;
}
.content {
position: relative;
width: calc(100% - 170px); /* 100% - width of left bar plus margin */
}

With a small amount of vanilla JS to toggle it the class:

var wrapper = document.querySelector(".global-wrapper");
document.getElementById("expand").onclick = function() {
wrapper.classList.toggle("expanded");
}

Why does `transform` break `position: fixed`?

Regarding the why, a quick quote from this article by meyer:

A transformed element creates a containing block even for descendants that have been set to position: fixed. In other words, the containing block for a fixed-position descendant of a transformed element is the transformed element, not the viewport

It's a quirky behavior that's been around since 2011.

position: fixed not woking when parent has the transform CSS property

This is not a bug.

Take a look at the spec: The Transform Rendering Model

Specifying a value other than ‘none’ for the ‘transform’ property
establishes a new local coordinate system at the element that it is
applied to.

So according to the spec: the element with fixed positioning will become relative to the element with the transform - not the viewport

As a workaround you could:

1) Use transitions (eg. on the left property) instead of transform (translateX)

2) Remove the position:fixed button from the container which uses transforms

Using CSS transform scale breaks position:fixed

Well the transform: scale(x) will break the element out of the coordinate flow and thereby can not have a fixed position.

I'd recommend instead wrapping the text below #header in a constrained div with overflow: auto. A fixed child of a fixed ancestor just doesn't make that much sense, but I can see what you were going for.

transform3d' not working with position: fixed children

This is because the transform creates a new local coordinate system, as per W3C spec:

In the HTML namespace, any value other than none for the transform results in the creation of both a stacking context and a containing block. The object acts as a containing block for fixed positioned descendants.

This means that fixed positioning becomes fixed to the transformed element, rather than the viewport.

There's not currently a work-around that I'm aware of.

It is also documented on Eric Meyer's article: Un-fixing Fixed Elements with CSS Transforms.

Positions fixed doesn't work when using -webkit-transform

After some research, there has been a bug report on the Chromium website about this issue, so far Webkit browsers can't render these two effects together at the same time.

I would suggest adding some Webkit only CSS into your stylesheet and making the transformed div an image and using it as the background.

@media screen and (-webkit-min-device-pixel-ratio:0) {
/* Webkit-specific CSS here (Chrome and Safari) */

#transformed_div {
/* styles here, background image etc */
}
}

So for now you'll have to do it the old fashioned way, until Webkit browsers catch up to FF.

EDIT: As of 10/24/2012 the bug has not been resolved.


This appears to not be a bug, but an aspect of the specification due to the two effects requiring separate coordinate systems and stacking orders. As explained in this answer.

Why adding transform to fixed parent changes child width?

From CSS 2.1 - Definition of "containing block" and CSS Position 3 - Definition of containing block,

If the element has position: fixed, the containing block is
established by the viewport in the case of continuous media or
the page area in the case of paged media.

However, that changes when you add transforms to some ancestor. From CSS Transforms 1 - The Transform Rendering Model,

For elements whose layout is governed by the CSS box model, any value
other than none for the transform results in the creation of both a
stacking context and a containing block. The object acts as a
containing block for fixed positioned descendants.

CSS3 transform rotate text, fixed position left and right, vertically centered

I solved it and cleaned the code up a bit.

.left,
.right {
position: fixed;
top: 0;
bottom: 0;
height: 1.5em;
margin: auto;
}

.left {
left: 0;
-webkit-transform-origin: 0 50%;
-moz-transform-origin: 0 50%;
-ms-transform-origin: 0 50%;
-o-transform-origin: 0 50%;
transform-origin: 0 50%;
-webkit-transform: rotate(-90deg) translate(-50%, 50%);
-moz-transform: rotate(-90deg) translate(-50%, 50%);
-ms-transform: rotate(-90deg) translate(-50%, 50%);
-o-transform: rotate(-90deg) translate(-50%, 50%);
transform: rotate(-90deg) translate(-50%, 50%);
}

.right {
right: 0;
-webkit-transform-origin: 100% 50%;
-moz-transform-origin: 100% 50%;
-ms-transform-origin: 100% 50%;
-o-transform-origin: 100% 50%;
transform-origin: 100% 50%;
-webkit-transform: rotate(90deg) translate(50%, 50%);
-moz-transform: rotate(90deg) translate(50%, 50%);
-ms-transform: rotate(90deg) translate(50%, 50%);
-o-transform: rotate(90deg) translate(50%, 50%);
transform: rotate(90deg) translate(50%, 50%);
}

Demo: http://codepen.io/anon/pen/LHeaB

Why changing the position changes the effect of 3D transform?

although both of them has the same perspective view why changing their position changed the effect of 3D transform ?

They have the same perspective, yes but the trick is in the perspective-origin which is set to be the center of the parent element (not the elements). Your Red element is already in center so it will only comes close to your while the yellow element isn't in the center so its movement will be different.

To better illustrate here is another example using a rotate transformation.

.container {
border:2px solid red;
perspective:300px;
perspective-origin:50% 50%;
padding:20px;
display:flex;
justify-content:space-around;
}

.container > div {
width:50px;
height:50px;
background:blue;
transform:rotateY(20deg);
}
<div class="container">
<div></div>
<div></div>
<div></div>
</div>

<div class="container" style="perspective-origin:10% 50%">
<div></div>
<div></div>
<div></div>
</div>

<div class="container" style="perspective-origin:70% 50%">
<div></div>
<div></div>
<div></div>
</div>


Related Topics



Leave a reply



Submit