Floating Overlapping Card di Flutter: Cara Membuat Widget Mengambang di Antara Dua Bagian Tampilan

UI aplikasi mobile modern semakin menekankan kedalaman (depth), transisi halus, dan visual yang bercerita. Salah satu pola desain yang memenuhi semua kriteria tersebut adalah floating overlapping card—sebuah widget berupa card yang terlihat mengambang dan berada setengah di atas dan setengah di bawah tepi bawah header.

Efek ini banyak digunakan di berbagai aplikasi: dashboard keuangan, onboarding, perjalanan, kesehatan, dan lain-lain. Widget card yang mengambang ini langsung menarik perhatian pengguna, menonjolkan informasi penting, dan memberikan kesan premium pada tampilan.

Dalam tutorial ini, Anda akan mempelajari cara membuat pola UI tersebut menggunakan Flutter, dengan contoh sederhana Sun-and-Sea UI yang indah.

Manfaat Visual dan Fungsional Floating Overlapping Card

1. Menciptakan kedalaman visual

Widget card terlihat “mengambang” berkat penggunaan bayangan dan penempatan elemen yang tepat.

2. Menonjolkan informasi penting

Mata pengguna akan langsung tertuju pada widget card tersebut—ideal untuk onboarding, promosi, atau highlight pengguna.

3. Menghubungkan dua bagian UI secara mulus

Alih-alih peralihan yang kaku, widget card ini membuat transisi antara header dan konten utama terasa lebih lembut dan natural.

4. Terlihat modern dan premium

Pola ini populer di aplikasi:

  • Aplikasi perjalanan (floating search bar)
  • Aplikasi perbankan (summary saldo)
  • Aplikasi kesehatan (statistik harian)
  • E-commerce (rekomendasi hari ini)

Cara Kerja Floating Overlapping Card dalam Layout Flutter

LayerDeskripsi
1. HeaderBagian atas dengan warna gradasi atau gambar
2. Floating CardDiposisikan setengah di atas tepi bawah header
3. Body ContentArea konten utama seperti list, grid, atau menu

Kode Flutter Lengkap (Penjelasan Bagian Penting)

Berikut adalah penjelasan tiga bagian utama dari layout: backgroundheader, dan floating card

Layer Background (Scaffold + Linear Gradient)

Lapisan pertama adalah gradasi biru laut yang menjadi latar belakang seluruh layar. Efek gradasi ini dibuat dengan membungkus Scaffold di dalam sebuah Container.

Container(
  decoration: const BoxDecoration(
    gradient: LinearGradient(
      colors: [_seaColorTop, _seaColorMiddle, _seaColorBottom],
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
    ),
  ),
  child: Scaffold(
    /// Set Scaffold background color menjadi transparan agar gradasi biru laut terlihat.
    backgroundColor: Colors.transparent,
    body: Stack(
      /// Set clipBehavior: Clip.none untuk membuat floating card terlihat seolah mengambang dan terlepas dari header. Tanpa ini floating card akan terpotong pada bagian bawah.
      clipBehavior: Clip.none,
      children: [...]
    ),
  ),
);

Mengapa desain ini penting?

  • Scaffold dibuat transparan, sehingga gradasi biru laut tetap terlihat di belakang widget card.
  • Container sebagai parent Scaffold membuat gradasi biru laut sepenuh layar.

Memahami arah gradasi warna

Efek gradasi dari warna light blue pada bagian atas layar sampai dengan deep blue pada bagian bawah layar menciptakan kesan kedalaman dan suasana laut.

Kenapa tidak langsung pakai background Scaffold?

Background Scaffold tidak support untuk background warna gradasi sepenuh layar.

Layer Sun Header (Bagian Atas Gradasi Kuning-Oranye)

Bagian ini adalah header dengan tema matahari, menggunakan gradasi warna kuning hingga oranye serta sudut bawah yang melengkung.

Container(
  height: height,
  width: double.infinity,
  decoration: const BoxDecoration(
    // Warna gradasi matahari: kuning di atas, oranye di bawah
    gradient: LinearGradient(
      colors: [_sunColorTop, _sunColorMiddle, _sunColorBottom],
      begin: Alignment.topCenter,
      end: Alignment.bottomCenter,
    ),
    // Sudut bawah yang melengkung
    borderRadius: BorderRadius.only(
      bottomLeft: Radius.circular(_headerCornerRadius),
      bottomRight: Radius.circular(_headerCornerRadius),
    ),
  ),
);

Floating Overlapping Card (Widget Utama Layout Ini)

Bagian paling menarik dari layout adalah widget card putih yang mengambang.

Rumus penempatan

final cardTopPosition = sunHeaderHeight - (cardHeight / 2);

Rumus ini memastikan:

  • Setengah bagian atas widget card masuk ke dalam header
  • Setengah bagian bawah widget card masuk ke area main content
  • Titik tengah selalu tepat berada pada tepi bawah header

Menggunakan Positioned dalam Stack

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

Styling widget card

BoxDecoration(
  color: Colors.white,
  borderRadius: SunAndSeaLayoutWidget._cardCornerRadius,
  boxShadow: [
    BoxShadow(
      color: Colors.black.withAlpha(100),
      blurRadius: 8,
      offset: Offset(0, 4),
    ),
  ],
)

Widget card ini memiliki:

  • Sudut melengkung
  • Background putih
  • Shadow lembut
  • Tampilan bersih dan modern

Isinya dapat berupa icon, teks, ataupun informasi penting lainnya.

Code Lengkap SunAndSeaLayoutWidget

Kode Anda Menggunakan 3 Konsep Utama:

Ratio-based sizing (pengaturan ukuran berdasarkan rasio)

  • Header = 30% dari tinggi layar
  • Card = 40% dari tinggi header

Ini membuat layout responsif di semua ukuran layar.

Stack + Positioned

Structure ini memungkinkan:

  • Widget saling overlap
  • Card bisa muncul setengah di header, setengah di background
  • Fleksibilitas tinggi dalam penentuan posisi

clipBehavior: Clip.none

Tanpa ini, floating card akan terpotong oleh Stack.
Dengan Clip.none, card bisa “keluar” dari batas header dan benar-benar terlihat mengambang.

Gabungan dari teknik-teknik ini membuat UI Anda terlihat profesional dan modern.

Berikut adalah kode lengkapnya 

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

Floating overlapping card adalah salah satu pola UI yang paling menarik secara visual dan sering digunakan dalam desain aplikasi modern. Dengan kombinasi gradasi warna di latar belakang, header bertema matahari, dan widget card yang mengambang di posisi yang sempurna, Anda dapat menciptakan pengalaman pengguna yang premium di Flutter. Tutorial ini menunjukkan bagaimana penggunaan gradasi, layering, dan ukuran berbasis rasio dapat menghasilkan tampilan yang responsif, rapi, dan profesional.

Jika Anda ingin menerapkan UI seperti ini dalam proyek Flutter Anda, LOGIQUE siap membantu. Kami menyediakan jasa pembuatan aplikasi Flutter yang dirancang untuk memenuhi standar performa, keamanan, dan pengalaman pengguna terbaik. Hubungi tim kami untuk mulai mengembangkan aplikasi yang sesuai dengan kebutuhan Anda.

Scroll to top