#app
  transition(name="page", :duration="1300")
    .page(:is="page" @change-page="onChangePage")
    
script#start(type="text/x-template")
  .start
    .inner 
      h1.title.enter-1 Page Transition Demo
      .button-wrapper.enter-2
        button.button.button-start(
          type="button" 
          @click="$emit('change-page', 'next')"
        ) 
          span.button-text Start!
    
script#next(type="text/x-template")
  .next
    .inner
      h1.title.enter-1 You may want to use...
      ul.next-list
        li.enter-2 <transition> built-in component of Vue.js
        li.enter-3 CSS Transition/Animation for simple animation combinations
        li.enter-4 JavaScript hooks for complex animation      
      .button-wrapper.enter-5
        button.button.button-next(
          type="button"
          @click="$emit('change-page', 'start')"
        )
          span.button-text Back
View Compiled
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  overflow: hidden;
  font-size: 24px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif
}

button {
  font-family: inherit;
  font-size: inherit;
}

.page {
  overflow-y: auto;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  padding: 50px 0;
  text-align: center;
}

.inner {
  margin: auto;
  height: 100%;
  width: 700px; 
}

.title {
  margin-bottom: 50px;
  font-size: 48px;
}

.button-wrapper {
  margin-top: 50px;
}

.button {
  position: relative;
  height: 60px;
  width: 300px;
  background-color: transparent;
  border: 3px solid #fff;
  color: #fff;
  cursor: pointer;
  transition: color 150ms cubic-bezier(0.1, 0.7, 0.6, 0.9); 
  
  &::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    top: 0;
    background-color: #fff;
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 150ms cubic-bezier(0.1, 0.7, 0.6, 0.9);
  }
  
  &:hover {
    &.button-start {
      color: #f1b00f;
    }
    
    &.button-next {
      color: #c598af;
    }
    
    &::before {
      transform: scaleX(1)
    }
  }
  
  &-text {
    position: relative;
  }
}

.start {
  background-color: #f1b00f;
  color: #fff;
}

.next {
  background-color: #c598af;
  color: #fff;
  
  &-list {
    list-style: disc;
    text-align: left;
    margin: auto;
    width: 430px;
    line-height: 1.6;
  }
}

/* Transition
 -----------------------------*/
@for $i from 1 through 5 {
  $enter-delay: 450ms;
  
  .page-enter-active {
    overflow: hidden;
    transition: transform $enter-delay cubic-bezier(0.4, 0.1, 0.7, 0.95);
    
    .enter-#{$i} {
      transition: 300ms cubic-bezier(0.1, 0.7, 0.6, 0.9);
      transition-property: opacity, transform;
      transition-delay: #{120ms * $i + $enter-delay};
    }
  }
  
  .page-enter {
    transform: translateX(100%);
    
    .enter-#{$i} {
      opacity: 0;
      transform: translateX(50px);
    }
  }
  
  .page-leave-active {
    display: block;
  }
}
View Compiled
Vue.config.productionTip = false

Vue.component('start', {
  template: '#start'
})

Vue.component('next', {
  template: '#next'
})

new Vue({
  el: '#app',
  
  data: {
    page: 'start'
  },
  
  methods: {
    onChangePage(to) {
      this.page = to
    }
  }
})

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js