Floating Overlapping Card in Flutter: How to Create a Floating Widget Between Two UI Sections

Mobile app UIs today are all about depth, smooth transitions, and visual storytelling. A design pattern that checks all those boxes is a floating overlapping card positioned half above and half below the header’s bottom edge.

You must have seen this effect everywhere from finance dashboards to onboarding screens. That floating card instantly draws attention, highlights important details, and gives your interface a premium look.

In this tutorial, you’ll learn how to recreate this pattern using Flutter, with Sun-and-Sea UI example.

Visual and Functional Benefits of Floating Overlapping Cards

1. It creates visual depth

This card appears to “float,” thanks to strategic shadows and elevation.

2. It highlights the most important content

Users’ eyes immediately land on the card’s message. Perfect for onboarding, promotions, or user highlights.

3. It connects two sections seamlessly

Instead of a harsh boundary, the card softens the transition between the header and the main content.

4. It feels modern and premium

This pattern is used in:

  • Travel apps (floating search bar)
  • Banking apps (balance summary card)
  • Health apps (daily stats)
  • Ecommerce apps (today’s recommendations)

How Floating Overlapping Cards Work in Flutter Layouts

Here’s the simple logic behind the screen:

LayerDescription
1. HeaderGradient or image section on top
2. Floating CardPositioned halfway down from the header edge
3. Body ContentBackground area such as lists, categories, or grids

Full Flutter Code (Explained Line by Line)

This is the highlight of important parts of the final code so beginners can understand it easily.

The Sea Background Layer (Scaffold + Linear Gradient)

The first important piece is the background gradient, representing a sea-like blue color theme. This background sits behind both the header and the floating card.

It’s created by wrapping the Scaffold inside a top-level Container.

Container(
  decoration: const BoxDecoration(
    gradient: LinearGradient(
      colors: [_seaColorTop, _seaColorMiddle, _seaColorBottom],
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
    ),
  ),
  child: Scaffold(
    /// Set the background color to transparent to make the blue sea gradient visible behind the card.
    backgroundColor: Colors.transparent,
    body: Stack(
      /// Set clipBehavior: Clip.none to let floating card visually “escape” the header and sit partly in the main content area.
      /// Without this, floating card gets cut off.
      clipBehavior: Clip.none,
      children: [...]
    ),
  ),
);

Why this design matters

  • The Scaffold background is transparent, so the sea gradient behind it is visible.
  • This ensures the card looks like it “floats above the sea.”
  • Using a Container outside the Scaffold allows full-screen gradient control.

Understanding gradient direction

The gradient runs from light blue at the top to deep blue at the bottom, creating a sense of depth and atmosphere.

Why use Container instead of Scaffold background?

Flutter’s Scaffold background doesn’t support complex gradients as flexibly, so this pattern creates a more powerful design structure.

The Sun Header Layer (Top Gradient Section)

Next comes the header—a warm, sun-colored background at the top of the screen.

Container(
  height: height,
  width: double.infinity,
  decoration: const BoxDecoration(
    // Sun colors: yellow at top, orange at bottom
    gradient: LinearGradient(
      colors: [_sunColorTop, _sunColorMiddle, _sunColorBottom],
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
    ),
    // Rounded bottom corners
    borderRadius: BorderRadius.only(
      bottomLeft: Radius.circular(_headerCornerRadius),
      bottomRight: Radius.circular(_headerCornerRadius),
    ),
  ),
);

The Rounded bottom corners create the exact space where the floating card can sit partially above and below.

The Floating Overlapping Card

Finally, the star of the layout: the floating overlapping card.

How it’s positioned

The simple magic formula:

final cardTopPosition = sunHeaderHeight - (cardHeight / 2);

This ensures the card always sits perfectly in the middle of the header and the content area.

This ensures the card’s center aligns exactly with the bottom of the header:

  • Top half sits inside the header
  • Bottom half sits over the sea background

This is the essence of the “floating overlapping card” effect.

Positioning inside the Stack

Positioned(
  top: cardTopPosition,
  left: _cardSidePadding,
  right: _cardSidePadding,
  child: SizedBox(height: cardHeight, child: const _FloatingCard()),
);

Styling the card

The card uses:

  • Rounded corners
  • White background
  • Subtle shadows
BoxDecoration(
  color: Colors.white,
  borderRadius: SunAndSeaLayoutWidget._cardCornerRadius, // 12
  boxShadow: [
    // Shadow makes the card look like it's floating
    BoxShadow(
      color: Colors.black.withAlpha(100),
      blurRadius: 8,
      offset: Offset(0, 4),
    ),
  ],
)

This gives the card:

  • A sense of depth
  • A floating illusion
  • A clean, modern appearance

The inside content is simple:

  • Icon
  • Text
  • Horizontal spacing
  • or anything that needs to be the main information

Perfect for welcome messages or quick actions.

Full Code Breakdown of SunAndSeaLayoutWidget

This code smartly uses:

Ratio-based sizing

  • Header = 30% of screen
  • Card = 40% of header

This improves responsiveness across devices.

Stack + Positioned

Allows overlapping without layout issues.

Clip.none

Ensures the card can visually “escape” beyond the header’s boundary.

This combination produces a layout that looks professionally designed and extremely flexible.

Here is the full code

import 'package:flutter/material.dart';

/// A beautiful layout with a sun-themed header, floating white card, and sea background.
///
/// The card sits halfway between the header and background, creating a floating effect.
class SunAndSeaLayoutWidget extends StatelessWidget {
  const SunAndSeaLayoutWidget({super.key});

  // Size ratios - these control how big each section is
  /// Header takes 30% of screen height
  static const double _headerHeightRatio = 0.3;

  /// Card height is 40% of header height
  static const double _cardHeightRatio = 0.4;

  // Spacing values
  /// Space on left and right sides of the card
  static const double _cardSidePadding = 24.0;

  /// Space inside the card around the content
  static const double _cardContentPadding = 16.0;

  /// Space between the icon and text in the card
  static const double _iconTextSpacing = 12.0;

  // Visual styling
  /// How round the header's bottom corners are
  static const double _headerCornerRadius = 32.0;

  /// How round the card corners are
  static const double _cardCornerRadius = 12.0;

  // Color palette
  /// Sky blue - top of sea gradient
  static const Color _seaColorTop = Color(0xFF87CEEB);

  /// Medium blue - middle of sea gradient
  static const Color _seaColorMiddle = Color(0xFF4682B4);

  /// Deep blue - bottom of sea gradient
  static const Color _seaColorBottom = Color(0xFF1E3A8A);

  /// Bright yellow - top of sun gradient
  static const Color _sunColorTop = Color(0xFFFFD700);

  /// Orange - middle of sun gradient
  static const Color _sunColorMiddle = Color(0xFFFFA500);

  /// Dark orange - bottom of sun gradient
  static const Color _sunColorBottom = Color(0xFFFF8C00);

  @override
  Widget build(BuildContext context) {
    // Get screen height and calculate sizes
    final screenHeight = MediaQuery.sizeOf(context).height;
    final sunHeaderHeight = screenHeight * _headerHeightRatio;
    final floatingCardHeight = sunHeaderHeight * _cardHeightRatio;

    return Container(
      decoration: const BoxDecoration(
        gradient: LinearGradient(
          colors: [_seaColorTop, _seaColorMiddle, _seaColorBottom],
          begin: Alignment.topCenter,
          end: Alignment.bottomCenter,
        ),
      ),
      child: Scaffold(
        /// Set the background color to transparent to make the blue sea gradient visible behind the card.
        backgroundColor: Colors.transparent,
        body: Stack(
          /// Set clipBehavior: Clip.none to let floating card visually “escape” the header and sit partly in the main content area.
          /// Without this, floating card gets cut off.
          clipBehavior: Clip.none,
          children: [
            // Sun header at the top
            _buildSunHeader(sunHeaderHeight),
            // White card floating between sun and sea
            _buildFloatingCard(
              sunHeaderHeight: sunHeaderHeight,
              cardHeight: floatingCardHeight,
            ),
          ],
        ),
      ),
    );
  }

  /// Creates the sun-themed header with yellow-to-orange gradient
  Widget _buildSunHeader(double height) {
    return Container(
      height: height,
      width: double.infinity,
      decoration: const BoxDecoration(
        // Sun colors: yellow at top, orange at bottom
        gradient: LinearGradient(
          colors: [_sunColorTop, _sunColorMiddle, _sunColorBottom],
          begin: Alignment.topCenter,
          end: Alignment.bottomCenter,
        ),
        // Rounded bottom corners
        borderRadius: BorderRadius.only(
          bottomLeft: Radius.circular(_headerCornerRadius),
          bottomRight: Radius.circular(_headerCornerRadius),
        ),
      ),
    );
  }

  /// Creates the white card that floats between the header and background
  Widget _buildFloatingCard({
    required double sunHeaderHeight,
    required double cardHeight,
  }) {
    // Position card so half is above header bottom edge, half is below
    final cardTopPosition = sunHeaderHeight - (cardHeight / 2);

    return Positioned(
      top: cardTopPosition,
      left: _cardSidePadding,
      right: _cardSidePadding,
      child: SizedBox(height: cardHeight, child: const _FloatingCard()),
    );
  }
}

/// The white card that displays content and floats between sun and sea.
/// This card has a white background with rounded corners and a shadow
/// to make it look like it's floating above the sea background.
class _FloatingCard extends StatelessWidget {
  const _FloatingCard();

  @override
  Widget build(BuildContext context) {
    return DecoratedBox(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(
          SunAndSeaLayoutWidget._cardCornerRadius,
        ),
        // Shadow makes the card look like it's floating
        boxShadow: [
          BoxShadow(
            color: Colors.black.withAlpha(100),
            blurRadius: 8,
            offset: const Offset(0, 4),
          ),
        ],
      ),
      child: const Padding(
        padding: EdgeInsets.all(SunAndSeaLayoutWidget._cardContentPadding),
        child: Row(
          children: [
            // Sun icon to match the theme
            Icon(Icons.sunny, color: Colors.orange, size: 24),
            SizedBox(width: SunAndSeaLayoutWidget._iconTextSpacing),
            // Welcome message
            Expanded(
              child: Text(
                'WELCOME!...',
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w600,
                  color: Colors.black87,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Screenshot on Iphone

The floating overlapping card is one of the most visually appealing and effective UI patterns commonly used in modern app design. Paired with a vibrant gradient background, a warm sun-themed header, and a perfectly centered floating card, this layout makes it easy to create a premium user experience in Flutter. This tutorial demonstrates how using gradients, layering, and ratio-based sizing leads to a responsive, polished interface.

If you’re looking to implement this kind of UI in your Flutter project, LOGIQUE is ready to help. We offer Flutter app development services designed to meet the highest standards of performance, security, and user experience. Contact our team today to start building an app that truly fits your business needs.

Scroll to top