Skip to content
Boring Doc
BreakingHigh impactOfficial migration guidesince 2.0.0landed _various_

Clip behavior

Framework · Official source

Flutter now defaults to _not_ clip except for a few specialized widgets (such as `ClipRect`). To override the no-clip default, explicitly set `clipBehavior` in widgets constructions.

Original behavior

Flutter used to be slow because of clips. For example, the Flutter gallery app benchmark had an average frame rasterization time of about 35ms in May 2018, where the budget for smooth 60fps rendering is 16ms. By removing unnecessary clips and their related operations, we saw an almost 2x speedup from 35ms/frame to 17.5ms/frame.

New behavior

Not stated in the source.

Who is affected
Applications and packages relying on the previous behaviour or signature. Code that uses ClipRect, Card, Chip and related APIs.
Practical impact
Behaviour or API differences that can break builds or change runtime behaviour.
What action should I take?
Follow the official migration guide below, update affected call sites, run `dart fix --apply` where a fix is available, then run your tests.

Before and after (from the official guide)

dart+3−3
Before
1 await tester.pumpWidget(
2 Directionality(
3 textDirection: TextDirection.ltr,
4 child: Center(
5 child: Stack(
6− overflow: Overflow.visible,
7 children: const <Widget>[
8 SizedBox(
9− width: 100,
10− height: 100,
11 ),
12 ],
13 ),
14 ),
15 ),
16 );
After
1 await tester.pumpWidget(
2 Directionality(
3 textDirection: TextDirection.ltr,
4 child: Center(
5 child: Stack(
6+ clipBehavior: Clip.none,
7 children: const <Widget>[
8 SizedBox(
9+ width: 100.0,
10+ height: 100.0,
11 ),
12 ],
13 ),
14 ),
15 ),
16 );
Raw before / after
await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Stack(
            overflow: Overflow.visible,
            children: const <Widget>[
              SizedBox(
                width: 100,
                height: 100,
              ),
            ],
          ),
        ),
      ),
    );
await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Stack(
            clipBehavior: Clip.none,
            children: const <Widget>[
              SizedBox(
                width: 100.0,
                height: 100.0,
              ),
            ],
          ),
        ),
      ),
    );
Migration checklist0/4
Official migration guide (excerpt, © The Flutter Authors, CC BY 3.0)

You have 4 choices for migrating your code:

  1. Leave your code as is if your content does not need to be clipped (for example, none of the widgets' children expand outside their parent's boundary). This will likely have a positive impact on your app's overall performance.
  2. Add clipBehavior: Clip.hardEdge if you need clipping, and clipping without anti-alias is good enough for your (and your clients') eyes. This is the common case when you clip rectangles or shapes with very small curved areas (such as the corners of rounded rectangles).
  3. Add clipBehavior: Clip.antiAlias if you need anti-aliased clipping. This gives you smoother edges at a slightly higher cost. This is the common case when dealing with circles and arcs.
  4. Add clip.antiAliasWithSaveLayer if you want the exact same behavior as before (May 2018). Be aware that it's very costly in performance. This is likely to be only rarely needed. One case where you might need this is if you have an image overlaid on a very different background color. In these cases, consider whether you can avoid overlapping multiple colors in one spot (for example, by having the background color only present where the image is absent).

For the Stack widget specifically, if you previously used overflow: Overflow.visible, replace it with clipBehavior: Clip.none.

For the ListWheelViewport widget, if you previously specified clipToSize, replace it with the corresponding clipBehavior: Clip.none for clipToSize = false and Clip.hardEdge for clipToSize = true.

Code before migration:

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Stack(
            overflow: Overflow.visible,
            children: const &#x3C;Widget>[
              SizedBox(
                width: 100,
                height: 100,
              ),
            ],
          ),
        ),
      ),
    );

Code after migration:

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: Stack(
            clipBehavior: Clip.none,
            children: const &#x3C;Widget>[
              SizedBox(
                width: 100.0,
                height: 100.0,
              ),
            ],
          ),
        ),
      ),
    );
Migration assistantAI-generated · grounded in cited sources
AI explanations are not configured
Set AI_PROVIDER (for example to openai-compatible with a local Ollama or LM Studio endpoint) to enable grounded explanations. Everything else on this page works without an AI provider.
Official migration guide·Verified classification (95%)

Listed in the official breaking-changes index (docs.flutter.dev/release/breaking-changes).

An official announcement or migration guide documents an intended behaviour or API change. A verified source change (git diff) shows code changed but does not by itself prove a public API is breaking. AI interpretations are labelled and never used to classify a change.

Source commit
b3045439b7c0
Source last updated
Oct 21, 2026
Last synchronized
Oct 21, 2026
Publication status
published
Publication history
  • Oct 21, 2026, 8:31 PM: new → published (ingestion) — Backed by an official breaking-change/migration guide.
AI explanationAI-generated · grounded in cited sources
AI explanations are not configured
Set AI_PROVIDER (for example to openai-compatible with a local Ollama or LM Studio endpoint) to enable grounded explanations. Everything else on this page works without an AI provider.
Was this useful?