Why is CSS translate3d transform behaving as relative positioned element? - css

In the below fiddle, <a> tag LOGO is absolute positioned within a layoutDiv div which is having -webkit-transform: translate3d(0,0,0); CSS being applied via 'modern' class.
https://jsfiddle.net/gurumvg/ubj98j6d/4/
Though the layoutDiv div is not having 'relative' position the <a> tag LOGO is positioned absolutely w.r.t layoutDiv div instead of BODY node. Wondering why the -webkit-transform: translate3d(0,0,0); style is positioning it as relative.
Appreciate any insights.

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

Related

CSS bug brings pseudo-elements between background and text on position fixed [duplicate]

This question already has answers here:
Why can't an element with a z-index value cover its child?
(5 answers)
Closed 6 months ago.
Seems like I just found a bug or something. Usually when an element has a pseudo-element and I want it to show behind its parent I use z-index:-1. This works fine if the element has position relative or absolute but on position fixed something weird happens: the pseudo-element comes between the background and the text of the element like this:
div {width:200px;height:100px;position:fixed;background:black;display:block;}
div::after {content:"";position:absolute;top:0;width:100%;height:100%;background:red;z-index:-1;display:block;}
<div>
example
</div>
Can this be fixed so the pseudo-element goes completely behind the parent as it does with the other positions?
Thank you.
The behavior your are experiencing is due to stacking contexts in CSS:
A stacking context is formed, anywhere in the document, by any element in the following scenarios:
[…]
Element with a position value absolute or relative and z-index value other than auto.
Element with a position value fixed […]
So when you use position: fixed on the parent, it becomes a new stacking context, whereas when you use position: absolute or position: relative without a z-index, it is not a new stacking context, which is why you see this discrepancy in behavior.
When the parent element is a stacking context it becomes a "container" for position stacking. The text or other elements inside it are by default at the stacking position 0 but the pseudo element in your example has z-index of -1 so it goes behind the text. It does not go behind the parent because the parent itself is the container. It is like you have all these elements in a box and elements can't go outside the the box.
So to have the pseudo element be behind its stacking context parent, we can use a 3D transform to translate the pseudo element behind the plane of the parent. We add transform-style: preserve-3d so "that the children of the element should be positioned in the 3D-space" and then we can add transform: translateZ(-1px) to push the child element behind:
div {
width:200px;
height:100px;
position:fixed;
background:black;
display:block;
transform-style: preserve-3d;
}
div::after {
content:"";
position:absolute;
top:0;
width:100%;
height:100%;
background:red;
z-index: -1;
display:block;
transform: translateZ(-1px);
}
<div>
example
</div>

Why inline element will return to its original position if I transform it when it be hovered?

I try to transform an element when it be hovered, like that:
span{
transition: transform 0.35s;
}
span:hover{
transform: translateY(30px);
}
<span>test</span>
On IE, it work well, but not on Chrome and Firefox.It will return to its original position.
I found if add display:block to span, it will fine(also has little problem with Firefox), but WHY? Is there better way to do this?
I think it returns to original position because it physically moves and the mouse is no longer hovering the element after the translation.
A couple ideas:
1) If you want the element to stay moved while the mouse is hovered but return when the mouse leaves, perhaps you could do a CSS3 Transition on padding instead of translate, that way the element content will move but the box in the DOM itself will stay to keep the :hover effect
2) If you want the element to stay in its place and not return after hovering, you will probably want to use Javascript to add a class to the element after hovering and style the class
Good luck!
A transformable element is an element in one of these categories:
an element whose layout is governed by the CSS box model which is either a block-level or atomic inline-level element, or whose display property computes to table-row, table-row-group, table-header-group, table-footer-group, table-cell, or table-caption [CSS21]
an element in the SVG namespace and not governed by the CSS box model which has the attributes transform, ‘patternTransform‘ or gradientTransform [SVG11].
From the w3 specification.
So inline-block elements, inline-table elements, replaced inline-level elements (think img, video, etc.) and possibly other atomic inline-level element are transformable inline-level elements.
If you make your span display either block, inline-block or inline-table, it will be considered a transformable element, otherwise it won't. What the browser does with non-transformable element is not specified.
span{
transition: transform 0.35s;
display:inline-block;
}
span:hover{
transform: translateY(30px);
}
<span>test</span>
i hope to help. The problem with Firefox is that the translateY only applies in divs, therefore:
Put your span within a div

Create fluid triangle with CSS

I want to create this triangle in CSS.
http://acceptatie.foursites.nl/foursites/vierkant.jpg
But it must be a fluid triangle. How can i make this I try with skewY. But than the triangle is broken at the to of the element.
Thank you for helping me!
Instead of using borders to make the triangle you can use transform to rotate a div and just hide the overflow of the parent element.
If use transform instead of borders you can have box shadow on the div to :)
Tranform code for rotating a div
-webkit-transform: rotate(357deg);
-moz-transform: rotate(357deg);
-ms-transform: rotate(357deg);
-o-transform: rotate(357deg);
and as i said just hide the overflow on the parent element, in your case the body tag
overflow: hidden;
But here is an example on jsfiddle
Hope you can use it.

:hover works only on lower part of rotateX transformed div

I have div with CSS rotateX transform applied to it:
-webkit-transform: perspective(500px) rotateX(60deg) rotateY(60deg) ;
and a bunch of smaller div's floated in it, with :hover rule applied to them.
The problem is that only half of inner divs react to :hover event.
JsFiddle: http://jsfiddle.net/fNxgn/4/
if you remove in css height: 200px all block will react hover event

css z-index lost after webkit transform translate3d

I have two absolutely positioned div elements that overlap. Both have set z-index values via css. I use the translate3d webkit transform to animate these elements off the screen, and then back onto the screen. After the transform, the elements no longer respect their set z-index values.
Can anyone explain what happens to the z-index / stack-order of the div elements once I do a webkit transform on them? And explain what I can do to keep the stack-order of the div elements?
Here is some more information on how I am doing the transform.
Before the transform, each element gets these two webkit transition values set via css (I am using jQuery to do the .css() function calls:
element.css({ '-webkit-transition-duration': duration + 's' });
element.css({ '-webkit-transition-property': '-webkit-transform' });
The element is then animated using the translate3d -webkit-transform:
element.css({ '-webkit-transform': 'translate3d(' + hwDelta + 'px, 0, -1px)' });
Btw, I have tried setting the 3rd parameter of translate3d to several different values to try to replicate the stack-order in the 3d space, but to no luck.
Also, iPhone/iPad and Android browsers are my target browser that this code needs to run on. Both support webkit transitions.
This might be related to: https://bugs.webkit.org/show_bug.cgi?id=61824
Basically when you apply a 3D transform on the z-axis, the z-index can't be accounted for anymore (you're now in a 3 dimensional rendering plane, use different z-values). If you want to switch back to 2D rendering for child elements, use transform-style: flat;.
This is most definitely related to the bug noted by samy-delux. This should only affect any elements which are positioned as absolute or relative. In order to remedy the issue, you can apply the following css statement to every element which is positioned this way and is causing issues:
-webkit-transform: translate3d(0,0,0);
This will apply the transform to the element without actually doing a transformation, but affecting its render order so it is above the element causing the issue.
Bit Late to this but try putting on the elements that have lost their Z-index placing the following, I had an issue when doing some parallax stuff recently and this helped massively.
transform-style: preserve-3d;
This saves putting
transform: translate3d(0,0,0);
On other elements which puts more strain on the GPU
Waiting to see the example
Have you tried to do a transform scale(1)? I remember to had a similar problem, and I had to re-arrange the html order of elements, and utilise a transform that I didn't need it just because the z-index of the use of transform changed.
If I am not in error, every time that you use a transform, it become the highest z-index available, and it is ordered by the nearest element of html is to the start of the tag. So from up to below.
I hope that this help
z-index will work against 3d transformed divs if you style the stackable element with -webkit-transform: translateZ(0px);
Snippet on codepen -> http://codepen.io/mrmoje/pen/yLIul
In the example, the buttons stack up and stack down raise and lower the footer's z-index (+/-1) against the rotated element (an img in this case).
I haven't been able to reproduce the problem you describe here. Regardless of what I do, the z-index value is retained throughout all transforms. I'm testing using Chromium (Google Chrome).
The third argument of the translate3d function manipulates the z-axis of the element. The concept is similar to, but not exactly the same as, the z-index... Elements with a lower z-axis are under elements with a higher value.
I know you tried values of the third argument to match your intended z-index, but the problem is that the z-axis doesn't seem to change during CSS3 animation. In the following example, the hovered element should be on top, but #element_a stays on top.
If I add a z-index to both the regular selector and the :hover selector, it seems to work and allow the hovered element to be top-most.
Although it's not exactly what you were looking for, this behavior provides a solution. You just need to use translate3d and z-index to set the order for the initial rendering.
<style>
div {
width: 300px;
height: 150px;
background-color: white;
border: 5px outset gray;
float: left;
margin: 20px;
-webkit-transition: 2s;
}
#element_a {
-webkit-transform: translate3d(0, 0, 50px);
}
#element_b {
-webkit-transform: translate3d(0, 0, 100px);
}
#element_a:hover {
-webkit-transform: translate3d(100px, 0, 60px);
}
#element_b:hover {
-webkit-transform: translate3d(-100px, 0, -60px);
}
</style>
<body>
<div id="element_a">
<img src="http://www.google.com/intl/en_com/images/srpr/logo3w.png">
</div>
<div id="element_b">
<img src="http://www.google.com/intl/en_com/images/srpr/logo3w.png">
</div>
</body>
I had this problem on iphone/ios where I had a dropdown menu that overlapped a leafletjs map but was being covered by the map. Noticed that the map had translate3d applied.
Added this to the dropdown element:
transform: translate3d(0,0,0);
...and it is fixed. Thank you stackoverflow people.
Another way around this is that you can create a parent element and apply all other transitions related to it:
# Apply transitions to a parent div
<div>
# This image z-index -1
<img src="foo"/>
# This image z-index -3
<img src="bar"/>
#This image z-index -2
<img src="gg"/>
</div>
JsFiddle

Resources