Skip to content

Fix Container clipBehavior not clipping decoration painting#184561

Closed
ishaquehassan wants to merge 12 commits into
flutter:masterfrom
ishaquehassan:fix/85268-container-clipbehavior-order
Closed

Fix Container clipBehavior not clipping decoration painting#184561
ishaquehassan wants to merge 12 commits into
flutter:masterfrom
ishaquehassan:fix/85268-container-clipbehavior-order

Conversation

@ishaquehassan

@ishaquehassan ishaquehassan commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Description

Container's clipBehavior property was not clipping the decoration painting because ClipPath was placed as a child of DecoratedBox in the widget tree. This meant only the child content was clipped, while the decoration itself (background color, gradient, border, shadow) was painted outside the clip boundary.

This caused visible artifacts when a Container with a rounded BoxDecoration and clipBehavior set was placed inside a parent with a solid background color: the parent's color would show through at the corners of the rounded decoration, and clipBehavior had no effect on the decoration's visual output.

Before (broken):

DecoratedBox        <-- paints decoration OUTSIDE clip
  └── ClipPath      <-- only clips child content
       └── child

After (fixed):

ClipPath            <-- clips everything: decoration + child
  └── DecoratedBox  <-- decoration painting is now clipped
       └── child

This fix swaps the order of ClipPath and DecoratedBox in Container.build() so that ClipPath wraps DecoratedBox, ensuring the clip applies to the entire visual output of the container (decoration + child content).

Shadow behavior change

Previously, boxShadow was not clipped because DecoratedBox painted it outside the ClipPath. With this fix, shadows are now also clipped to the decoration shape when clipBehavior is set. This is the correct behavior because:

  • clipBehavior defaults to Clip.none, so shadows are unaffected unless the developer explicitly opts into clipping
  • Developers who set clipBehavior expect the container's visual bounds to be constrained to the decoration shape
  • This is consistent with how ClipRRect and ClipPath work when wrapping decorated content

The shadow golden test has been updated to reflect this corrected behavior.

Fixes #85268

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@github-actions github-actions Bot added the framework flutter/packages/flutter repository. See also f: labels. label Apr 3, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modifies the Container widget to ensure that its decoration is clipped when clipBehavior is set. This is achieved by reordering the widget composition so that DecoratedBox is a child of ClipPath. Corresponding tests, including a golden test and a widget hierarchy check, have been added to verify this behavior. I have no feedback to provide.

@victorsanni victorsanni added the CICD Run CI/CD label Apr 3, 2026

@victorsanni victorsanni left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically a revert of #64362, is this intended?

Comment thread packages/flutter/test/widgets/container_test.dart Outdated
@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 3, 2026
Split BoxDecoration with shadows into two DecoratedBoxes when
clipBehavior is set: shadow paints outside the clip, background
and content paint inside. Fix typo clipBehaviour to clipBehavior
in test names and golden file names.
@ishaquehassan

Copy link
Copy Markdown
Contributor Author

Good catch on #64362! The initial commit was indeed a straight revert of that fix. Updated the approach in the latest commit to preserve shadow visibility while properly clipping the decoration background.

When clipBehavior is set and the decoration is a BoxDecoration with shadows, the decoration is now split into two DecoratedBoxes:

  • Outer DecoratedBox paints only the shadow (outside the clip, stays visible)
  • ClipPath clips to the decoration shape
  • Inner DecoratedBox paints background, border, gradient, image (inside the clip, properly clipped)

For decorations without shadows, ClipPath simply wraps the single DecoratedBox.

Also fixed the typo in test names and golden file names (clipBehaviour -> clipBehavior).

@victorsanni victorsanni requested a review from Piinks April 7, 2026 16:58
@victorsanni

Copy link
Copy Markdown
Contributor

Added @Piinks as the reviewer of #64362, the PR which this PR is reverting.

@victorsanni victorsanni added the CICD Run CI/CD label Apr 7, 2026
@victorsanni victorsanni self-requested a review April 7, 2026 17:00
@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 7, 2026

@Piinks Piinks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for contributing a solution. While this approach addresses the immediate issue of BoxDecoration shadows being clipped, it introduces several long-term maintenance and architectural concerns for the framework.

Specifically, the current implementation manually destructures and restructures BoxDecoration properties inside Container.build. This manual mapping is strictly limited to BoxDecoration and creates a maintenance risk; any future properties added to the BoxDecoration class would also need to be manually updated here to ensure they aren't lost during the split. Furthermore, this approach does not provide a fix for other common decorations, such as ShapeDecoration or custom subclasses.

A more robust and scalable solution would be to implement clipBehavior support directly within DecoratedBox and its corresponding RenderDecoratedBox. This would provide a first-class mechanism for clipping backgrounds while naturally allowing external effects like shadows to remain visible, benefiting all decoration types across the entire framework rather than just those inside a Container.

Given these concerns, I suggest we close this PR and move the technical discussion to issue #154780, which tracks the addition of clipBehavior to DecoratedBox. This will ensure we land a sustainable, framework-wide solution that maintains the integrity of the Container composition logic.

@ishaquehassan

Copy link
Copy Markdown
Contributor Author

Makes total sense @Piinks. The manual BoxDecoration split was definitely fragile and wouldn't scale to ShapeDecoration or custom types. Moving the fix to DecoratedBox/RenderDecoratedBox level is the right call.

Closing this and will pick it up on #154780 instead 👍

@ishaquehassan ishaquehassan deleted the fix/85268-container-clipbehavior-order branch April 7, 2026 20:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Container clipBehavior not working

3 participants