#579: CSS overflow: clip and overflow-clip-margin

Visit on Github.

Opened Dec 2, 2020

HIQaH! QaH! TAG!

I'm requesting a TAG review of CSS overflow: clip and overflow-clip-margin

[One paragraph summary of idea, ideally copy-pasted from Explainer introduction]

Adds two CSS features. The 'clip' value results in a box’s content being clipped to the box's overflow clip edge. In addition, no scrolling interface is provided, and the content can not be scrolled by the user or programmatically. The overflow-clip-margin property enables specifying how far outside the bounds an element is allowed to paint before being clipped.

  • Explainer¹: None

  • Specification URL: https://drafts.csswg.org/css-overflow-3/#valdef-overflow-clip and https://drafts.csswg.org/css-overflow-3/#propdef-overflow-clip-margin .

  • Tests: css/css-overflow/clip-001.html css/css-overflow/dynamic-visible-to-clip-001.html css/css-overflow/overflow-body-propagation-007.html css/css-overflow/overflow-body-propagation-008.html css/css-overflow/overflow-body-propagation-009.html css/css-overflow/overflow-clip-* css/css-overflow/overflow-clip-margin* css/css-overflow/overflow-clip-scroll-size.html

  • Security and Privacy self-review²: Not aware of any security or privacy implications

  • GitHub repo (if you prefer feedback filed there): None

  • Primary contacts (and their relationship to the specification):

  • Organization(s)/project(s) driving the specification: CSSWG

  • Key pieces of existing multi-stakeholder review or discussion of this specification: Continued evolution of overflow.

  • External status/issue trackers for this specification (publicly visible, e.g. Chrome Status): https://www.chromestatus.com/feature/5638444178997248

Further details:

  • I have reviewed the TAG's API Design Principles
  • Relevant time constraints or deadlines: Would love to enable this now (89) in chrome.
  • The group where the work on this specification is currently being done: CSSWG
  • Major unresolved issues with or opposition to this specification: none
  • This work is being funded by: Google

You should also know that...

[please tell us anything you think is relevant to this review]

We'd prefer the TAG provide feedback as (please delete all but the desired option):

🐛 open issues in our GitHub repo for each point of feedback

☂️ open a single issue in our GitHub repo for the entire review

💬 leave review feedback as a comment in this issue and @-notify [github usernames]

Discussions

Comment by @LeaVerou Jan 26, 2021 (See Github)

@hober and I tried to review this in our VF2F breakout today, but realized there is no explainer, and no list of use cases this is trying to address, without which review is rather difficult. Could you please add an explainer minimally containing a list of user needs and example code these are trying to address?

Comment by @sky2 Jan 26, 2021 (See Github)

Here's an explainer.

Prior to this work, it was not possible to have an element hide overflow and prevent scrolling of any kind (programmatic or user). The ‘clip’ value of ‘overflow’ adds this functionality. That is, the content is clipped to the element's padding box and scrolling of any kind is not allowed. The element is not a scroll container, and does not start a new formatting context. If you wish to start a new formatting context, you can use display: flow-root to do so.

For some uses, it is desirable to modify the clipping edge. For example, the shadow of a child element should still be visible. The ‘overflow-clip-margin’ property determines precisely how far outside the element's bounds the element is allowed to paint before being clipped. ‘Overflow-clip-margin’ may be used with ‘overflow: clip’ as well as ‘contain: paint.’

The following illustrates using ‘overflow-clip-margin’ with ‘contain: paint.’ For browsers that support overflow-clip-margin the box-shadow will be visible.

#container { width: 100px; height: 100px; contain: paint; overflow-clip-margin: 10px; } #child { width: 100px; height: 100px; box-shadow: 8px 8px blue; border: 1px solid; } </style>

<div id="container"> <div id="child"></div> </div>
Discussed Feb 15, 2021 (See Github)

Peter: why wouldn't you also want the overflow-clip-margin to work in overflow: hidden? Maybe it doesn't make sense for scroll or auto, but it does seem useful in hidden as well as clip.

Peter: The only difference between hidden and clip is that one causes a scroll container. Two high-level knobs that switch a low-level value which isn't exposed. We should expose the low-level knob "turn this thing into a scoll container". Or "look, just make me a stacking context" or "just make me a containing block."

Peter to write up a comment on this issue.

Comment by @plinss Feb 16, 2021 (See Github)

Looked at this today with @hober and have two points of feedback:

  1. It seems odd to constrain the overflow-clip-margin to the overflow: clip case. Wouldn't an additional margin also make sense in the overflow: hidden state?

  2. Adding another high-level feature that has the same behavior as another high-level feature with the exception of a low-level detail seems like an anti-pattern that CSS is guilty of in multiple places. Examples are other properties that cause the generation of stacking contexts or containing blocks, and are often used just for those side-effects (e.g. position: relative with no offsets). Many of these cases would be better served by a direct control of the lower-level feature, e.g. "make this a stacking context", or "make this a containing block". We're wondering if it doesn't make more sense to have an individual control of whether something is a scroll container and use that feature in conjunction with overflow: hidden to get the overflow: clip behavior.

Comment by @sky2 Feb 16, 2021 (See Github)

On Mon, Feb 15, 2021 at 4:33 PM Peter Linss notifications@github.com wrote:

Looked at this today with @hober https://github.com/hober and have two points of feedback:

It seems odd to constrain the overflow-clip-margin to the overflow: clip case. Wouldn't an additional margin also make sense in the overflow: hidden state?

As the "overflow: hidden" case is still scrollable (programatically), I don't think it makes sense to support the overflow-clip-margin there.

Adding another high-level feature that has the same behavior as another high-level feature with the exception of a low-level detail seems like an anti-pattern that CSS is guilty of in multiple places. Examples are other properties that cause the generation of stacking contexts or containing blocks, and are often used just for those side-effects (e.g. position: relative with no offsets). Many of these cases would be better served by a direct control of the lower-level feature, e.g. "make this a stacking context", or "make this a containing block". We're wondering if it doesn't make more sense to have an individual control of whether something is a scroll container and use that feature in conjunction with overflow: hidden to get the overflow: clip behavior.

If we were to introduce another property, then we would end up contradicting configurations. For example, 'overflow: scroll;' and 'scrollable: false' ?

-Scott

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/w3ctag/design-reviews/issues/579#issuecomment-779510583, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACHE7YRVEQSG7V5BO5NH553S7G4OZANCNFSM4ULE44UA .

Discussed May 1, 2021 (See Github)

We talked a bunch (and failed to minute) about why overflow-clip-margin doesn't apply to overflow:hidden or even overflow:visible. Tess captured the conversation in a comment on the issue.

Comment by @hober May 12, 2021 (See Github)

Hi,

@atanassov and I took a look at this today in a TAG breakout.

Looked at this today with @hober and have two points of feedback:

  1. It seems odd to constrain the overflow-clip-margin to the overflow: clip case. Wouldn't an additional margin also make sense in the overflow: hidden state?

As the "overflow: hidden" case is still scrollable (programatically), I don't think it makes sense to support the overflow-clip-margin there.

I'm afraid I don't follow. Currently, there are two differences between overflow: hidden and overflow: clip:

  1. overflow: hidden content is programmatically scrollable, whereas overflow: clip content is not
  2. overflow: clip content is clipped to the overflow clip edge whereas overflow: hidden content is clipped to the padding box.

But what if you want content that is programmatically scrollable but clipped to the overflow clip edge? It seems like you have to choose between your content looking like you want but not behaving like you want (overflow: clip), or your content acting like you want but not looking like you want (overflow: hidden).

In the degenerate case of overflow-clip-margin: 0;, the overflow clip edge just is the padding box, so I doubt there would be much of a compat hit if we made overflow: hidden clip to the overflow clip edge.

There are also use cases for overflow-clip-margin for other values of overflow, such as overflow: visible. Suppose you wanted to slowly reveal more lines of text in a box. If overflow-clip-margin affected overflow: visible boxes, you could simply animate its value from -somenumber to 0 to reveal the rest of the text without causing weird layout things to happen and without having to create an extraneous opaque element to put on top of the text (& animate a translate transform of).

Comment by @torgo Jun 2, 2021 (See Github)

Hi @sky2 we're just picking this up and I notice there hasn't been any feedback. We'll punt it to our next session in 2 weeks time. Looking forward to your thoughts.

Comment by @sky2 Jun 8, 2021 (See Github)

There is no technical reason why overflow-clip-margin couldn't be applied to hidden as well. We would need the constraint that 'hidden' is set along both axis.

As to applying overflow-clip-margin to 'overflow: visible' as well. That seems confusing, given the 'visible' implies no clipping.

Discussed Aug 9, 2021 (See Github)

Rossen: [CSS thing and chromium implementation]

Dan: notes "positive" signals in the Chromnestatus page from Safari. - good for multistakeholder.

Rossen: between Tess & I we spoke about it - how it would apply to different kinds of overflow... whether it's programmatic or through UA - eg panning. Main question - 2 types of overflow. Overflow that is scrollable or manipulatiable - and one that isn't. overflowVisible creates overflow but it's not scrollable. overflowClip if applied to visible will constrain the bounds but doesn't change the bounds. We gave reasoning why the proposal seems a bit confusing and more explanation is needed. Response has not addressed the issue - followup discussion is needed. Explainer in-lined into the comments - i don't appreciate the corner cutting. One of the main reasons for the explainer is to satisfy the criteria - use cases - how the feature addresses the use cases - what other other methods were considered to satisfy? Is this the best way to go... Plus security & Privacy... They are talking about experimentation... The chromestatus page only talks about overflow-clip.

Peter: the issue is about both.

[mozilla shipped clip but ...]

Rossen: don't see anything about margin from reading the Mozilla intent-to-ship. Somewhat misleading on Chromestatus.

Rossen: more discussion warrented. I don't think overflow clip margin is shipped.

Peter: i have concerns about clip. One of those things where we have multiple ways of doing something in CSS. This whole thing feels bolted on the side instead of fitting in well with CSS.

Rossen: what's a better approach?

Dan: because they don't provide the user needs, can you tell me what this is used in?

Peter: anything that has a specified or constrained size that is smaller than what it would need to fit its content can potentially overflow

Dan: right, so something might overflow the bounds of an iframe?

Peter: not an iframe, but a paragraph with a really long word. Something is going to have to give. The question is how doe sit give? overflow:visible you draw the contents extend outside the box. Auto or scroll you add scrollbars and don'td raw the outside but allow the user to scroll. Hidden you don't draw the outside, dont add a scroll but you could programatically still scroll it. The author can add some other mechanism to display it. This, if I'm reading correctly, you don't draw the overflow, no mechanism to scroll it whatseover, the margin basically says go ahead and draw some extra, eg. by 20px worth of the overflow but no more than that. Lets you expand the clipping region.

... One of my questions was why should the margin only apply to clip, why not over-flow hidden? Main concern was that when you overflow there's a side effect. Scroll or auto, and start scrolling, auto you only scroll if you have to, scroll you always have a scrolling mechanism. Side effect is when you get a scrolling mechanism you get a stacking contet. Everything in the box is an atomic unit for rendering. Eg. with z ordering things things can't be in the middle. It isolates that whole thing into its own rendering area. One purpose is to control overflow without generating a stacking context.

Rossen: which is not great

Peter: I think that's why you can't scroll programatically because if you don't have a stacking context you can't do all of the math, it's too complicated

Dan: where the need for the explainer would come in is talking about that, and also the use cases that make this important. Obviously it's being driven by some user need - who is it and what is the need? That justifies the added complexity and the difference between this and the case where its scrollable but only programatically

Peter: CSS has made this msitake in several places - switching some property has a main effect and a side effect, like creating a stacking context or becoming a containing block. We wind up with people doing things like making something position relative then not offsetting it, becuase it has the side effect of creating a stacking context. You want to force the thing to be a stacking context or containing block. My desire has been that these side effects should just have their own switches. If I want to force something to be a containing block or a stacking context I should be able to say containing-block: always, and not have to trick the engine into that state. I think this is one of those things where we're adding a property that people are going to use for its side effects more than its effect and we should just enable direct control over the side effect that people want.

Rossen: I think you need to give your comment more gravity and then continue the conversation

Peter: I said what I meant.. he responded with 'why not a scrollable context'.. which is not what i was saying. I'll respond.

Rossen: will leave feedback about explainer

Discussed Aug 30, 2021 (See Github)

Peter: One of my problems with this feature is that we're adding yet another clipping mechanism to the existing clip property.

Rossen: Current spec defines overflow:clip as a strict superset of clip. It also allows better integration with non-scrollable content. In the ideal case that property will overtake clip entirely and we can deprecate it.

Peter: Yes and then again, clip exists today despite its (lack of) usefulness. It seems weird to have both a clip property and a seperate overflow-clip-margin. What if overflow: clip opts in to using the clip property to define the box? Alternatively, if this is meant to fully replace clip, then that should be stated.

Rossen: So how can we resolve this from TAG POV?

Peter: The behavior makes sense but the resolutoin is certainly not satisfying. It almost feels we need another resolution type to ask for a feature to go back for additional design considerations.

... Let's discuss more at the plenary with the rest of the group.

Discussed Sep 1, 2021 (See Github)

Rossen and Peter had a breakout about this some time ago in which they convinved themselves that this isn't a great approach. Rossen closed with a comment that captures their thinking.

Comment by @atanassov Sep 14, 2021 (See Github)

@hober and I looked at this issue during our Gethen virtual f2f and the following is a summary of our discussion.

  1. There is an existing clipping mechanism in CSS provided through the clip property. This is not ideal since it only applies to absolutely positioned elements, but it exists.
  2. This proposal could be a good generalization of clipping since it could apply to most other elements and it provides better control through properties such as overflow-clip-margin.

The problems we see with the approach are:

  1. By introducing overflow:clip we are essentially adding a second mechanism for clipping to the platform
  2. There is no clear expectation if overflow-clip-margin can or should apply to clip
  3. The overflow:clip value makes clipping of scrollers impossible, a capability that is possible with clip property.

All in all, we don't see a clear path of convergence between the clip property and new clip value of overflow. We also don't see how one can become a superset of the other even if the goal was to overtake and deprecate clip property.

At this point we are closing the issue until the above could be satisfied. Thank you for working for us. Happy to review another proposal when ready.