Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

GdS's avatar
Level 26

Solved: page transitions with inertia / react

Hello everyone,

learning inertia/react as a side-project and I'm really enjoying it.

I'm struggling with page transitions inside a persisted layout. I want to apply animate.css classes (or any custom css-only animation) during Inertia page transitions, something like fadeIn/fadeOut.

I thought to register a callback on every Inertia start/finish event from inside the persisted layout component like this:

function LayoutWithPageTransition(Page) {
			const [transitioning, setTransitioning] = useState(true)
				
			useEffect(() => {
					Inertia.on('start', () => setTransitioning(true))
					Inertia.on('finish', () => setTransitioning(false))
			}, [])

			const pageTransition = useMemo(() => 
				'animate__animated' + ' ' + transitioning
					? 'animated__fadeOut' : 'animated__fadeIn'
			, [transitioning])

			return <div className={pageTransition}>
						{ Page }
			</div>
}

My approach doesn't seem to work :-)

  1. Has anyone achieved this behavior? How?
  2. Is there a better approach?

Thanks in advance, GdS

0 likes
9 replies
GdS's avatar
GdS
OP
Best Answer
Level 26

Solved: via local state and via dom manipulation

After a lot of trial and error :-D I came up with two solutions.

1. Via local state flag

As I understand, my first attempts were faulty because I didn't account for the initial events, that were fired also on Inertia first load. So, I improved the first approach using js template tags and initializing local state at null.

// solved via local state flag
function LayoutWithPageTransition(Page) {
  const [transitioning, setTransitioning] = useState(null)

  useEffect(() => {
    Inertia.on('start', () => setTransitioning(true))
    Inertia.on('finish', () => setTransitioning(false))
  }, [])

  const pageTransition = useMemo(
    () => `animate__animated ${ 
			transitioning ? 'animate__fadeOut' : 'animate__fadeIn'
	}`, [transitioning])

	return <div className={pageTransition}>{Page}</div>
}

2. Via direct dom manipulation

I initialized the transitioned element with the entry animation class, then toggled both classes in a single handler (for convenience).

// solved via direct dom manipulation
function LayoutWithPageTransition(Page) {
	const transitionedEl = useRef(null)

  const handleTransition = useCallback(() => {
    transitionedEl.current.classList.toggle('animate__fadeIn')
    transitionedEl.current.classList.toggle('animate__fadeOut')
  }, [])

  useEffect(() => {
    Inertia.on('start', handleTransition)
    Inertia.on('finish', handleTransition)
  }, [])

	return <div
        ref={transitionedEl}
        className='animate__animated animate__fadeIn'>
        {Page}
	</div>
}

Conclusion

Both solutions achieve the same effect, but I prefer using the local state flag because I'm concerned with code readability in the direct dom manipulation solution.

I would love to read some other approach and opinions.

Kindest regards, GdS

PS: Since I can already foresee myself reusing the state solution on every layout, I've built an npm package on-the-fly: use-inertia-simple-page-transition

1 like
Sakura-ne's avatar

@GdS how about when we're doing like pagination or filtering that make changes in the url the transition not triggred?

what I expect the transition run only when page changes. any solution?

GdS's avatar
Level 26

@Sakura-ne Indeed the solutions above should only run on navigation, after all it's just a matter of binding inertia events to a layout component.

If the app triggers the start and finish inertia events, the solutions above should work as expected. Otherwise you may apply the same approach with the appropriate inertia events for your use case to transition any component.

mltefive's avatar

Good job. Thanks! Could you open source on Github? I want to add @types

1 like
GdS's avatar
Level 26

@mltefive Thanks, please feel free to add @types!

I really appreciate it because I'm not confident enough to write a d.ts myself for it.

Since I was checking the repo, I updated the package to support Inertia 1.0

k2-tek's avatar

Same question, any guidance on the same logic for Vue to have page transitions?

GdS's avatar
Level 26

@secondman and @k2-tek sorry for the long delay. I haven't used laravel for a very long while (I missed it).

In pseudocode I would think of re-using the state approach above:

// layout-transition.vue
<template>
   <Transition
      enter-active-class="animate__animated animate__fadeIn"
	  leave-active-class="animate__animated animate__fadeOut"
   >
       <Layout v-show="show" />
   </Transition>
</template>

<script setup>
import { ref } from 'vue'
import { router } from '@inertiajs/vue3'
import Layout from '@layouts'

const show = ref(null)

Inertia.on('start', () => show.value = true)
Inertia.on('finish', () => show.value = false)
</script>

My educated guess though is that vue3 may offer smarter ways to accomplish this task via built-in Transition component.

Please or to participate in this conversation.