Repository navigation
Description
1. Overview
This proposal introduces new widgets, SliverClipRect and SliverClipRRect. Those widgets serve as the Sliver equivalent of the existing ClipRect and ClipRRect widgets. It clips its child sliver using a rectangle / rounded rectangle and include specific logic to handle SliverConstraints.overlap, allowing for the visual removal of content that scrolls underneath pinned headers.
2. Background & Motivation
The Problem
Currently, the ClipRect and ClipRRect widgets only support RenderBox protocol.
There are two primary scenarios where clipping is essential in the Sliver world, but currently difficult to achieve:
- Visual Styling: Applying a hard clip to a group of slivers (e.g., inside a
SliverMainAxisGrouporSliverDecoratedBox). - Overlap Management: When using pinned headers (like
SliverAppBarorSliverPersistentHeader) with transparent or semi-transparent backgrounds. By default, scrolling content paints underneath the pinned header. If the header is transparent, the scrolling content is visible, which is often undesirable. Developers need a way to "clip" the scrolling content exactly at the point where it overlaps with the pinned header.
The Solution
SliverClipRect/SliverClipRRect solve this by creating a RenderSliverClipRect/RenderSliverClipRRect. Those render object:
- Accept
CustomClipper<Rect>andCustomClipper<RRect>. - Optionally accounts for
constraints.overlapto automatically clip the portion of the child obstructed by pinned headers. - Correctly handles hit-testing, ensuring that clipped/overlapped areas do not consume touch events.
3. Design
API Surface
The API mirrors the existing ClipRect and ClipRRect but adds the clipOverlap property specific to the Sliver protocol.
class SliverClipRect extends SingleChildRenderObjectWidget {
const SliverClipRect({
super.key,
super.child,
this.clipper,
this.clipBehavior = Clip.hardEdge,
this.clipOverlap = true,
});
/// If non-null, determines which clip rectangle to use.
final CustomClipper<Rect>? clipper;
/// {@macro flutter.rendering.ClipRectLayer.clipBehavior}
final Clip clipBehavior;
/// Whether to automatically clip the portion of the child that is overlapped
/// by preceding pinned slivers.
///
/// If true, the clip rect will be adjusted to exclude the area defined by
/// [SliverConstraints.overlap].
final bool clipOverlap;
}class SliverClipRRect extends SingleChildRenderObjectWidget {
/// Creates a sliver that clips its child using a rounded rectangle.
const SliverClipRRect({
super.key,
required Widget sliver,
this.borderRadius = BorderRadius.zero,
this.clipper,
this.clipBehavior = Clip.antiAlias,
this.clipOverlap = true,
}) : super(child: sliver);
/// The border radius of the rounded corners.
///
/// Values are clamped so that horizontal and vertical radii sums do not
/// exceed width/height.
///
/// This value is ignored if [clipper] is non-null.
final BorderRadiusGeometry borderRadius;
/// If non-null, determines which clip to use.
final CustomClipper<RRect>? clipper;
/// {@macro flutter.rendering.ClipRectLayer.clipBehavior}
final Clip clipBehavior;
/// Whether to automatically clip the portion of the child that is overlapped
/// by preceding pinned slivers.
///
/// If true, the clip rect will be adjusted to exclude the area defined by
/// [SliverConstraints.overlap].
final bool clipOverlap;
}Rendering Logic
The RenderSliverClipRect/RenderSliverClipRRect calculate the clip rect/rrect based on the child's paint bounds. If clipOverlap is true, it intersects the calculated clip rect with the visible portion of the viewport (excluding the overlap defined in constraints).
4. Use Cases
Use Case 1: Grouped Decoration with Hard Edges
This scenario involves a group of slivers wrapped in a decoration (e.g., a gradient). We want to ensure that if the decoration has specific bounds, the children are clipped strictly to those bounds, ignoring overlap logic.
Use Case 2: Transparent Pinned Header
This scenario involves a design where the SliverAppBar (or pinned header) has no background (transparent), but the Scaffold has a complex background (e.g., a gradient).
Without clipping, as items scroll up, they would become visible behind the text of the SliverAppBar because the App Bar is transparent. Using SliverClipRect with clipOverlap: true (the default) ensures items disappear the moment they hit the overlap point.
Example
The example below combines the two previous use cases and works with PR #179003.
Scaffold(
body: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: <Color>[Colors.blue.shade200, Colors.blue.shade800],
),
),
child: CustomScrollView(
slivers: <Widget>[
const SliverAppBar(
pinned: true,
title: Text('Group Clipping'),
backgroundColor: Colors.transparent,
),
SliverSafeArea(
top: false,
sliver: SliverPadding(
padding: const EdgeInsets.all(16),
sliver: SliverClipRRect(
borderRadius: BorderRadius.circular(12),
sliver: DecoratedSliver(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: <Color>[Colors.blue, Colors.purple],
),
sliver: SliverMainAxisGroup(
slivers: <Widget>[
const PinnedHeaderSliver(
child: ListTile(
title: Text('Pinned Header', style: TextStyle(color: Colors.white)),
),
),
SliverClipRect(
sliver: SliverList.builder(
itemCount: 20,
itemBuilder: (BuildContext context, int index) => ListTile(
title: Text('Item $index', style: const TextStyle(color: Colors.white)),
),
),
),
],
),
),
),
),
),
],
),
),
)demo.webm
Optional proposal
In a new PR, we eventually can add : SliverClipOval, SliverClipPath and SliverRSuperellipse.
Activity
[-]Add `SliverClipRect` and `SliverClipRRect` to the Widgets Library[/-][+]Add `SliverClipRect` and `SliverClipRRect` to the widgets library[/+]tirth-patel-nc commentedon Nov 24, 2025
@manu-sncf thanks for the report. labelling it as a new proposal. thanks for contributing as well!
flutter-triage-bot commentedon Apr 14, 2026
This issue is assigned to @manu-sncf but has had no recent status updates. Please consider unassigning this issue if it is not going to be addressed in the near future. This allows people to have a clearer picture of what work is actually planned. Thanks!
flutter-triage-bot commentedon May 23, 2026
This issue is assigned to @manu-sncf but has had no recent status updates. Please consider unassigning this issue if it is not going to be addressed in the near future. This allows people to have a clearer picture of what work is actually planned. Thanks!
flutter-triage-bot commentedon Jul 1, 2026
This issue was assigned to @manu-sncf but has had no status updates in a long time. To remove any ambiguity about whether the issue is being worked on, the assignee was removed.
Add SliverClipRect and SliverClipRRect (flutter#179003)
github-actions commentedon Sep 3, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.