i have a vertical list of items, each of which can be removed. I put my items inside a transition-group and created simple opacity and transform transitions for them. The transitions on the removed elements work as expected, however if I remove an element which is not placed at the bottom, the ones beneath just jump up and take its place without any transition. I Can't find a way to target this behaviour. All I want is just that the elements below slide up smoothly.
Is there any way to achieve this effect by using css transitipms and Vue's animation hooks?
Here is a demo: https://jsfiddle.net/gcp18nq0/
Template:
<div id="app">
<div class="form">
<label for="name">Name</label>
<input type="text" id="name" v-model="name">
<button @click="addPlayer">Add player</button>
</div>
<div class="players">
<transition-group name="player">
<div class="panel" v-for="player in players" :key="player.id">
<h2>
{{ player.name}}
<span class="remove" @click="removePlayer(player.id)">Remove</span>
</h2>
</div>
</transition-group>
</div>
</div>
Script:
data() {
return {
name: "",
players: [
{id: 1, name: 'Player1'},
{id: 2, name: 'Player2'},
{id: 3, name: 'Player3'},
]
}
},
methods: {
addPlayer: function () {
//,,,,
},
removePlayer: function (playerId) {
//...
}
}
});
CSS
.form {
margin:0 auto;
width:400px;
}
.panel {
width: 400px;
margin: 10px auto;
overflow: hidden;
border: 1px solid;
text-align: center;
}
.remove {
float: right;
cursor: pointer;
text-decoration: underline;
font-size: 12px;
vertical-align: bottom
}
.player-enter,
.player-leave-to
/* .fade-leave-active below version 2.1.8 */
{
opacity: 0;
}
.player-enter {
transform: translateY(30%);
}
.player-leave-to {
transform: translateX(30%);
}
.player-enter-active,
.player-leave-active {
transition: all 1.5s;
}
.player-move {
transition: all 1.5s;
}
The only working way I found was by adding position:absolute on "player-leave-active" state but since the element collapses it changes its vertical position, which is not the desired effect. I also tried changing the height but there the elements below still jump up a bit after the height is set to 0. Im sure that this can be achieved easily with jQuery but i believe that there should be a way to do it without js.
Thank you in advance!
p.s. its my first post here, so i hope that it was explained clearly enough.
So I made some small tweaks to your fiddle: https://jsfiddle.net/gcp18nq0/1/ and hopefully that is what you looking for.
The most important change was setting display: inline-block
on the .panel
class, according to the Vue documentation:
One important note is that these FLIP transitions do not work with elements set to display: inline. As an alternative, you can use display: inline-block or place elements in a flex context.
new Vue({
el: "#app",
data() {
return {
name: "",
players: [{
id: 1,
name: 'Batman'
},
{
id: 2,
name: 'Robin'
},
{
id: 3,
name: 'Superman'
},
{
id: 4,
name: 'Spiderman'
},
]
}
},
methods: {
addPlayer: function() {
const newPlayer = {
id: this.players.length + 1,
name: this.name,
};
this.players.push(newPlayer);
},
deletePlayer: function(playerId) {
let playerToRemove = this.players.find((player) => {
return player.id === playerId;
});
let playerIndex = this.players.indexOf(playerToRemove);
this.players.splice(playerIndex, 1);
}
}
});
.form {
margin: 0 auto;
width: 400px;
}
.panel {
width: 400px;
margin: 6px auto;
overflow: hidden;
border: 1px solid;
text-align: center;
transition: all 1s;
display: inline-block;
}
.players {
position: relative;
text-align: center;
}
.remove {
float: right;
cursor: pointer;
text-decoration: underline;
font-size: 12px;
vertical-align: bottom
}
.player-enter,
.player-leave-to {
opacity: 0;
}
.player-enter {
transform: translateY(30%);
}
.player-leave-to {
transform: translateX(300%);
}
.player-leave-active {
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<div class="form">
<label for="name">Name</label>
<input type="text" id="name" v-model="name">
<button @click="addPlayer">Add player</button>
</div>
<div class="players">
<transition-group name="player" tag="div">
<div class="panel" v-for="player in players" :key="player.id">
<h2>
{{ player.name}}
<span class="remove" @click="deletePlayer(player.id)">Remove</span>
</h2>
</div>
</transition-group>
</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With