I am trying to implement a slide in/out animation when transitioning between ui-views.
Here's a plunker. (Navigate from Home > About > Home)
When a new view appears, the old view jumps down below it. The intention is for the old view to seamlessly slide off left with no vertical movement, like a carousel.
I am aware of the position: absolute solution to this; but doing this rather messes up other elements of my layout; I'd like to keep the elements in the page flow. I have tried all manner of combinations of display, position etc.
.slide-left {
position: relative;
transition: all 1s ease-in-out;
margin: 1em;
}
.slide-left.ng-enter {
transform: translateX(110%);
opacity: 0;
}
.slide-left.ng-enter-active {
transform: translateX(0);
opacity: 1;
}
.slide-left.ng-leave {
transform: translateX(0);
opacity: 1;
}
.slide-left.ng-leave-active {
transform: translateX(-110%);
opacity: 0;
}
Are there any other solutions? How do carousels work? (Off to check their source code...)
Edit:
Having checked Bootstrap's source code, they use position: absolute when the slide animation is in progress (.next and .prev classes). I'm concluding that the use of absolute is unavoidable for this effect to work; at least it only has to apply during the effect.
Related
I was trying to make a 100% pure css animation, fadein and fadeout when i click on hamburguer menu to reveal the sidebar, (the backdrop should showing opacity like 500 miliseconds) (like jquery fadein) and when i click inside the sidebar to close the menu (the backdrop should hidde the opacity in 2 seconds) (like jquery fadeout)
You can see the version of jquery code here: https://cdpn.io/gilperon/fullpage/ZErBzvY
This is a very simple code, to open menu i put the event on hamburguer icon onclick=' $('#menu-backdrop').fadeIn(500);' and close to close, i put onclick=' $('#menu-backdrop').fadeout(2000);'
If it is not possible to make 100% css pure the animation, since it should be activated by onclick, maybe use just the javascript pure to onclick to add class, and the animation by done via css
I have a lot of ways using height:0 and key frames, but it was not possible to make the animation fadeout, fadein it works.
I make a code that workds to fadein, but to fadeout not working:
Another options are welcome, maybe using visibility, or other ways to show and hidden the animation, display:none usually not works with css animation
#menu-backdrop {
display: none;
animation:fadeOut 5s linear;
}
#menu-backdrop.exibir {
display: block;
animation:fadeIn 0.5s linear;
}
#keyframes fadeIn {
0% {
opacity:0
}
100% {
opacity:1;
}
}
#keyframes fadeOut {
0% {
opacity:1
}
100% {
opacity:0;
}
}
If anyone can post a work solution should be great, thank you very much guys.
Okay what you need is a transition, and you need to move away from your display property as it will break your animations and transitions since you cannot animate or transition that property in CSS.
A quick example:
const button = document.querySelector( 'button' );
const nav = document.querySelector( 'nav' );
button.addEventListener( 'click', event => {
event.preventDefault();
nav.classList.toggle( 'active' );
});
nav {
position: fixed;
right: 0;
top: 0;
width: 50%;
height: 100%;
background: red;
transition: opacity .4s;
/* This should be set to 0, but to make the point
* of pointer-events clear, I will set it to slightly
* higher so you can see there's no interaction
* with the nav. */
opacity: .1;
pointer-events: none;
}
nav:hover {
/* If you can interact with the navigation,
* you will see it change color. */
background: blue;
}
nav.active {
opacity: 1;
pointer-events: all;
}
nav + button:before {
content: 'Open ';
}
nav.active + button:before {
content: 'Close ';
}
<nav></nav>
<button>Nav</button>
The above shows you that by combining pointer-events: none with opacity you can effectively hide your menu. I added the :hover state for the <nav> to show that you cannot click the <nav> when it is open, and you should therefor consider this element invisible to the user.
I have a less file that hide and display an element like the following:
.cmp-accordion__panel {
&--hidden {
display: none;
}
&--expanded {
display: block;
-webkit-animation: slide-down 0.5s ease-out;
-moz-animation: slide-down 0.5s ease-out;
}
}
#-webkit-keyframes slide-down {
0% {
opacity: 0;
-webkit-transform: translateY(-5%);
}
100% {
opacity: 1;
-webkit-transform: translateY(0);
}
}
#-moz-keyframes slide-down {
0% {
opacity: 0;
-moz-transform: translateY(-5%);
}
100% {
opacity: 1;
-moz-transform: translateY(0);
}
}
In my JavaScript, I toggle the class name of the element between "cmp-accordion__panel--hidden" and "cmp-accordion__panel--expanded" if the event is triggered. I use keyframe and opacity to animate the transition from "display:none" to "display:block".
However, when I go from "display:block" to "display:none" to hide the element, the effect happens INSTANTLY. What should I add to animate the hiding?
As already said, is not possible animate or transition from display:block; to display: none; but this could be simulated in another way and is not necessary to use CSS animations, simply CSS transitions (in addition, is not necessary anymore to use vendor-prefixes to declare transitions or animations).
Please, look at this working example:
HTML (I inserted a fake content to create an element with a relative big height)
<div class="cmp-accordion__panel--expanded">
b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b<br>b
</div>
LESS
[class*="cmp-accordion__panel"] {
border:solid 1px red;
overflow:hidden;
transition:opacity 0.3s ease-out, max-height 0.8s ease-out;
}
.cmp-accordion__panel {
&--hidden {
max-height:0;
opacity:0;
}
&--expanded {
opacity:1;
max-height:1000px;
}
}
Please note that, thanks to attribute partial value selector I added also some rules that apply to both *--hidden and *--expanded classes (I personally prefer a general class and an addition of a second one in some cases, instead of switching between two, but I did not want to change too much your approach).
The key rule is switching between two values of max-height property, from a 0 value to another "enough big" one. If you effectively know final height of the element you can simply use also height property, but in case of dynamic content, max-height did the trick.
Please note also the presence of overflow:hidden; applied to both classes, to simulate height changes.
Finally, animation effect relies only on a CSS transition applied to opacity and max-height properties, with different timings to enhance effect.
You cannot animate or transition from display: block; to display: none;, so you will need to remove this if you wish to animate it.
To ensure it fades and is removed you should animate the visibilty and opacity attributes.
Alternatively if you are using jQuery you can use the .fadeOut() function.
MDN - CSS Visibility
jQuery - fadeOut()
I'm trying to create a 100% width and 100vh height div which would slide from out of the screen from above to down of page. At the 70% of animation I would like to make it at the bottom then at 90% move it 30px up and on 100% make it at the bottom again so it would look like it slide from up then bounce at the bottom.
I want this happen after clicking some DOM element in a grand grandchild so basically, I'll use eventBus and my "sliding div" will be in root component (app.vue) and in the child I'll emit:
showObserved() {
eventBus.$emit('showObserved');
}
here I'm emitting my custom event and then I'm watching this event in root component and changing boolean variable:
eventBus.$on('showObserved', async() => {
this.showObserved = true;
});
eventBus.$on('hideObserved', async() => {
this.showObserved = false;
});
and basing on this boolean I'm displaying my sliding div using v-if directive:
<transition name="slide-up" mode="out-in">
<observed-offer v-if="showObserved"></observed-offer>
</transition>
and here finally I use transition vue built-in component in order to make it sliding and this are my styles which should make effect that I explained in first parahraph:
/* slide from up to down */
.slide-up-leave-active {
animation: slide-out-up .4s linear;
}
.slide-up-enter-active {
animation: slide-in-up .4s linear forwards;
}
.slide-up-in-leave-active {
animation: slide-out-up .4s linear;
}
.slide-up-leave {
opacity: 1;
transform: translateY(-100%);
}
#keyframes slide-out-up {
0% {
transform: translateY(0);
}
70% {
transform: translateY(0);
}
90% {
transform: translateY(10%);
}
100% {
transform: translateY(0);
}
}
#keyframes slide-in-up {
0% {
transform: translateY(-100%);
}
70% {
transform: translateY(0);
}
90% {
transform: translateY(10%);
}
100% {
transform: translateY(0);
}
}
and this are style's of my sliding div:
.observed {
width: 100%;
height: 100vh;
z-index: 999999999;
overflow: hidden;
background-color: white;
}
But this doesn't work behavior is that it instantly makes entire page white and slide only content of div. I'm pretty sure that I just made wrong CSS styles I tried various other styles and it didn't work. Also maybe it has also something to do with height: 100vh.
I add demo repository. In this demo sliding in is almost working but slide out doesn't work at all. Installation of this project is simple just clone it then cd path/to/project then npm install && npm run dev or something similiar depending on OS.
In demo it's also not hovering entire page but it leave space for button as you'll see if you clone it.
Well actually I handle to fix transitions in demo repo now the only issue is that it doesn't veil/cover entire page but it leave space for root content. Pull repo again to see that.
Issue was that I was using bad transition styles and that I didn't have fixed position with top: 0 left: 0 on my panel component. After fixing that it's working correctly as you can inspect in demo repository.
Sorry for wasting time for issue that I fixed myself but it was much harder to troubleshoot in origin big project. When I created this demo repo it became so easy.
I'm working on CSS and web development,but just face a something which i really don't understand it:
.header{
position: absolute;
width:60%;
top: 20%;
left: 50%;
transform: translateX(-50%);<------ executed after animation
text-align: center;
animation: moveUp 2s;
animation-fill-mode: backwards;
}
#keyframes moveUp{
0%{
opacity: 0;
transform:translateY(2rem);
}
100%{
opacity: 1;
transform: translateY(0rem);
}
}
so my problem here is the indicated line doesn't apply on ".header" until the animation gets applied in other word it applies animation first then translate -50% ,is there a priority of execution here or it is different thing?
Usually the styles are parsed from top to bottom, however this isn't the issue here.
What is happening in your case is the transform is being applied initially, but then it is being overridden by the animation. Once the animation is over, the element is reverting back to its default style which has the transform.
Essentially, even though the transform is applied at first, you don't see it until the element reverts to it after the end of the animation.
The only solution if you want to have the transform during the animation, is to include it in the animation itself.
#keyframes moveUp {
0 % {
opacity: 0;
transform: translate(-50%, 2rem);
}
100 % {
opacity: 1;
transform: translate(-50%, 0);
}
}
EDIT: To clarify, the order at which the styles are applied does not matter. Whether the animation or the transform is applied first, the result will be the same.
I think a source of your confusion is that the first transform is a translateX while the animation only does translateY. In both cases what is changing is the value of the transform property of the element. Therefore which axis the translation is on doesn't matter. First you set transform: translateX(-50%), but then once the animation kicks in, transform becomes translateY(2rem). The translateX part is removed from the transform, unless you include it in the animation like I have shown.
Preface
I'm trying to create a responsive website with a navigation menu that satisfies the following two requirements:
Navigation is fully visible in a normal browser window, laid out horizontally.
Navigation becomes a toggleable vertical menu for mobile devices and small screens, which animates between its "opened" and "closed" state.
I want performance to be good on mobile devices — especially on iOS — which means that the animation should use a GPU-accelerated translate3d transform CSS transition.
My Problem
Setting this up was a piece of cake, and for the most part it works great. I used z-index: 1 and transform: translate3d(0,-100%,0) to hide the menu behind a header with z-index: 2 in its default closed state, and then transform: translate3d(0,0,0) to animate the menu to its opened state.
But I'm just having one problem: When I resize my Chrome browser window and the mobile media query kicks in, the menu animates from an opened to closed state.
Resize your browser window to less than 600px wide to see the problem in action:
Fullscreen jsfiddle: http://fiddle.jshell.net/ymDYG/1/show/
Original jsfiddle: http://jsfiddle.net/ymDYG/1/
I think I know why this is happening: when the mobile media query kicks in, the browser sees that .nav is not currently active, so it animates it to the default closed state. I've tried experimenting with using display:none and display:block for the different media query states, but that seems to completely break the animation.
How can I prevent the nav menu's "closing" animation from firing as the browser window is resized?
Nice job, very clean. Can i steal it? :-)
Anyway, here's your solution with a demo.
I just moved the transition to another class:
.nav {
/* stuff */
z-index: 1;
transform: translate3d(0,-100%,0);
-webkit-transform: translate3d(0,-100%,0);
}
.nav.active {
transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);
}
.nav.activated {
transition: transform 400ms linear;
-webkit-transition: -webkit-transform 400ms linear;
}
Which you can add to the element at first "Toggle":
function toggle(){
$(".nav").addClass("activated").toggleClass("active");
}
P.S. If you don't want the transition to happen even after the user has opened the menu and then resized the window again, you could use Modernizr's mq method:
$(window).on('resize',function(){
if(Modernizr.mq('(min-width:600px)')) $(".nav").removeClass("activated");
});
Referring to the side effect that Giona mentioned:
P.S. If you don't want the transition to happen even after the user has opened the menu and then resized the window again (...)
there is a cleaner way to fix this without firing on each resize event. You can remove the class resposible for transition after the transition end (full demo here):
$(function()
{
$(".nav").on("transitionend", function() {
$(this).removeClass("activated");
});
}
)();
By combining answers from Giona and Janusz Kacalak (and Justin Bull's comment), we can further optimize the code so that the nav bar will never animate from an opened to closed state (not just for the first time, which is what Giona's code does).
function toggle() {
var navbar = $(".nav");
if (navbar.hasClass("active")) {
// Closing the nav bar.
navbar.removeClass("active");
// Listening for a transition.
// Use `.one` here because we only want this to be called once.
navbar.one(whichTransitionEvent(), function() {
// Remove animation property after the nav bar is closed.
navbar.removeClass("activated");
});
} else {
// Opening the nav bar.
navbar.addClass("activated").addClass("active");
}
}
// Ref: https://davidwalsh.name/css-animation-callback
function whichTransitionEvent() {
var t;
var el = document.createElement('fakeelement');
var transitions = {
'transition': 'transitionend',
'OTransition': 'oTransitionEnd',
'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
};
for (t in transitions) {
if (el.style[t] !== undefined) {
return transitions[t];
}
}
}
body { margin: 0; }
.toggle { display: none; }
.nav { list-style-type: none; margin: 0; padding: 0; }
.nav li { float: left; margin: 0; padding: 20px; background: #fdd; }
.nav li:nth-child(2n) { background: #dfd; }
#media only screen and (max-width: 599px)
{
.toggle {
display: block;
position: relative;
z-index: 2;
padding: 20px;
background: #eee;
}
.nav li {
display: block;
float: none;
}
.nav {
display: block;
position: relative;
z-index: 1;
transform: translate3d(0,-100%,0);
-webkit-transform: translate3d(0,-100%,0);
}
.nav.active {
transform: translate3d(0,0,0);
-webkit-transform: translate3d(0,0,0);
}
.nav.activated {
transition: transform 400ms linear;
-webkit-transition: -webkit-transform 400ms linear;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Toggle menu
<ul class="nav">
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
</ul>