---
title: JavaScript Transition Hooks Require done() Callback with css="false"
impact: HIGH
impactDescription: Without calling done(), JavaScript-only transitions complete immediately, skipping the animation entirely
type: gotcha
tags: [vue3, transition, javascript, animation, hooks, gsap, done-callback]
---
# JavaScript Transition Hooks Require done() Callback with css="false"
**Impact: HIGH** - When using JavaScript-only transitions (with `:css="false"`), the `@enter` and `@leave` hooks **must** call the `done()` callback to signal when the animation completes. Without calling `done()`, Vue considers the transition finished immediately, causing elements to appear/disappear without animation.
This is especially important when using animation libraries like GSAP, Anime.js, or the Web Animations API.
## Task Checklist
- [ ] When using `:css="false"`, always call `done()` in `@enter` and `@leave` hooks
- [ ] Call `done()` when your JavaScript animation completes (in the `onComplete` callback)
- [ ] Remember: `done()` is optional when CSS handles the transition, but **required** with `:css="false"`
- [ ] Use `:css="false"` to prevent CSS rules from interfering with JS animations
**Problematic Code:**
```vue
Content
```
**Correct Code:**
```vue
Content
```
## Why Use `:css="false"`?
1. **Prevents CSS interference**: Vue won't add transition classes that might conflict
2. **Slight performance benefit**: Skips CSS transition detection
3. **Clearer intent**: Makes it explicit that JS controls the animation
```vue
May have CSS conflicts
Pure JS animation
```
## Complete JavaScript Transition Example
```vue
Content
```
## Using Web Animations API
```vue
```
## Common Mistakes
```javascript
// WRONG: Calling done() immediately instead of after animation
function onEnter(el, done) {
gsap.from(el, { opacity: 0, duration: 0.5 })
done() // Called immediately - animation skipped!
}
// WRONG: Forgetting done() parameter
function onEnter(el) { // No 'done' parameter
gsap.from(el, {
opacity: 0,
onComplete: done // Error: done is not defined!
})
}
// CORRECT: Pass done to animation callback
function onEnter(el, done) {
gsap.from(el, {
opacity: 0,
duration: 0.5,
onComplete: done // Called after 0.5s
})
}
```
## Reference
- [Vue.js Transition - JavaScript Hooks](https://vuejs.org/guide/built-ins/transition.html#javascript-hooks)
- [GSAP with Vue](https://gsap.com/resources/vue/)