# How to Customize Page Transition Animations in Celeris Web: A Complete Guide

> Customize page transition animations in Celeris Web using a three-layer architecture: global settings, per-route meta, and CSS classes. Master route transitions with this complete guide.

- Repository: [Kirk Lin/celeris-web](https://github.com/kirklin/celeris-web)
- Tags: how-to-guide
- Published: 2026-03-05

---

**Celeris Web controls route transitions through a three-layer architecture: global `TransitionSetting` configuration stored in Pinia, per-route `meta.transitionName` overrides, and CSS classes mapped to `RouterTransitionConstants` like "fade" or "zoom-fade".**

Celeris Web is a modern Vue 3 admin framework that ships with built-in page transition animations. Understanding how to customize these transitions requires knowledge of the configuration types, the transition resolution logic, and the CSS class mapping. This guide walks you through the exact implementation found in the `kirklin/celeris-web` source code.

## Understanding the Transition Architecture

Page transitions in Celeris Web are governed by the [`TransitionSetting`](https://github.com/kirklin/celeris-web/blob/master/packages/web/types/src/config.ts) interface defined in [`packages/web/types/src/config.ts`](https://github.com/kirklin/celeris-web/blob/main/packages/web/types/src/config.ts). This interface controls whether transitions are enabled, which default animation to use, and auxiliary loading indicators.

The configuration exposes four key properties:

- **`shouldEnable`**: A boolean toggle that globally enables or disables transition animations (defaults to `true`).
- **`routerBasicTransition`**: The default animation name used when a route does not specify its own (defaults to `"fade"`).
- **`shouldOpenNProgress`**: Controls whether the NProgress bar appears during route changes.
- **`shouldOpenPageLoading`**: Toggles the full-page loading mask during navigation.

These settings are persisted in the Pinia app store and accessed via composables like `useTransitionSetting()`.

## Configuring Global Default Transitions

To change the default animation for the entire application, modify the `transitionSetting` field in the project settings store. The [`setProjectSetting`](https://github.com/kirklin/celeris-web/blob/master/apps/admin/src/setting/projectSetting.ts) action in [`apps/admin/src/setting/projectSetting.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/setting/projectSetting.ts) provides the API for this update.

Valid values for `routerBasicTransition` are constrained by the `RouterTransitionConstants` type: `"fade"`, `"zoom-fade"`, `"zoom-out"`, `"slide-fade"`, `"slide-fade-bottom"`, or `"scale-fade"`.

```typescript
// apps/admin/src/setting/projectSetting.ts
import { useAppStore } from '~/store'

const appStore = useAppStore()

// Change global default to "zoom-fade"
appStore.setProjectSetting({
  transitionSetting: { 
    routerBasicTransition: 'zoom-fade' 
  }
})

```

After this change, every navigation that does not specify a per-route override will use the `"zoom-fade"` CSS transition class.

## Overriding Transitions for Individual Routes

For granular control, individual route definitions can specify a `meta.transitionName` property. The framework resolves the final animation name through the [`getTransitionName`](https://github.com/kirklin/celeris-web/blob/master/apps/admin/src/layouts/transition.ts) helper in [`apps/admin/src/layouts/transition.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/layouts/transition.ts).

This function checks the route's meta fields first, then falls back to the global `routerBasicTransition` setting stored in the app state.

```typescript
// src/router/routes.ts
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: () => import('@/views/Dashboard.vue'),
    meta: { 
      transitionName: 'slide-fade'  // Custom animation for this page only
    }
  },
  {
    path: '/settings',
    name: 'Settings',
    component: () => import('@/views/Settings.vue')
    // Falls back to global routerBasicTransition
  }
]

export default createRouter({
  history: createWebHistory(),
  routes,
})

```

When navigating to `/dashboard`, the router applies the `slide-fade` CSS classes; navigating to `/settings` uses whatever value is currently set in the global `TransitionSetting`.

## Extending Available Transition Types

The allowed transition names are enumerated as constants in [[`packages/web/constants/src/themeConstants.ts`](https://github.com/kirklin/celeris-web/blob/main/packages/web/constants/src/themeConstants.ts)](https://github.com/kirklin/celeris-web/blob/master/packages/web/constants/src/themeConstants.ts).

```typescript
// packages/web/constants/src/themeConstants.ts
export const RouterTransitionConstants = {
  ZOOM_FADE: "zoom-fade",
  ZOOM_OUT: "zoom-out",
  SLIDE_FADE: "slide-fade",
  SLIDE_FADE_BOTTOM: "slide-fade-bottom",
  FADE: "fade",
  SCALE_FADE: "scale-fade",
} as const;

export type RouterTransitionConstants = keyof typeof RouterTransitionConstants;

```

To add a custom animation:

1. Extend the `RouterTransitionConstants` object with a new key-value pair.
2. Create corresponding CSS classes in your global stylesheet (e.g., [`src/assets/transition.css`](https://github.com/kirklin/celeris-web/blob/main/src/assets/transition.css)) using Vue's transition naming convention.

```css
/* src/assets/transition.css */
.my-slide-enter-active,
.my-slide-leave-active {
  transition: transform 0.4s ease, opacity 0.4s ease;
}

.my-slide-enter-from,
.my-slide-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

```

Then reference the new constant in your settings:

```typescript
// Extend the constant first, then use it
appStore.setProjectSetting({
  transitionSetting: { routerBasicTransition: 'my-slide' }
})

```

## Disabling Transitions Entirely

Set `shouldEnable` to `false` within the `TransitionSetting` object to disable all page animations instantly. When this flag is disabled, the `getTransitionName` function returns `undefined`, causing Vue to skip the `<transition>` wrapper around `<router-view>`.

```typescript
appStore.setProjectSetting({
  transitionSetting: { shouldEnable: false }
})

```

This also disables the associated `shouldOpenNProgress` and `shouldOpenPageLoading` feedback if you set those to `false` as well.

## Summary

- **Global configuration** lives in `TransitionSetting` ([`packages/web/types/src/config.ts`](https://github.com/kirklin/celeris-web/blob/main/packages/web/types/src/config.ts)) and is managed through the Pinia app store.
- **Per-route overrides** use the `meta.transitionName` property, resolved by `getTransitionName` in [`apps/admin/src/layouts/transition.ts`](https://github.com/kirklin/celeris-web/blob/main/apps/admin/src/layouts/transition.ts).
- **Animation names** are type-safe constants defined in [`packages/web/constants/src/themeConstants.ts`](https://github.com/kirklin/celeris-web/blob/main/packages/web/constants/src/themeConstants.ts) and mapped to CSS classes.
- **Customization** involves updating the store for global changes, adding route meta for specific pages, or extending the constants and CSS for new animations.

## Frequently Asked Questions

### How do I change the default page transition for all routes?

Call `appStore.setProjectSetting()` with a new `routerBasicTransition` value from the `RouterTransitionConstants` set. This updates the global default stored in the Pinia state, which `getTransitionName` uses as its fallback when no route-specific transition is defined.

### Can I disable animations on specific routes only?

Celeris Web does not provide a built-in `meta` flag to disable transitions per-route. However, you can set `meta.transitionName` to a custom value like `"none"` and modify your layout's transition logic to treat that string as a no-op, or conditionally wrap `<router-view>` based on route meta.

### Where are the transition animation CSS classes defined?

The CSS classes corresponding to `RouterTransitionConstants` (e.g., `.fade-enter-active`, `.zoom-fade-leave-to`) are defined in the project's global stylesheet, typically located in [`src/assets/transition.css`](https://github.com/kirklin/celeris-web/blob/main/src/assets/transition.css) or within the UnoCSS/Tailwind configuration. These classes handle the actual opacity, transform, and timing properties.

### How do I add a custom transition animation not in the default set?

First, add your animation name to the `RouterTransitionConstants` enum in [`packages/web/constants/src/themeConstants.ts`](https://github.com/kirklin/celeris-web/blob/main/packages/web/constants/src/themeConstants.ts). Then create the corresponding CSS transition classes using Vue's naming convention (`<name>-enter-active`, `<name>-leave-active`, etc.). Finally, use your new constant value in either the global settings or a route's `meta.transitionName`.