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.
Table of Contents
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
| Layer | Deskripsi |
|---|---|
| 1. Header | Bagian atas dengan warna gradasi atau gambar |
| 2. Floating Card | Diposisikan setengah di atas tepi bawah header |
| 3. Body Content | Area konten utama seperti list, grid, atau menu |
Kode Flutter Lengkap (Penjelasan Bagian Penting)
Berikut adalah penjelasan tiga bagian utama dari layout: background, header, 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.
Containersebagai 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,
),
),
),
],
),
),
);
}
}

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.
