<div id="app">
  <div id="messages">
    <transition-group id="tt" name='list' tag="div">
      <div class="message" v-for="(message, i) in messages" :key="i">
        {{ message }}
      </div>
    </transition-group>
  </div>
</div>
body {
  background: gray;
}
#app {
  width: 100%;
  height: 90vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
#messages {
  display: flex;
  flex-flow: column;
  justify-content: flex-end;
  width: 300px;
  height: 600px;
  border: 1px solid black;
  overflow: hidden;
}
#messages {
  background: linear-gradient(180deg, skyblue, red);
  background-attachment: fixed;
}
.message {
  padding: 5px;
  border: 10px solid gray;
  position: relative;
  margin-top:-1px; /* устраняет фоновые полоски*/
}

.list-move {
  transition: transform 1s;
}

.list-enter-active, .list-leave-active {
  transition: opacity,transform 1s;
}
.list-enter, .list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}

new Vue({
  el: '#app',
  data() {
    return {
      messages: [
        'ssdf',
        'sdf',
        'ssdf',
        'sdf',
        'ssdf',
        'sdf',
        'ssdf',
        'sdf',
        'ssdf',
        'sdf',
      ]
    }
  },
  mounted() {
    let i = 0
    const s = setInterval(() => {
      this.messages.push('Привет ' + i)
      i++
      if (i > 1000) clearInterval(s)
    }, 2000)
  }
})

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

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