image

14 Feb 2026

9K

35K

Mastering Flutter Page Transitions: Slide & Opacity Animations

Smooth and engaging page transitions are crucial for a delightful user experience in modern mobile applications. Flutter provides a powerful and flexible animation framework that allows developers to create sophisticated custom transitions with relative ease. This article delves into implementing custom page transitions in Flutter, specifically focusing on combining slide and opacity animations for a polished effect.

The Importance of Custom Page Transitions

Default page transitions in Flutter (like the platform-adaptive material page route) are functional, but custom animations can significantly elevate an app's aesthetic and usability. By visually guiding users through navigation changes, custom transitions reduce cognitive load and make the app feel more responsive and premium. Combining slide and opacity animations creates a dynamic, yet subtle, effect where a new page slides into view while simultaneously fading in.

Flutter's Animation Fundamentals

Before diving into page transitions, it's helpful to understand the core components of Flutter's animation system:

  • AnimationController: Manages the animation's state, including starting, stopping, and reversing. For page transitions, this is typically managed internally by Flutter.
  • Animation: An abstract class that represents a value that changes over time. Its value can be a `double`, `Offset`, `Color`, etc.
  • Tween: Defines a range for the animation (e.g., from 0.0 to 1.0, or from one `Offset` to another). It interpolates values between its `begin` and `end` properties.
  • AnimatedBuilder/AnimatedWidget: Widgets that rebuild themselves when an `Animation` changes value.

Introducing PageRouteBuilder for Custom Transitions

For custom page transitions, Flutter provides the `PageRouteBuilder` class. Unlike `MaterialPageRoute` or `CupertinoPageRoute`, `PageRouteBuilder` allows you to define both the `pageBuilder` (which builds the actual page widget) and the `transitionsBuilder` (which defines how the page animates during transition).

The `transitionsBuilder` callback provides several parameters:

  • `context`: The build context.
  • `animation`: The primary animation for the page transition (from 0.0 to 1.0 when entering, and 1.0 to 0.0 when exiting).
  • `secondaryAnimation`: The animation for the previous page (often used for parallax effects or fading out the previous page).
  • `child`: The widget built by the `pageBuilder`, which is the page currently transitioning.

Implementing Slide Transition

A slide transition makes a page appear to slide from one position to another. This is achieved using `SlideTransition` combined with an `OffsetTween`.


Widget slideTransitionBuilder(
    BuildContext context,
    Animation animation,
    Animation secondaryAnimation,
    Widget child,
) {
    var begin = Offset(1.0, 0.0); // Starts from right
    var end = Offset.zero;       // Ends at its natural position
    var curve = Curves.ease;     // Define the animation curve

    var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));

    return SlideTransition(
        position: animation.drive(tween),
        child: child,
    );
}

In this example, the page slides horizontally from the right side of the screen (`Offset(1.0, 0.0)`) to its final position (`Offset.zero`).

Implementing Opacity (Fade) Transition

An opacity transition makes a page gradually appear or disappear by changing its transparency. This is achieved using `FadeTransition` with a `Tween`.


Widget opacityTransitionBuilder(
    BuildContext context,
    Animation animation,
    Animation secondaryAnimation,
    Widget child,
) {
    var begin = 0.0; // Starts fully transparent
    var end = 1.0;   // Ends fully opaque
    var curve = Curves.easeIn;

    var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));

    return FadeTransition(
        opacity: animation.drive(tween),
        child: child,
    );
}

Here, the page fades in from fully transparent (`0.0`) to fully opaque (`1.0`).

Combining Slide and Opacity Transitions

To combine both effects, we simply nest the `FadeTransition` inside the `SlideTransition` (or vice-versa) within the `transitionsBuilder`. Both transitions will use the same `animation` controller provided by `PageRouteBuilder`.


import 'package:flutter/material.dart';

class SlideFadeTransitionPage extends PageRouteBuilder {
  final Widget page;

  SlideFadeTransitionPage(this.page)
      : super(
          pageBuilder: (context, animation, secondaryAnimation) => page,
          transitionsBuilder: (context, animation, secondaryAnimation, child) {
            // Define slide animation
            var slideBegin = Offset(1.0, 0.0); // Slides in from right
            var slideEnd = Offset.zero;
            var slideCurve = Curves.easeOut; // Smoother deceleration

            var slideTween = Tween(begin: slideBegin, end: slideEnd)
                .chain(CurveTween(curve: slideCurve));

            // Define opacity animation
            var fadeBegin = 0.0; // Fades in from transparent
            var fadeEnd = 1.0;
            var fadeCurve = Curves.easeIn; // Smoother acceleration

            var fadeTween = Tween(begin: fadeBegin, end: fadeEnd)
                .chain(CurveTween(curve: fadeCurve));

            return SlideTransition(
              position: animation.drive(slideTween),
              child: FadeTransition(
                opacity: animation.drive(fadeTween),
                child: child,
              ),
            );
          },
          transitionDuration: Duration(milliseconds: 700), // Adjust duration as needed
          reverseTransitionDuration: Duration(milliseconds: 400),
        );
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Page Transitions',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'Welcome to the Home Page!',
              style: TextStyle(fontSize: 24),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                Navigator.of(context).push(
                  SlideFadeTransitionPage(DetailPage()),
                );
              },
              child: Text('Go to Detail Page'),
            ),
          ],
        ),
      ),
    );
  }
}

class DetailPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Detail Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'This is the Detail Page!',
              style: TextStyle(fontSize: 24, color: Colors.deepPurple),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: Text('Go Back'),
            ),
          ],
        ),
      ),
    );
  }
}

Code Explanation:

  • The `SlideFadeTransitionPage` class extends `PageRouteBuilder` to encapsulate our custom transition logic.
  • Inside `transitionsBuilder`, we first define `slideTween` for the `SlideTransition`. It uses `Offset(1.0, 0.0)` as `begin` to make the new page slide in from the right.
  • Next, `fadeTween` is defined for `FadeTransition`, with `begin: 0.0` to make the page fade in from transparent.
  • We chain `CurveTween` to `Tween` to apply an easing curve to the animation, making it more natural. `Curves.easeOut` for sliding and `Curves.easeIn` for fading can create a nice overlapping effect.
  • The `SlideTransition` is the outer widget, and its `child` is the `FadeTransition`, which in turn wraps the actual `child` (the page being navigated to).
  • `transitionDuration` and `reverseTransitionDuration` define how long the forward and reverse animations take, respectively.
  • In `HomePage`, when the button is pressed, `Navigator.of(context).push()` is called with an instance of `SlideFadeTransitionPage` wrapping the `DetailPage`.

Further Customization and Considerations

  • Animation Curves: Experiment with different `Curves` (e.g., `Curves.bounceOut`, `Curves.fastOutSlowIn`) to achieve various acceleration and deceleration effects.
  • Multiple Tweens: You can apply multiple `Tween`s to the same animation controller using `chain()` to create complex motion paths.
  • Secondary Animation: The `secondaryAnimation` parameter can be used to animate the previous page. For example, you could make the previous page scale down or fade out slightly as the new page comes in.
  • Performance: While Flutter's animation system is highly optimized, be mindful of animating many complex widgets simultaneously, as it can impact performance on lower-end devices.

Conclusion

Custom page transitions with slide and opacity animations are a fantastic way to enhance the user experience in Flutter applications. By leveraging `PageRouteBuilder`, `SlideTransition`, and `FadeTransition`, developers can craft seamless and visually appealing navigation flows. The flexibility of Flutter's animation framework allows for endless possibilities, enabling you to bring your app's unique design language to life.

Related Articles

May 14, 2026

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter Countdown timers are essential in many applic

May 11, 2026

Unleashing Dynamic UIs: Flutter's Animation Prowess

Unleashing Dynamic UIs: Flutter's Animation Prowess for Slide & Scale Effects Flutter's declarative UI framework, combined with its powerful animation capabilit

May 11, 2026

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy A well-designed Product Detail Page (PDP) is