Vue

HTML

<div class="fader">
<div id="app">
  <h2>Todos:</h2>
  <ol>
    <li v-for="todo in todos">
      <label>
        <input type="checkbox"
          v-on:change="toggle(todo)"
          v-bind:checked="todo.done">

        <del v-if="todo.done">
          {{ todo.text }}
        </del>
        <span v-else>
          {{ todo.text }}
        </span>
      </label>
    </li>
  </ol>
</div>
</div>

<div class="spinner-block">
  <h1>Загрузка приложения...</h1>
  <div class="spinner"></div>
</div>

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

del {
  color: rgba(0, 0, 0, 0.3);
}

.spinner-block {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #fff;
}
.spinner {
  font-size: 50px;
  position: relative;
}
.spinner:before, .spinner:after {
  content: "";
  position: relative;
  display: block;
}
.spinner:before {
  animation: spinner 2.5s cubic-bezier(0.75, 0, 0.5, 1) infinite normal;
  width: 1em;
  height: 1em;
  background-color: #f07260;
}
.spinner:after {
  animation: shadow 2.5s cubic-bezier(0.75, 0, 0.5, 1) infinite normal;
  bottom: -.5em;
  height: .25em;
  border-radius: 50%;
  background-color: rgba(#000,0.2);
}

@keyframes spinner {
  50% {
    border-radius: 50%;
    transform: scale(0.5) rotate(360deg);
  }
  100% {
    transform: scale(1) rotate(720deg);
  }
}
@keyframes shadow {
  50% {
    transform: scale(0.5);
    background-color: rgba(#000,0.1);
  }
}

.fader {
  opacity: 0;
  transition: opacity 1s ease;
}
body.AppMounted .spinner-block { display: none; }
body.AppMounted .fader { opacity: 1; }

Vue

setTimeout(function(){ // имитация задержки сети

new Vue({
  el: "#app",
  data: {
    todos: [
      { text: "Learn JavaScript", done: false },
      { text: "Learn Vue", done: false },
      { text: "Play around in JSFiddle", done: true },
      { text: "Build something awesome", done: true }
    ]
  },
  mounted(){
  	this.$nextTick(()=>document.body.classList.add('AppMounted'));
  },
  methods: {
  	toggle: function(todo){
    	todo.done = !todo.done
    }
  }
})

}, 3000);