why without display:none, css3 transition not working? - css

The code is from Bootstrap carousel, I wonder why without display:none, css3 transition not working? It should move from right to left.
Thanks! https://jsfiddle.net/25d3ga9j/11/
I want to remove .item{display:none}, and add visibility: hidden, then keep it working. It works in Firefox(transition-property: left),but not in Chrome(transition-property: transform;transform: translate3d...)
https://jsfiddle.net/zjmove/r8ejf5Lk/
$('.item').addClass('next')
$('.item')[0].offsetWidth // force reflow
$('.item').addClass('left')
.item {
height: 100px;
background: red;
display: none; //why with out display:none, transition not working?
}
.c {
overflow: hidden;
}
.item {
transition: transform 0.6s ease-in-out;
backface-visibility: hidden;
perspective: 1000px;
}
.item.next {
display: block;
transform: translate3d(100%, 0, 0);
left: 0;
}
.item.next.left {
transform: translate3d(0, 0, 0);
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="c">
<div class='item'>
</div>
</div>

There is a few things going on here, where the first is whether the first script line might run before the DOM is ready $('.item').addClass('next')
The second, there is no time for the first class to finish its transition until the second gets added, but a delay might solve that.
Either way, and based on whether which comes first (may vary between browsers), you can get different result.
The below sample shows how it should be set up when not using display: none, which by the way should be avoid if possible
$(window).load(function() {
$('.item').addClass('left')
});
.c {
overflow: hidden;
}
.item {
transition: transform 0.6s ease-in-out;
backface-visibility: hidden;
perspective: 1000px;
transform: translate3d(100%, 0, 0);
height: 100px;
background: red;
}
.item.left {
transform: translate3d(0, 0, 0);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="c">
<div class='item'>
</div>
</div>

Related

moving div from outside to inside the div and out again in pure css not using keyframe

content1.className = 'start';
window.getComputedStyle(document.getElementById('content1')).opacity;
content1.style.marginLeft = "0px";
content1.className = 'transition1';
.main {
width: 300px;
height: 250px;
top: 0px;
left: 0px;
overflow: hidden;
position: relative;
background-color: grey;
cursor: pointer;
}
#content1 {
background-color: red;
width: 300px;
height: 250px;
top: 0px;
left: 0px;
margin-left: -300px;
}
.start {
opacity: 0
}
.transition1 {
opacity: 1;
visibility: hidden;
/*margin-left: -300px !important;*/
-webkit-transition: margin-left 1.5s ease 1.5s, margin-left 1.5s ease 1.5s, visibility 1.5s ease 1.5s
}
<div id="main" class="main">
<div id="content1" class="content1 hidden">
</div>
</div>
I want the red div to start from outside and go into the grey div slowly then after a few seconds it would go out slowly again. I tried using transition but it seems to now work.
My guess is timing is wrong?
UPDATE
I have the above now What I lack is the timing to show the red div then go out again to left. I have set a visibility but I think there is a way to just use margins?
If you're wanting to do this without keyframes, then I have two ideas.
First idea is to add the transition css property to the actual #content1 element. Because as you're removing the .transition1 class, you're taking away the transition details.
If that doesn't work, then you might need to break this into 4 different "states".
That is:
Start State: Red div starts unseen
Start-to-End Transition State: .transition1 class gets added
End State: A class is added to ensure that the red div has the same margin from the .transition1 even after the .transition1 class gets taken away.
End-to-State Transition State: Essentially do the opposite of what you did in the .transition1 class.
EDIT:
Maybe ignore the "4 steps" because I likely was overthinking what you were asking.
I'm not 100% sure why you wouldn't want a keyframe, but I've added a few options you can reference depending on your overall use case. Each of these rely on some sort of trigger or event. In my case, a click. But this can be determined by any sort of event.
var main2 = document.getElementById('main2');
var content2 = document.getElementById('content2');
main2.addEventListener('click', function() {
content2.classList.toggle('active');
});
var main4 = document.getElementById('main4');
var content4 = document.getElementById('content4');
main4.addEventListener('click', function() {
content4.classList.add('animate');
setTimeout(function() {
content4.classList.remove('animate');
}, 1500)
});
.main {
width: 300px;
height: 250px;
position: relative;
background-color: grey;
cursor: pointer;
overflow: hidden;
}
#content1 {
position: absolute;
background-color: red;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
transform: translate(-100%, 0);
-webkit-transition: transform 1.5s ease;
}
.main:hover #content1 {
transform: translate(0, 0);
}
/* Toggle Option */
#content2 {
position: absolute;
background-color: red;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
transform: translate(-100%, 0);
-webkit-transition: transform 1.5s ease;
}
#content2.active {
transform: translate(0, 0);
}
/* SetTimeout Option */
#content4 {
position: absolute;
background-color: red;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
transform: translate(-100%, 0);
-webkit-transition: transform 1.5s ease;
}
#content4.animate {
transform: translate(0, 0);
}
<h2>Hover Option</h2>
<p>Animation happens on hover and disappears after hover</p>
<div class="main">
<div id="content1">
</div>
</div>
<h2>Toggle Option</h2>
<p>Animation happens on click and disappears on second click</p>
<div id="main2" class="main">
<div id="content2">
</div>
</div>
<h2>SetTimeout Option</h2>
<p>Animation happens on click and disappears after 1 second</p>
<div id="main4" class="main">
<div id="content4">
</div>
</div>

What can I use to replace translate3d

So, the code transform: translate3d(0,0,0); makes position:fixed; not work. and by removing it, I am now allowed to use position:fixed; again. one problem, my navigation bar was using the transform code to open, what other way can I use to make it do the same?
heres the code with the transform code, keep in mind this have been removed.
.nav-content {
flex: 1;
box-shadow: 0 0 5px rgba(0,0,0,1);
transform: translate3d(0,0,0);
transition: transform .3s;
}
.nav-content.isOpen {
transform: translate3d(220px,0,0);
}
.nav-content.isClosed {
transform: translate3d(0,0,0);
}
Transforms establish a containing block even for fixed elements. There is no workaround. Either don't use transforms or fixed positioning becomes somewhat useless.
In this case, if you are only using translate3d to translate in X direction, you can just use relative positioning with a left offset.
.nav-content {
position: relative;
left: 0;
transition: left .3s;
}
.nav-content.isOpen {
left: 220px;
}
.nav-content {
position: relative;
left: 0;
transition: left .3s;
height: 200vh;
border: 3px solid blue;
}
:checked ~ .nav-content {
left: 220px;
}
.fixed {
position: fixed;
}
<input type="checkbox" id="toggle" />
<label for="toggle">Toggle</label>
<div class="nav-content">
<div class="fixed">I am fixed</div>
</div>

Transform and Stacking Order

I am trying to understand what is really happening “3d” world of CSS.
I made a simple example
Particularly the code which bugs me the most is:
.back {
background-color: tomato;
transform: rotateY(180deg);
z-index: 1;
}
The thing which is not clear to me is why when you hover over .inner, its background color (gold) is not visible?? If you remove the transform property from .back or if you set the rotateY to 0deg then the gold background color of the .inner is clearly visible.
Why is the transform property of .back changing the stacking order?
Logically it makes sense that children(.front and .back) should appear in front of their parent(.inner).
Also, I would like to know what really happens when you set transform-style to flat? Does that make parent and all of its children collapse into single “unit” where element with highest stacking order takes priority/visibility?
in your code :
.outer {
display: block;
width: 200px;
height: 200px;
border: 2px solid gold;
perspective: 1000px;
padding: 10px;
margin: 0 auto;
}
.inner {
position: relative;
height: 100%;
width: 100%;
transition: transform 2s linear;
transform-style: preserve-3d;
background-color: gold;
backface-visibility: visible;
transform: rotateY(50deg);
}
.sides {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
color: white;
backface-visibility: hidden;
}
.front {
background-color: blue;
transform: translateZ(20px)
}
.back {
background-color: tomato;
transform: rotateY(180deg) translateZ(10px);
}
.inner:hover {
transform: rotateY(180deg)
}
<div class="outer">
<div class="inner">
<div class="sides front">Front Side</div>
<div class="sides back">Back Side</div>
</div>
</div>
you are using
transform: rotateY(180deg) translateZ(10px);
The transforms are applied right to left, so first it goes to the front 10px. But after that, it rotates 180deg. (around the transform-origin that is constant). That makes the previous 10px go towards the back instead of to the front.
if the order is the inverse
transform: translateZ(10px) rotateY(180deg);
now the rotation is done first, and so the translation is unafected by it and goes to the front.
and No, sorry, z-index is not a substitute for 3-d transforms, if you want to use 3d transforms, translation is the only way to go ....
In your first example, z-index is useless, as can be seen easily
codepen with z-index removed
This works because you are setting
backface-visibility: hidden;
So only the face that is facing front will be visible

rotateY() vs matrix3d transitions in Edge

I've come across a strange problem with the way Edge (and IE 11) handles my matrix3d transform. The page I'm working on has elements that already have an arbitrary transform applied to them (due to a plugin being used), however thanks to my manager I now need to apply a 180 degree rotation around the Y axis on top of this. Because of this, I could not simply use the rotateY() function as it replaced the old transform and moved the element, so I figured I'd need to use matrices. This works fine in Chrome and Firefox, but Edge doesn't seem to handle matrix3d in the same way.
Here's an example of using rotateY: http://codepen.io/anon/pen/wGqapy
(HTML)
<body>
<div class="flip-container">
<div class="front">
Test
</div>
</div>
</body>
(CSS)
.flip-container,
.front {
width: 320px;
height: 480px;
}
.front {
transition: 0.6s;
position: absolute;
top: 0;
left: 0;
z-index: 2;
background-color: green;
}
.flip-container:hover .front
{
transform: rotateY(180deg);
}
When you mouse over the element, it rotates around the Y axis in 3D space. And here's an example of using matrix3d, using the same matrix shown in the "computed CSS" tab in Edge: http://codepen.io/anon/pen/QNMbmV
(HTML)
<body>
<div class="flip-container">
<div class="front">
Test
</div>
</div>
</body>
(CSS)
.flip-container,
.front {
width: 320px;
height: 480px;
}
.front {
transition: 0.6s;
position: absolute;
top: 0;
left: 0;
z-index: 2;
background-color: green;
}
.flip-container:hover .front
{
transform: matrix3d(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1);
}
This, however, seems to spin around more than one axis. This does not occur in Firefox or Chrome. Am I supposed to use some magical vendor-specific CSS? I've been unsuccessful in searching SO or Google, so I hope someone has some insight!
Thanks in advance.
Matrices are very good for calculus, and for setting the transforms in an universal way. But aren't so good when you are transitioning from one state to the other.
a simple animation as
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
is impossible to set with matrices
Also, take into account that even using matrices, you can chain them with others transforms.
All that said, let's see an example of your rotation working on a previously transformed element
.flip-container,
.front {
width: 320px;
height: 480px;
}
.front {
transition: 0.6s;
position: absolute;
top: 0;
left: 0;
z-index: 2;
background-color: green;
/* transform: rotate(10deg); is equivalent to matrix(0.984808, 0.173648, -0.173648, 0.984808, 0, 0) */
transform: matrix(0.984808, 0.173648, -0.173648, 0.984808, 0, 0) rotateY(0deg);
}
.flip-container:hover .front {
transform: matrix(0.984808, 0.173648, -0.173648, 0.984808, 0, 0) rotateY(180deg);
}
<div class="flip-container">
<div class="front">
Test
</div>
</div>

CSS hover firing more than once with webkit 3d transform

When I use a webkit 3d transform on hover, only the top 50% of the hover area works, while the bottom 50% is unstable. I'm currently testing on Chrome (31.0.1650.63). Is it a bug? Is there any workaround?
Try to place your mouse on the top of the div and slowly bring it to the bottom.
HTML
<div class="hoverArea"></div>
<div class="flip">
<div class="front">front</div>
<div class="back">back</div>
</div>
CSS
.hoverArea, .flip, .front, .back {
width: 200px;
height: 200px;
position: absolute;
top: 0;
left: 0;
}
.hoverArea {
z-index: 10;
}
.flip {
-webkit-transform-style: preserve-3d;
-webkit-transition: 0.5s;
-webkit-perspective: 800;
z-index: 9;
}
.front {
background-color: #f00;
-webkit-backface-visibility: hidden ;
}
.back {
background-color: #f0f;
-webkit-transform: rotatex(-180deg);
-webkit-backface-visibility: hidden ;
}
.hoverArea:hover + .flip {
-webkit-transform: rotatex(-180deg);
}
http://jsfiddle.net/4P53y/
You can fix it by removing the .hoverArea element and instead apply the :hover event on the .flip element.
.flip:hover {
-webkit-transform: rotatex(-180deg);
}
Demo
If you want to still use the .hoverArea element then you can use transform:translateZ(1px); on .hoverArea to make it function correctly. It makes the browser render the element more carefully
.hoverArea {
z-index: 10;
-webkit-transform:translateZ(1px);
}
Demo

Resources