Reputation: 1341
I am attempting to slide one of two 'pages' i.e <divs>
into view with a gentle transition where the user can see one page sliding out whilst the other page slides in. In my final application, the transition will be triggered from my backend (probably with a WebSocket message).
I would like the pages to slide in from the left and for the effect to 'loop'; that is that when returning to the first page, it still slides in from the left.
I have created a snippet below which demonstrates my current plan of using a CSS3 transition to achieve the desired effect. It works but feels very clunky.
It operates as follows:
#page1
starts in view and #page2
has it's horizontal position offset by its width through use of the in-frame
and out-of-frame
classes respectively.
For #page1
to #page2
transition, I simply apply the .slide
class which uses a transform:translateX()
to reposition both 'pages' by their width and the transition property of the page
class handles the transition effect.
In order to perform loop-like behaviour I wait for the transition to finish, then I toggle which page has which in-frame
or out-of-frame
class with the intention of bringing #page1
back to being off-screen to the left of #page2
. However in order to prevent this position-change running as a transition, I have to apply the .notransition
class which feels like a kludgey work-around.
My Question: Is there a better way to achieve this behaviour using CSS transitions?
I know bootstrap's carousel can do it for me like this but it would be nice to know if/where I am going wrong.
// add transition finished handler to each page
$('.page').on('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function() {
// toggle in/out of frame
$(this).toggleClass('in-frame')
.toggleClass('out-of-frame')
.addClass('notransition')
.removeClass('slide')
})
$('body').click(function() {
// start transform
$('.page').removeClass('notransition').addClass('slide')
})
html,
body {
height: 100%;
overflow: hidden;
text-align: center;
font-size: 2em;
}
#content {
position: relative;
height: 100%;
}
.page {
position: absolute;
top: 0;
height: 100%;
width: 100%;
-webkit-transition: transform 2s cubic-bezier(0.19, 1, 0.22, 1);
-moz-transition: transform 2s cubic-bezier(0.19, 1, 0.22, 1);
-o-transition: transform 2s cubic-bezier(0.19, 1, 0.22, 1);
transition: transform 2s cubic-bezier(0.19, 1, 0.22, 1);
}
.slide {
-webkit-transform: translateX(100%);
-moz-transform: translateX(100%);
-o-transform: translateX(100%);
transform: translateX(100%);
}
.in-frame {
left: 0%;
}
.out-of-frame {
left: -100%;
}
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="content">
<div id="page1" class="page in-frame" style="background: #d67e56;">
Main Page <br> (Click Me)
</div>
<div id="page2" class="page out-of-frame" style="background: #d94e4e;">
Other Page <br> (Click Me)
</div>
</div>
Upvotes: 1
Views: 320
Reputation: 1935
Your way looks good to me, another solution still using CSS transitions could be to use a setTimeout() and create a variable which you check to see if it has changed before allowing another click.
//set a variable
var finish = true;
$('body').click(function() {
//check to see if last transition has finished
if(finish == true){
//set variable to false
finish = false;
// start transform
$('.page').removeClass('notransition').addClass('slide');
setTimeout(function(){
finish = true;
$('.page').toggleClass('in-frame').toggleClass('out-of-frame').addClass('notransition').removeClass('slide')
}
,2000);
}
});
Upvotes: 1