[Blink] Implement single-axis scroll containers for sticky position [chromium/src : main]

1 view
Skip to first unread message

Free Debreuil (Gerrit)

unread,
Feb 25, 2026, 12:33:32 PM (3 days ago) Feb 25
to Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Ian Kilpatrick, Menard, Alexis, Olga Gerchikov, AyeAye, Chromium LUCI CQ, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org
Attention needed from Ian Kilpatrick, Steve Kobes and Vladimir Levin

Free Debreuil voted and added 3 comments

Votes added by Free Debreuil

Auto-Submit+1

3 comments

Patchset-level comments
File-level comment, Patchset 70 (Latest):
Free Debreuil . resolved

PTAL : )

File third_party/blink/renderer/core/layout/layout_box_model_object.h
Line 125, Patchset 52: PhysicalAxes handled_axes = kPhysicalAxesBoth) const;
Ian Kilpatrick . resolved

This method should be returning the 1D data.

Free Debreuil
Posting here for reference (from chat):
```
It might make sense to making the return structure like:
SomethingPair {
horizontal_;
veritcal_;
}
Then setting the sticky constraints per-axis.
```
Free Debreuil

Implemented as `struct StickyConstraintsData`. Please let me know if there are any issues with this approach.

File third_party/blink/renderer/core/layout/layout_box_model_object.cc
Line 751, Patchset 52: GetMutableForPainting().FirstFragment().SetStickyConstraints(new_constraint);
Ian Kilpatrick . unresolved

And setting here should only be setting each of the axis separately rather than mutating the to set the old data.

It works at the moment, but its fragile, e.g. what happens if a style change means that we'll set a different axis - but not clear the old data?

Free Debreuil

From my understanding, the old axes will need to be cleared out by querying the `ComputedStyle`. That is the intention of this code - but possibly it could be structured to explicitly clear the old axes to be clearer.

```
// Only copy over axes from the `old_constraint` that are still valid from the
// `ComputedStyle`. This handles edge cases where fragment descendants are
// reused when the scroll container parent changes axes handled.
const PhysicalAxes valid_axes = StickyConstrainedAxes(StyleRef());
```
Free Debreuil

I have updated the logic to create a new constraints object, instead of mutating the old one. Please let me know if additional changes or restructuring would make sense to do.

Open in Gerrit

Related details

Attention is currently required from:
  • Ian Kilpatrick
  • Steve Kobes
  • Vladimir Levin
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I78f82f96725f7ef6da110480c27e5077210fdc7b
Gerrit-Change-Number: 7551712
Gerrit-PatchSet: 70
Gerrit-Owner: Free Debreuil <freede...@google.com>
Gerrit-Reviewer: Free Debreuil <freede...@google.com>
Gerrit-Reviewer: Ian Kilpatrick <ikilp...@chromium.org>
Gerrit-Reviewer: Vladimir Levin <vmp...@chromium.org>
Gerrit-CC: AyeAye Python Dispatcher <android-build-ayeay...@system.gserviceaccount.com>
Gerrit-CC: David Bokan <bo...@chromium.org>
Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
Gerrit-CC: Fredrik Söderquist <f...@opera.com>
Gerrit-CC: Menard, Alexis <alexis...@intel.com>
Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
Gerrit-CC: Stephen Chenney <sche...@chromium.org>
Gerrit-CC: Steve Kobes <sko...@chromium.org>
Gerrit-Attention: Steve Kobes <sko...@chromium.org>
Gerrit-Attention: Ian Kilpatrick <ikilp...@chromium.org>
Gerrit-Attention: Vladimir Levin <vmp...@chromium.org>
Gerrit-Comment-Date: Wed, 25 Feb 2026 17:33:24 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
Comment-In-Reply-To: Ian Kilpatrick <ikilp...@chromium.org>
Comment-In-Reply-To: Free Debreuil <freede...@google.com>
satisfied_requirement
unsatisfied_requirement
open
diffy

Ian Kilpatrick (Gerrit)

unread,
Feb 25, 2026, 5:59:09 PM (3 days ago) Feb 25
to Free Debreuil, Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Menard, Alexis, Olga Gerchikov, AyeAye, Chromium LUCI CQ, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org
Attention needed from Free Debreuil, Steve Kobes and Vladimir Levin

Ian Kilpatrick added 4 comments

File third_party/blink/renderer/core/layout/layout_box_model_object.cc
Line 186, Patchset 70 (Latest): SetStickyConstraints(StickyConstraintsData{});
Ian Kilpatrick . unresolved

I think you may want to clear the per-axis sticky constraints here.

E.g. just clear one if changed now.

File third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h
Line 77, Patchset 70 (Latest):struct CORE_EXPORT StickyPositionScrollingConstraints final
Ian Kilpatrick . unresolved

What does it look like if we make StickyPositionScrollingConstraints
STACK_ALLOCATED()

and store the PerAxisData directly on the FragmentData?

It'd likely simplify the SetStickyContraints logic.

File third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.cc
Line 136, Patchset 70 (Latest): if (x_data_ && (scroll_axes & kPhysicalAxesHorizontal) != kPhysicalAxesNone) {
Ian Kilpatrick . unresolved
```suggestion
if (x_data_ && (scroll_axes & kPhysicalAxesHorizontal)) {
```

I'm fine with above if that works for you (and elsewhere)

File third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
Line 2420, Patchset 70 (Latest): sticky_descendant->SetStickyConstraints(std::move(data))) {
Ian Kilpatrick . unresolved

So the order of calling UpdateAllStickyConstraints isn't guaranteed.

E.g. a layer with a deeper depth may get called before/after the other layer.

It'd likely make the logic within SetStickyConstraints simpler if we just store the PerAxisData directly instead of having the wrapping StickyPositionConstraints object.

Open in Gerrit

Related details

Attention is currently required from:
  • Free Debreuil
  • Steve Kobes
  • Vladimir Levin
Gerrit-Attention: Free Debreuil <freede...@google.com>
Gerrit-Attention: Vladimir Levin <vmp...@chromium.org>
Gerrit-Comment-Date: Wed, 25 Feb 2026 22:59:03 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

Free Debreuil (Gerrit)

unread,
Feb 27, 2026, 6:38:52 AM (yesterday) Feb 27
to Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Ian Kilpatrick, Menard, Alexis, Olga Gerchikov, AyeAye, Chromium LUCI CQ, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org
Attention needed from Ian Kilpatrick, Steve Kobes and Vladimir Levin

Free Debreuil voted and added 6 comments

Votes added by Free Debreuil

Auto-Submit+1

6 comments

Patchset-level comments
Free Debreuil . resolved

PTAL : )

File third_party/blink/renderer/core/layout/layout_box_model_object.cc
Line 186, Patchset 70: SetStickyConstraints(StickyConstraintsData{});
Ian Kilpatrick . resolved

I think you may want to clear the per-axis sticky constraints here.

E.g. just clear one if changed now.

Free Debreuil

Good point - that is much cleaner and less error prone - and is in line with the existing behavior as well. I've updated it so that it clears per-axis as needed.

Line 751, Patchset 52: GetMutableForPainting().FirstFragment().SetStickyConstraints(new_constraint);
Ian Kilpatrick . resolved

And setting here should only be setting each of the axis separately rather than mutating the to set the old data.

It works at the moment, but its fragile, e.g. what happens if a style change means that we'll set a different axis - but not clear the old data?

Free Debreuil

From my understanding, the old axes will need to be cleared out by querying the `ComputedStyle`. That is the intention of this code - but possibly it could be structured to explicitly clear the old axes to be clearer.

```
// Only copy over axes from the `old_constraint` that are still valid from the
// `ComputedStyle`. This handles edge cases where fragment descendants are
// reused when the scroll container parent changes axes handled.
const PhysicalAxes valid_axes = StickyConstrainedAxes(StyleRef());
```
Free Debreuil

I have updated the logic to create a new constraints object, instead of mutating the old one. Please let me know if additional changes or restructuring would make sense to do.

Free Debreuil

`SetStickyConstraints` is now very simple - as the clearing logic has been moved to `LayoutBoxModelObject::StyleDidChange`.

File third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h
Line 77, Patchset 70:struct CORE_EXPORT StickyPositionScrollingConstraints final
Ian Kilpatrick . resolved

What does it look like if we make StickyPositionScrollingConstraints
STACK_ALLOCATED()

and store the PerAxisData directly on the FragmentData?

It'd likely simplify the SetStickyContraints logic.

Free Debreuil

That works nicely I think - I've updated it so that the `StickyPositionScrollingConstraints` (now STACK_ALLOCATED) is created transiently from the `PerAxisData` (now stored directly on the `FragmentData`) to preserve existing ergonomics.

File third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.cc
Line 136, Patchset 70: if (x_data_ && (scroll_axes & kPhysicalAxesHorizontal) != kPhysicalAxesNone) {
Ian Kilpatrick . resolved
```suggestion
if (x_data_ && (scroll_axes & kPhysicalAxesHorizontal)) {
```

I'm fine with above if that works for you (and elsewhere)

Free Debreuil

I think that would be a good syntax - but `PhysicalAxes` is a `using` of `base::StrongAlias`, which does not implement the `bool` operator.

Primitives such as `std::bitset` have an `any()` syntax which is nice (e.g. `(scroll_axes & kPhysicalAxesHorizontal).any()`) - but maybe non-trivial to add.

I've kept the existing syntax - no problem to switch to a different syntax that's clearer if needed.

File third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
Line 2420, Patchset 70: sticky_descendant->SetStickyConstraints(std::move(data))) {
Ian Kilpatrick . resolved

So the order of calling UpdateAllStickyConstraints isn't guaranteed.

E.g. a layer with a deeper depth may get called before/after the other layer.

It'd likely make the logic within SetStickyConstraints simpler if we just store the PerAxisData directly instead of having the wrapping StickyPositionConstraints object.

Free Debreuil

Nice - yes that is a good solution - the `StickyConstraintsData` is now assigned directly to the `PerAxisData`.

Please let me know if there's any issues with the implementation.

Open in Gerrit

Related details

Attention is currently required from:
  • Ian Kilpatrick
  • Steve Kobes
  • Vladimir Levin
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: I78f82f96725f7ef6da110480c27e5077210fdc7b
    Gerrit-Change-Number: 7551712
    Gerrit-PatchSet: 73
    Gerrit-Owner: Free Debreuil <freede...@google.com>
    Gerrit-Reviewer: Free Debreuil <freede...@google.com>
    Gerrit-Reviewer: Ian Kilpatrick <ikilp...@chromium.org>
    Gerrit-Reviewer: Vladimir Levin <vmp...@chromium.org>
    Gerrit-CC: AyeAye Python Dispatcher <android-build-ayeay...@system.gserviceaccount.com>
    Gerrit-CC: David Bokan <bo...@chromium.org>
    Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
    Gerrit-CC: Fredrik Söderquist <f...@opera.com>
    Gerrit-CC: Menard, Alexis <alexis...@intel.com>
    Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
    Gerrit-CC: Stephen Chenney <sche...@chromium.org>
    Gerrit-CC: Steve Kobes <sko...@chromium.org>
    Gerrit-Attention: Steve Kobes <sko...@chromium.org>
    Gerrit-Attention: Ian Kilpatrick <ikilp...@chromium.org>
    Gerrit-Attention: Vladimir Levin <vmp...@chromium.org>
    Gerrit-Comment-Date: Fri, 27 Feb 2026 11:38:44 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Ian Kilpatrick (Gerrit)

    unread,
    Feb 27, 2026, 2:44:19 PM (yesterday) Feb 27
    to Free Debreuil, Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Menard, Alexis, Olga Gerchikov, AyeAye, Chromium LUCI CQ, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org
    Attention needed from Free Debreuil, Steve Kobes and Vladimir Levin

    Ian Kilpatrick added 5 comments

    Patchset-level comments
    Ian Kilpatrick . resolved

    Thanks for the changes!

    File third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.cc
    Line 136, Patchset 70: if (x_data_ && (scroll_axes & kPhysicalAxesHorizontal) != kPhysicalAxesNone) {
    Ian Kilpatrick . unresolved
    ```suggestion
    if (x_data_ && (scroll_axes & kPhysicalAxesHorizontal)) {
    ```

    I'm fine with above if that works for you (and elsewhere)

    Free Debreuil

    I think that would be a good syntax - but `PhysicalAxes` is a `using` of `base::StrongAlias`, which does not implement the `bool` operator.

    Primitives such as `std::bitset` have an `any()` syntax which is nice (e.g. `(scroll_axes & kPhysicalAxesHorizontal).any()`) - but maybe non-trivial to add.

    I've kept the existing syntax - no problem to switch to a different syntax that's clearer if needed.

    File third_party/blink/renderer/core/paint/fragment_data.h
    Line 62, Patchset 73 (Latest): bool SetStickyConstraints(StickyConstraintsData constraints) {
    Ian Kilpatrick . unresolved

    Now that we have a ClearStickyConstraints, is it valid to pass a "empty" constraints here (e.g. add DCHECK?)

    File third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
    Line 547, Patchset 73 (Latest): To<LayoutBoxModelObject>(object).StickyConstraints());
    Ian Kilpatrick . unresolved

    would a HasStickyConstraints make these callsites easier?

    up to yout.

    Line 858, Patchset 73 (Latest): auto layout_constraint = box_model.StickyConstraints();
    Ian Kilpatrick . unresolved

    .nit const ?

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Free Debreuil
    • Steve Kobes
    • Vladimir Levin
    Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      Gerrit-Attention: Free Debreuil <freede...@google.com>
      Gerrit-Attention: Vladimir Levin <vmp...@chromium.org>
      Gerrit-Comment-Date: Fri, 27 Feb 2026 19:44:12 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Free Debreuil (Gerrit)

      unread,
      Feb 27, 2026, 3:48:01 PM (yesterday) Feb 27
      to Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Ian Kilpatrick, Menard, Alexis, Olga Gerchikov, AyeAye, Chromium LUCI CQ, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org
      Attention needed from Ian Kilpatrick, Steve Kobes and Vladimir Levin

      Free Debreuil voted and added 5 comments

      Votes added by Free Debreuil

      Auto-Submit+1

      5 comments

      Patchset-level comments
      File-level comment, Patchset 74 (Latest):
      Free Debreuil . resolved

      Thank you for reviewing! Please let me know if additional changes are needed.

      File third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.cc
      Line 136, Patchset 70: if (x_data_ && (scroll_axes & kPhysicalAxesHorizontal) != kPhysicalAxesNone) {
      Ian Kilpatrick . resolved
      ```suggestion
      if (x_data_ && (scroll_axes & kPhysicalAxesHorizontal)) {
      ```

      I'm fine with above if that works for you (and elsewhere)

      Free Debreuil

      I think that would be a good syntax - but `PhysicalAxes` is a `using` of `base::StrongAlias`, which does not implement the `bool` operator.

      Primitives such as `std::bitset` have an `any()` syntax which is nice (e.g. `(scroll_axes & kPhysicalAxesHorizontal).any()`) - but maybe non-trivial to add.

      I've kept the existing syntax - no problem to switch to a different syntax that's clearer if needed.

      Ian Kilpatrick

      Hmmm..... can we do something like:
      https://source.chromium.org/chromium/chromium/src/+/main:components/autofill/core/common/unique_ids.h;l=27-34?q=%22public%20base::StrongAlias%22&ss=chromium
      ?

      Free Debreuil

      Good point with the subclass. I thought that wouldn't be possible, since we weren't injecting the inherited type into `StrongAlias` with CRTP (so I assumed there would be operators that would result in the `StrongAlias` type instead of the inherited type).

      But it looks like there are no methods / operators in there that return the `StrongAlias` type - so inheritance is a nice approach.

      Have updated the definition and usage sites. Thanks!

      File third_party/blink/renderer/core/paint/fragment_data.h
      Line 62, Patchset 73: bool SetStickyConstraints(StickyConstraintsData constraints) {
      Ian Kilpatrick . resolved

      Now that we have a ClearStickyConstraints, is it valid to pass a "empty" constraints here (e.g. add DCHECK?)

      Free Debreuil

      Yes good point - have updated this with an additional `DCHECK`.

      File third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
      Line 547, Patchset 73: To<LayoutBoxModelObject>(object).StickyConstraints());
      Ian Kilpatrick . resolved

      would a HasStickyConstraints make these callsites easier?

      up to yout.

      Free Debreuil

      Yes - that is better - have updated thanks!

      Line 858, Patchset 73: auto layout_constraint = box_model.StickyConstraints();
      Ian Kilpatrick . resolved

      .nit const ?

      Free Debreuil

      Updated thank you.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Ian Kilpatrick
      • Steve Kobes
      • Vladimir Levin
      Submit Requirements:
        • requirement satisfiedCode-Coverage
        • requirement is not satisfiedCode-Owners
        • requirement is not satisfiedCode-Review
        • requirement is not satisfiedReview-Enforcement
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: chromium/src
        Gerrit-Branch: main
        Gerrit-Change-Id: I78f82f96725f7ef6da110480c27e5077210fdc7b
        Gerrit-Change-Number: 7551712
        Gerrit-PatchSet: 74
        Gerrit-Owner: Free Debreuil <freede...@google.com>
        Gerrit-Reviewer: Free Debreuil <freede...@google.com>
        Gerrit-Reviewer: Ian Kilpatrick <ikilp...@chromium.org>
        Gerrit-Reviewer: Vladimir Levin <vmp...@chromium.org>
        Gerrit-CC: AyeAye Python Dispatcher <android-build-ayeay...@system.gserviceaccount.com>
        Gerrit-CC: David Bokan <bo...@chromium.org>
        Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
        Gerrit-CC: Fredrik Söderquist <f...@opera.com>
        Gerrit-CC: Menard, Alexis <alexis...@intel.com>
        Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
        Gerrit-CC: Stephen Chenney <sche...@chromium.org>
        Gerrit-CC: Steve Kobes <sko...@chromium.org>
        Gerrit-Attention: Steve Kobes <sko...@chromium.org>
        Gerrit-Attention: Ian Kilpatrick <ikilp...@chromium.org>
        Gerrit-Attention: Vladimir Levin <vmp...@chromium.org>
        Gerrit-Comment-Date: Fri, 27 Feb 2026 20:47:55 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: Yes
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Ian Kilpatrick (Gerrit)

        unread,
        Feb 27, 2026, 11:44:50 PM (21 hours ago) Feb 27
        to Free Debreuil, Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Menard, Alexis, Olga Gerchikov, AyeAye, Chromium LUCI CQ, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org
        Attention needed from Free Debreuil, Steve Kobes and Vladimir Levin

        Ian Kilpatrick voted and added 4 comments

        Votes added by Ian Kilpatrick

        Code-Review+1

        4 comments

        Patchset-level comments
        Ian Kilpatrick . resolved

        lgtm - Thanks for your patience! This looks great.

        File third_party/blink/renderer/core/layout/layout_box_model_object.cc
        Line 545, Patchset 74 (Latest): CHECK(walk == &scroll_container_layer || is_fixed_to_view);
        Ian Kilpatrick . unresolved

        .nit scope so that `walk` doesn't leak into the rest of this long function.

        ```
        bool is_fixed_to_view = false;
        {
        const PaintLayer* walk = Layer();
        ... //etc
        }
        ```
        File third_party/blink/renderer/core/paint/fragment_data.h
        Line 88, Patchset 74 (Latest): if (!axes_to_clear || !rare_data_) {
        return has_changed;
        }
        Ian Kilpatrick . unresolved
        ```suggestion
        if (!rare_data_) {
        return false;
        }
        ```

        (no need to short-circuit axes_to_clear)

        File third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
        Line 546, Patchset 74 (Latest): return To<LayoutBoxModelObject>(object).HasStickyConstraints();
        Ian Kilpatrick . unresolved

        This could arguably be:

        ```
        if (const auto* box_model = DynamicTo<LayoutBoxModelObject>(object)) {
        return box_model->HasStickyConstraints();
        }
        return false;
        ```

        (avoiding the double convert check).

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Free Debreuil
        • Steve Kobes
        • Vladimir Levin
        Submit Requirements:
        • requirement satisfiedCode-Coverage
        • requirement satisfiedCode-Owners
        • requirement satisfiedCode-Review
        • requirement is not satisfiedNo-Unresolved-Comments
        • requirement satisfiedReview-Enforcement
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: chromium/src
        Gerrit-Branch: main
        Gerrit-Change-Id: I78f82f96725f7ef6da110480c27e5077210fdc7b
        Gerrit-Change-Number: 7551712
        Gerrit-PatchSet: 74
        Gerrit-Owner: Free Debreuil <freede...@google.com>
        Gerrit-Reviewer: Free Debreuil <freede...@google.com>
        Gerrit-Reviewer: Ian Kilpatrick <ikilp...@chromium.org>
        Gerrit-Reviewer: Vladimir Levin <vmp...@chromium.org>
        Gerrit-CC: AyeAye Python Dispatcher <android-build-ayeay...@system.gserviceaccount.com>
        Gerrit-CC: David Bokan <bo...@chromium.org>
        Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
        Gerrit-CC: Fredrik Söderquist <f...@opera.com>
        Gerrit-CC: Menard, Alexis <alexis...@intel.com>
        Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
        Gerrit-CC: Stephen Chenney <sche...@chromium.org>
        Gerrit-CC: Steve Kobes <sko...@chromium.org>
        Gerrit-Attention: Steve Kobes <sko...@chromium.org>
        Gerrit-Attention: Free Debreuil <freede...@google.com>
        Gerrit-Attention: Vladimir Levin <vmp...@chromium.org>
        Gerrit-Comment-Date: Sat, 28 Feb 2026 04:44:40 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: Yes
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Free Debreuil (Gerrit)

        unread,
        12:07 AM (21 hours ago) 12:07 AM
        to Ian Kilpatrick, Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Menard, Alexis, Olga Gerchikov, AyeAye, Chromium LUCI CQ, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org
        Attention needed from Steve Kobes and Vladimir Levin

        Free Debreuil voted and added 4 comments

        Votes added by Free Debreuil

        Auto-Submit+1

        4 comments

        Patchset-level comments
        File-level comment, Patchset 75 (Latest):
        Free Debreuil . resolved

        Thank you for reviewing.

        File third_party/blink/renderer/core/layout/layout_box_model_object.cc
        Line 545, Patchset 74: CHECK(walk == &scroll_container_layer || is_fixed_to_view);
        Ian Kilpatrick . resolved

        .nit scope so that `walk` doesn't leak into the rest of this long function.

        ```
        bool is_fixed_to_view = false;
        {
        const PaintLayer* walk = Layer();
        ... //etc
        }
        ```
        Free Debreuil

        Good point updated thank you.

        File third_party/blink/renderer/core/paint/fragment_data.h
        Line 88, Patchset 74: if (!axes_to_clear || !rare_data_) {
        return has_changed;
        }
        Ian Kilpatrick . resolved
        ```suggestion
        if (!rare_data_) {
        return false;
        }
        ```

        (no need to short-circuit axes_to_clear)

        Free Debreuil

        Yes that that is better - updated thank you.

        File third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
        Line 546, Patchset 74: return To<LayoutBoxModelObject>(object).HasStickyConstraints();
        Ian Kilpatrick . resolved

        This could arguably be:

        ```
        if (const auto* box_model = DynamicTo<LayoutBoxModelObject>(object)) {
        return box_model->HasStickyConstraints();
        }
        return false;
        ```

        (avoiding the double convert check).

        Free Debreuil

        Yes - updated thank you.

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Steve Kobes
        • Vladimir Levin
        Submit Requirements:
          • requirement satisfiedCode-Coverage
          • requirement satisfiedCode-Owners
          • requirement satisfiedCode-Review
          • requirement satisfiedReview-Enforcement
          Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
          Gerrit-MessageType: comment
          Gerrit-Project: chromium/src
          Gerrit-Branch: main
          Gerrit-Change-Id: I78f82f96725f7ef6da110480c27e5077210fdc7b
          Gerrit-Change-Number: 7551712
          Gerrit-PatchSet: 75
          Gerrit-Owner: Free Debreuil <freede...@google.com>
          Gerrit-Reviewer: Free Debreuil <freede...@google.com>
          Gerrit-Reviewer: Ian Kilpatrick <ikilp...@chromium.org>
          Gerrit-Reviewer: Vladimir Levin <vmp...@chromium.org>
          Gerrit-CC: AyeAye Python Dispatcher <android-build-ayeay...@system.gserviceaccount.com>
          Gerrit-CC: David Bokan <bo...@chromium.org>
          Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
          Gerrit-CC: Fredrik Söderquist <f...@opera.com>
          Gerrit-CC: Menard, Alexis <alexis...@intel.com>
          Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
          Gerrit-CC: Stephen Chenney <sche...@chromium.org>
          Gerrit-CC: Steve Kobes <sko...@chromium.org>
          Gerrit-Attention: Steve Kobes <sko...@chromium.org>
          Gerrit-Attention: Vladimir Levin <vmp...@chromium.org>
          Gerrit-Comment-Date: Sat, 28 Feb 2026 05:06:59 +0000
          Gerrit-HasComments: Yes
          Gerrit-Has-Labels: Yes
          Comment-In-Reply-To: Ian Kilpatrick <ikilp...@chromium.org>
          satisfied_requirement
          open
          diffy

          Free Debreuil (Gerrit)

          unread,
          12:07 AM (21 hours ago) 12:07 AM
          to Ian Kilpatrick, Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Menard, Alexis, Olga Gerchikov, AyeAye, Chromium LUCI CQ, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org
          Attention needed from Steve Kobes and Vladimir Levin

          Free Debreuil voted Commit-Queue+2

          Commit-Queue+2
          Gerrit-Comment-Date: Sat, 28 Feb 2026 05:07:07 +0000
          Gerrit-HasComments: No
          Gerrit-Has-Labels: Yes
          satisfied_requirement
          open
          diffy

          Blink W3C Test Autoroller (Gerrit)

          unread,
          12:37 AM (20 hours ago) 12:37 AM
          to Free Debreuil, Ian Kilpatrick, Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Menard, Alexis, Olga Gerchikov, AyeAye, Chromium LUCI CQ, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org
          Attention needed from Steve Kobes and Vladimir Levin

          Message from Blink W3C Test Autoroller

          Exportable changes to web-platform-tests were detected in this CL and a pull request in the upstream repo has been made: https://github.com/web-platform-tests/wpt/pull/58138.

          When this CL lands, the bot will automatically merge the PR on GitHub if the required GitHub checks pass; otherwise, ecosystem-infra@ team will triage the failures and may contact you.

          WPT Export docs:
          https://chromium.googlesource.com/chromium/src/+/main/docs/testing/web_platform_tests.md#Automatic-export-process

          Open in Gerrit

          Related details

          Attention is currently required from:
          • Steve Kobes
          • Vladimir Levin
          Submit Requirements:
          • requirement satisfiedCode-Coverage
          • requirement satisfiedCode-Owners
          • requirement satisfiedCode-Review
          • requirement satisfiedReview-Enforcement
          Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
          Gerrit-MessageType: comment
          Gerrit-Project: chromium/src
          Gerrit-Branch: main
          Gerrit-Change-Id: I78f82f96725f7ef6da110480c27e5077210fdc7b
          Gerrit-Change-Number: 7551712
          Gerrit-PatchSet: 75
          Gerrit-Owner: Free Debreuil <freede...@google.com>
          Gerrit-Reviewer: Free Debreuil <freede...@google.com>
          Gerrit-Reviewer: Ian Kilpatrick <ikilp...@chromium.org>
          Gerrit-Reviewer: Vladimir Levin <vmp...@chromium.org>
          Gerrit-CC: AyeAye Python Dispatcher <android-build-ayeay...@system.gserviceaccount.com>
          Gerrit-CC: Blink W3C Test Autoroller <blink-w3c-te...@chromium.org>
          Gerrit-CC: David Bokan <bo...@chromium.org>
          Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
          Gerrit-CC: Fredrik Söderquist <f...@opera.com>
          Gerrit-CC: Menard, Alexis <alexis...@intel.com>
          Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
          Gerrit-CC: Stephen Chenney <sche...@chromium.org>
          Gerrit-CC: Steve Kobes <sko...@chromium.org>
          Gerrit-Attention: Steve Kobes <sko...@chromium.org>
          Gerrit-Attention: Vladimir Levin <vmp...@chromium.org>
          Gerrit-Comment-Date: Sat, 28 Feb 2026 05:37:22 +0000
          Gerrit-HasComments: No
          Gerrit-Has-Labels: No
          satisfied_requirement
          open
          diffy

          Chromium LUCI CQ (Gerrit)

          unread,
          4:39 AM (16 hours ago) 4:39 AM
          to Free Debreuil, Blink W3C Test Autoroller, Ian Kilpatrick, Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Menard, Alexis, Olga Gerchikov, AyeAye, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org

          Chromium LUCI CQ submitted the change with unreviewed changes

          Unreviewed changes

          74 is the latest approved patch-set.
          The change was submitted with unreviewed changes in the following files:

          ```
          The name of the file: third_party/blink/renderer/core/paint/fragment_data.h
          Insertions: 1, Deletions: 1.

          @@ -85,7 +85,7 @@
          AssertIsFirst();

          bool has_changed = false;
          - if (!axes_to_clear || !rare_data_) {
          + if (!rare_data_) {
          return has_changed;
          }
          if ((axes_to_clear & kPhysicalAxesHorizontal) &&
          ```
          ```
          The name of the file: third_party/blink/renderer/core/layout/layout_box_model_object.cc
          Insertions: 10, Deletions: 8.

          @@ -534,15 +534,17 @@
          DCHECK(StyleRef().HasStickyConstrainedPosition());

          bool is_fixed_to_view = false;
          - // Walk up layout / paint layer tree to find if a fixed to view element exists
          - // between this element and `scroll_container_layer`.
          - const PaintLayer* walk = Layer();
          - while (walk && walk != &scroll_container_layer && !is_fixed_to_view) {
          - walk = walk->ContainingScrollContainerLayer(&is_fixed_to_view);
          + {
          + // Walk up layout / paint layer tree to find if a fixed to view element
          + // exists between this element and `scroll_container_layer`.
          + const PaintLayer* walk = Layer();
          + while (walk && walk != &scroll_container_layer && !is_fixed_to_view) {
          + walk = walk->ContainingScrollContainerLayer(&is_fixed_to_view);
          + }
          + // We should reach `scroll_container_layer` unless we hit a fixed to view
          + // ancestor (in which case we stop early).
          + CHECK(walk == &scroll_container_layer || is_fixed_to_view);
          }
          - // We should reach `scroll_container_layer` unless we hit a fixed to view
          - // ancestor (in which case we stop early).
          - CHECK(walk == &scroll_container_layer || is_fixed_to_view);

          // Skip anonymous containing blocks except for anonymous fieldset content box.
          LayoutBlock* sticky_container = StickyContainer();
          ```
          ```
          The name of the file: third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
          Insertions: 3, Deletions: 4.

          @@ -539,11 +539,10 @@
          }

          static bool NeedsStickyTranslation(const LayoutObject& object) {
          - if (!object.IsBoxModelObject()) {
          - return false;
          + if (const auto* box_model = DynamicTo<LayoutBoxModelObject>(object)) {
          + return box_model->HasStickyConstraints();
          }
          -
          - return To<LayoutBoxModelObject>(object).HasStickyConstraints();
          + return false;
          }

          static bool NeedsAnchorPositionScrollTranslation(const LayoutObject& object) {
          ```

          Change information

          Commit message:
          [Blink] Implement single-axis scroll containers for sticky position

          Adds support for independent horizontal and vertical sticky positioning
          overflow behaviors. Elements can now stick on one axis while keeping the
          other axis visible or clipped.

          Introduces the `StickyConstraintsData` struct to process partial,
          per-axis updates and merge constraints cleanly when the X and Y axes
          track different scroll container parents. This feature is gated by the
          `SingleAxisScrollContainersEnabled` runtime flag.

          Also updates the compositor reason finder to safely drop elements back
          to main-thread scrolling if multiple scroll containers are tracked, as
          the compositor currently assumes a single scroll parent.
          Fixed: 486922896
          Change-Id: I78f82f96725f7ef6da110480c27e5077210fdc7b
          Cq-Do-Not-Cancel-Tryjobs: true
          Commit-Queue: Free Debreuil <freede...@google.com>
          Reviewed-by: Ian Kilpatrick <ikilp...@chromium.org>
          Auto-Submit: Free Debreuil <freede...@google.com>
          Cr-Commit-Position: refs/heads/main@{#1591964}
          Files:
          • M third_party/blink/renderer/core/animation/view_timeline.cc
          • M third_party/blink/renderer/core/layout/fragment_builder.cc
          • M third_party/blink/renderer/core/layout/geometry/axis.h
          • M third_party/blink/renderer/core/layout/layout_box_model_object.cc
          • M third_party/blink/renderer/core/layout/layout_box_model_object.h
          • M third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
          • M third_party/blink/renderer/core/layout/physical_fragment_test.cc
          • M third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc
          • M third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.cc
          • M third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h
          • M third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
          • M third_party/blink/renderer/core/paint/fragment_data.cc
          • M third_party/blink/renderer/core/paint/fragment_data.h
          • M third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
          • M third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
          • M third_party/blink/web_tests/VirtualTestSuites
          • A third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-single-axis-basic.html
          • A third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-single-axis-dynamic.html
          • A third_party/blink/web_tests/external/wpt/css/css-position/sticky/position-sticky-single-axis-nested.html
          • A third_party/blink/web_tests/virtual/single-axis-scroll-containers/README.md
          Change size: L
          Delta: 20 files changed, 506 insertions(+), 205 deletions(-)
          Branch: refs/heads/main
          Submit Requirements:
          • requirement satisfiedCode-Review: +1 by Ian Kilpatrick
          Open in Gerrit
          Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
          Gerrit-MessageType: merged
          Gerrit-Project: chromium/src
          Gerrit-Branch: main
          Gerrit-Change-Id: I78f82f96725f7ef6da110480c27e5077210fdc7b
          Gerrit-Change-Number: 7551712
          Gerrit-PatchSet: 76
          Gerrit-Owner: Free Debreuil <freede...@google.com>
          Gerrit-Reviewer: Chromium LUCI CQ <chromiu...@luci-project-accounts.iam.gserviceaccount.com>
          Gerrit-Reviewer: Free Debreuil <freede...@google.com>
          Gerrit-Reviewer: Ian Kilpatrick <ikilp...@chromium.org>
          Gerrit-Reviewer: Vladimir Levin <vmp...@chromium.org>
          Gerrit-CC: AyeAye Python Dispatcher <android-build-ayeay...@system.gserviceaccount.com>
          Gerrit-CC: Blink W3C Test Autoroller <blink-w3c-te...@chromium.org>
          open
          diffy
          satisfied_requirement

          Blink W3C Test Autoroller (Gerrit)

          unread,
          6:14 AM (15 hours ago) 6:14 AM
          to Chromium LUCI CQ, Free Debreuil, Ian Kilpatrick, Vladimir Levin, Steve Kobes, Fredrik Söderquist, Dirk Schulze, Stephen Chenney, AyeAye Python Dispatcher, Menard, Alexis, Olga Gerchikov, AyeAye, David Bokan, chromium...@chromium.org, fmalit...@chromium.org, pdr+svgw...@chromium.org, kouhe...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-revie...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, blink-...@chromium.org, zol...@webkit.org

          Message from Blink W3C Test Autoroller

          The WPT PR for this CL has been merged upstream! https://github.com/web-platform-tests/wpt/pull/58138

          Open in Gerrit

          Related details

          Attention set is empty
          Submit Requirements:
          • requirement satisfiedCode-Coverage
          • requirement satisfiedCode-Owners
          • requirement satisfiedCode-Review
          • requirement satisfiedReview-Enforcement
          Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
          Gerrit-MessageType: comment
          Gerrit-Project: chromium/src
          Gerrit-Branch: main
          Gerrit-Change-Id: I78f82f96725f7ef6da110480c27e5077210fdc7b
          Gerrit-Change-Number: 7551712
          Gerrit-PatchSet: 76
          Gerrit-Owner: Free Debreuil <freede...@google.com>
          Gerrit-Reviewer: Chromium LUCI CQ <chromiu...@luci-project-accounts.iam.gserviceaccount.com>
          Gerrit-Reviewer: Free Debreuil <freede...@google.com>
          Gerrit-Reviewer: Ian Kilpatrick <ikilp...@chromium.org>
          Gerrit-Reviewer: Vladimir Levin <vmp...@chromium.org>
          Gerrit-CC: AyeAye Python Dispatcher <android-build-ayeay...@system.gserviceaccount.com>
          Gerrit-CC: Blink W3C Test Autoroller <blink-w3c-te...@chromium.org>
          Gerrit-CC: David Bokan <bo...@chromium.org>
          Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
          Gerrit-CC: Fredrik Söderquist <f...@opera.com>
          Gerrit-CC: Menard, Alexis <alexis...@intel.com>
          Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
          Gerrit-CC: Stephen Chenney <sche...@chromium.org>
          Gerrit-CC: Steve Kobes <sko...@chromium.org>
          Gerrit-Comment-Date: Sat, 28 Feb 2026 11:13:54 +0000
          Gerrit-HasComments: No
          Gerrit-Has-Labels: No
          satisfied_requirement
          open
          diffy
          Reply all
          Reply to author
          Forward
          0 new messages