w3c / fxtf-drafts

Mirror of https://hg.fxtf.org/drafts
https://drafts.fxtf.org/
Other
69 stars 48 forks source link

[css-masking] Disabling masks and clipPaths when display is none #245

Open karip opened 6 years ago

karip commented 6 years ago

Safari, Firefox, Chrome and Edge allow disabling <mask> and <clipPath> by setting the display property to "none", like this: <mask id="my-mask" display="none">…</mask>

Here’s an example with a mask and a clip path in SVG. They both have display set to "none", which disables them: https://codepen.io/anon/pen/mpBdrx

The paragraph about the display property seems to be about direct rendering, but it doesn’t mention that the display property disables the mask/clipPath:

The opacity, filter and display properties do not apply to the mask element; thus, mask elements are not directly rendered even if the display property is set to a value other than none, and mask elements are available for referencing even when the display property on the mask element or any of its ancestors is set to none.

Could the spec be updated to match the current browser behavior? It should say that if the display property is "none", then the mask or clip path is disabled.

karip commented 6 years ago

Interestingly, the results are not as consistent when masks and clip paths are referenced from HTML: https://codepen.io/anon/pen/opGXyx

dirkschulze commented 6 years ago
display: none disables resource? Edge Gecko Blink WebKit
<clipPath> on HTML element N/A2 yes yes yes
<mask> on HTML element N/A2 no1 N/A2 N/A2
<clipPath> on SVG element yes yes yes yes
<mask> on SVG element yes yes yes yes

1) Rendering of element with applied mask gets disabled. 2) Not supported by the implementation.

Note: "display: none disables resource" means <clipPath> or <mask> gets ignored and do not contribute to the rendering of the clipped/masked element.

SVG 1.1 and CSS Masking state for <clipPath>:

The ‘display’ property does not apply to the ‘clipPath’ element; thus, ‘clipPath’ elements are not directly rendered even if the ‘display’ property is set to a value other than none, and ‘clipPath’ elements are available for referencing even when the ‘display’ property on the ‘clipPath’ element or any of its ancestors is set to none.

and for <mask>:

The ‘opacity’, ‘filter’ and ‘display’ properties do not apply to the ‘mask’ element; thus, ‘mask’ elements are not directly rendered even if the ‘display’ property is set to a value other than none, and ‘mask’ elements are available for referencing even when the ‘display’ property on the ‘mask’ element or any of its ancestors is set to none.

Clearly, none of the implementations follow the spec text where display shouldn't have any affect on <clipPath> or <mask>.

dirkschulze commented 6 years ago

@dbaron @longsonr Do you know why there is a difference on <mask> with display: none on HTML element in comparison to SVG elements?

dirkschulze commented 6 years ago

I suppose that for HTML, Firefox follows this description (because of display: none):

A mask reference that is an empty image (zero width or zero height), that fails to download, is not a reference to an mask element, is non-existent, or that cannot be displayed (e.g. because it is not in a supported image format) still counts as an image layer of transparent black.

If the <mask> source gets disabled by display: none then this makes sense. However, it is still inconsistent with the behavior on SVG and still different to the spec text.

Edit: Gecko issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1463336

AmeliaBR commented 5 years ago

Well, I suppose it could be useful to be able to disable/enable all uses of a mask or clipPath with display — but it would need to be implemented consistently for all use cases!

And it makes the logical model much more difficult: what about display being turned off on a parent element? What about references to clip path and mask in external files (currently only supported consistently in Firefox)?

We'd definitely have to retract the parts of SVG 2 that assign these elements a display: none !important rule in the user agent stylesheet as a way of replacing the prose about never being rendered regardless of display value.

Either way, I do think we should continue to distinguish between mask {display: none} and mask > * { display: none}, where the latter creates a valid mask that is transparent/empty and completely masks everything. (And the same for clipPath.)

svgeesus commented 5 years ago

Some of this spec wording dates from the time that we defined defs in terms of CSS:

defs {display: none }

to explain why anything inside it is not drawn directly. But things can still be drawn if referenced from outside defs.

css-meeting-bot commented 5 years ago

The SVG Working Group just discussed Disabling masks and clipPaths when display is none.

The full IRC log of that discussion <AmeliaBR> Topic: Disabling masks and clipPaths when display is none
<AmeliaBR> GitHub: https://github.com/w3c/fxtf-drafts/issues/245
<AmeliaBR> Dirk: Question is what happens when `display: none` on the <mask> or <clipPath> element itself.
<AmeliaBR> ... I uploaded some test results
<AmeliaBR> ... most browers disable the effect (as if you didn't specify a clip-path). But there are discrepancies when the effect is on HTML elements.
<AmeliaBR> ... (for browsers/effects which are supported on HTML element, `display: none` is treated as if the mask was full transparent / clipPath was empty. So the element with the effect disappears.
<AmeliaBR> Dirk: Not sure what to do with that, but for SVG effects on SVG elements, it looks like we have consistency.
<AmeliaBR> Dirk: I'd recommend standardizing that: if clip-path or mask property references an element with `display: none`, treat it the same as if it referenced a non-existant element, so no effect.
<AmeliaBR> Chris: Does this only apply if `display: none` is directly set on the element itself, or does it also imply by inheritance, e.g., from `<defs display="none">`.
<AmeliaBR> ... Because a defs is general defined as the same as display: none.
<krit> https://codepen.io/anon/pen/eomKyj
<AmeliaBR> Amelia: And it also depends on the spec text. Assuming the SVG 1 spec was implemented (display: none has no effect), we rewrote it to define these elements as having a `display: none !important` user agent style so it could be defined with CSS. But that doesn't work if display: none actually has an effect.
<krit> https://codepen.io/anon/pen/qwEKpG
<AmeliaBR> Dirk: After a quick test, it looks like an explicit `display: none` on the defs element does disable the child masks / clipPaths, in Blink and WebKit.
<AmeliaBR> Amelia: Since we have consistency between browsers, there may be content depending on it, we should change the spec to match. But we need to figure out what that is, and how to define it clearly. And whether it applies to other elements, e.g., filter effects.
<AmeliaBR> Dirk: Yes, so we need to do some comparison, e.g., for the defs issue. But I think we should focus on masks / clipPath for now.
<AmeliaBR> Amelia: The same text about display not having an effect is used in many parts of the spec. If we're going to rewrite it, we need to figure out how much need to edit.
<AmeliaBR> Dirk: Can we agree on the `display: none` for the mask and clipPath element?
<AmeliaBR> Amelia: I think we need to do more testing first. Go through all the elements in SVG that have the same rules.
<AmeliaBR> Dirk: But these aren't in the SVG spec anymore, they're in CSS Masking.
<AmeliaBR> Amelia: Are you in a rush to republish?
<AmeliaBR> Dirk: No, but we don't want edits on one spec to wait for the other.
<AmeliaBR> Amelia: But we do want to make sure that the final edits are consistent.
<AmeliaBR> Dirk: OK, so you want to get data for all SVG effects, like gradients and patterns and so on?
<AmeliaBR> Amelia: Yep. Should probably open a dedicated issue on the SVG repo. And filter effects, too.
<AmeliaBR> Dirk: There's already one on Filters (https://github.com/w3c/fxtf-drafts/issues/130)
<AmeliaBR> ... it's also on the agenda, but I guess we should also defer until we get full data.
css-meeting-bot commented 5 years ago

The CSS Working Group just discussed disabling masks/clip paths when display:none.

The full IRC log of that discussion <TabAtkins> Topic: disabling masks/clip paths when display:none
<astearns> github: https://github.com/w3c/fxtf-drafts/issues/245
<TabAtkins> AmeliaBR: I don't expect a resolution here. SVG call discussed it, we decided we needed detailed testing for browser interop
<TabAtkins> AmeliaBR: What browsers are doing doesn't match long-standing SVG text tho
<TabAtkins> AmeliaBR: this is about SVG elements that are never rendered: <*gradient>, <pattern>, <symbol>, etc
<TabAtkins> AmeliaBR: In SVG1, these all had an opaque paragraph that said 'display doesn't apply to these elements, no matter what you say it won't be rendered, and nobody what you say they'll always b eusable"
<TabAtkins> AmeliaBR: For SVG2, I was working on trying to make <use>-element shadow DOM make more sense
<TabAtkins> AmeliaBR: To make <symbol> not work directly, but work if you render it in which case 'display' does apply
<TabAtkins> AmeliaBR: Figured I could replace that prose with a UA stylesheet using !important to mean authors can't change 'display'.
<hober> q+
<TabAtkins> AmeliaBR: So say "display:none; except for <symbol> that is a direct child of a <use> shadow tree"
<TabAtkins> AmeliaBR: But turns out that in browsers, display:none *does* do something
<TabAtkins> AmeliaBR: In most browsers, if you set <mask style=display:none>, it has no effect on elements using it as a mask
<TabAtkins> AmeliaBR: This isn't in specs but happnes i nmultiple browsers.
<astearns> ack dbaron
<Zakim> dbaron, you wanted to comment on ancestors being display:none
<TabAtkins> dbaron: Interesting is whether the element has display:None *and* whether ancestor has it
<TabAtkins> dbaron: Tied to "is the thing that makes these work the presence of their DOM node, or the presence of boxes they create"
<TabAtkins> dbaron: For many browsers, these live in the box tree, and using them links to the box tree, and display:none means no boxes are generated and they fail
<TabAtkins> dbaron: So question is if that's what we want to do
<TabAtkins> dbaron: So in general display:none and ancestor display:none are not distinguishable
<TabAtkins> dbaron: So using a non-none !important value doesn't work, as it doesn't solve the ancestor problem
<astearns> ack hober
<TabAtkins> hober: Do we need to special-case these at all? In HTML <style> defaults to display:none, but you can display:block it to render it.
<TabAtkins> hober: So who cares?
<TabAtkins> dbaron: I think at this point that's not backwards compatible
<TabAtkins> chris: Used to be that you couldn't display <title> no matter what you did. But now you can.
<TabAtkins> AmeliaBR: I don't know how much will break, I didn't know that browsers were doing it anyway.
<TabAtkins> AmeliaBR: I suppose it could be useful sometimes to disable a clip-path by setting one thing on the <clipPath> rather than changing all the uses...
<TabAtkins> AmeliaBR: Practical case it breaks. Lots of inline SVGs using a gradient, so you have an inline SVG somewhere that defines those gradients. You don't want it to draw, so can you tell that SVG display:none?
<TabAtkins> AmeliaBR: Some browsers you can, some you can't, because of what dbaron mentioned earlier.
<TabAtkins> AmeliaBR: So instead you throw a pile of styles at it to make it visually hidden but not display:none
<TabAtkins> emilio: Is part of the reason it depends on the box tree-- we have a special thing for SVG that says "this frame is non-display" that doesn't do anything on its own
<TabAtkins> emilio: What that gets you is that a lot of elements don't generate a box at all when they're invalid markup - not in an SVG parent or whatever.
<TabAtkins> emilio: You need to make all those checks in two places now
<TabAtkins> AmeliaBR: So if anyone wants to help us build up that interop-testing table, that would be very helpful.
<TabAtkins> astearns: So I think you can take that back to the SVGWG with our notion that it's probably not worth special-casing, and maybe impossible.
<dbaron> Is there going to be some attempt to drive towards interop?
css-meeting-bot commented 4 years ago

The SVG Working Group just discussed Disabling masks and clipPaths when display is none.

RESOLUTION: display: none on mask/clipPath/filter element (or ancestor) should cause the graphical effect to be ignored, so there is no impact on the rendering of the SVG/HTML element the resource applies to (as if it was not specified for that element)

The full IRC log of that discussion <krit> topic: Disabling masks and clipPaths when display is none
<krit> GitHub: https://github.com/w3c/fxtf-drafts/issues/245
<krit> AmeliaBR: This one Is tricky since there is a case where the browser implementations do not match the spec.
<krit> AmeliaBR: We need to figure out what browsers are doing in the finer details.
<krit> https://github.com/w3c/fxtf-drafts/issues/245#issuecomment-390863839
<krit> krit: Did the investigation on browser support for <clipPath> and <mask>
<krit> krit: also differed between resources applied to HTML or SVG elements
<krit> krit: seems like browsers are doing more or less the same with 2 exceptions (see comment https://github.com/w3c/fxtf-drafts/issues/245#issuecomment-390863839)
<krit> krit: The CSS WG discussed the issue and let it to the SVG WG to resolve on the final behaviour.
<krit> krit: IMO there are 2 possibilities: 1) Ignore the mask/clipPath, has no effect on rendering 2) keep it unspecified
<krit> chris: This was a change we made midway at the beginning of SVG. On SVG Filters we got no output. So we said if filters are broken it has no effect.
<krit> chris: So I expect that the implementations were different.
<krit> AmeliaBR: This is not about broken masks/clipPath. It is about display: none on resource itself.
<krit> chris: at the time <defs> was described as do-not render
<krit> chris: this was not implemented as expected. It lead to implementations not rendering anything in <defs> and might be the source of what we see today.
<krit> krit: Yes, that seems the case for some browsers that do not create a rendering tree for <defs> content or elements with display none
<krit> AmeliaBR: Agree that we should follow what implementations do.
<krit> krit: So are members fine to say it should not apply to rendering the SVG/HTML element? Matching the majority of browsers but keep an option for others to implement it differently for technical reasons?
<krit> AmeliaBR: Not a fan of should instead of must but if it helps implementation to conform to the spec.
<krit> krit: I understand the concerns with the proposals but do I hear objections?
<krit> chris: no
<AmeliaBR> display: none and filters, https://github.com/w3c/csswg-drafts/issues/4213
<krit> AmeliaBR: we have a similar issue for filters. Should it work the same way?
<krit> AmeliaBR: FF seems to disable rendering of the element which seems less useful
<krit> krit: So similar results as for mask/clipPath
<krit> krit: Can we agree to let all behave the same?
<krit> AmeliaBR: yes.
<krit> AmeliaBR: as long as we have tests in place.
<krit> krit: I can definitely add tests to web platform tests
<krit> AmeliaBR: and we would need edits to the specs.
<krit> AmeliaBR: we have places where we say display does not apply and now we need to describe how it does have an affect. And we need to sync all the changes across all specs and SVG2
<krit> krit: fair point
<krit> proposed resolution: display: none on mask/clipPath/filter element should have no affect on the rendered SVG/HTML element the resource applies to as in it was not specified for that element
<AmeliaBR> proposed resolution: display: none on mask/clipPath/filter element (or ancestor) causes the graphical effect to be ignored, so there is no impact on the rendering of the SVG/HTML element the resource applies to (as if it was not specified for that element)
<krit> RSOLUTION: display: none on mask/clipPath/filter element (or ancestor) should causes the graphical effect to be ignored, so there is no impact on the rendering of the SVG/HTML element the resource applies to (as if it was not specified for that element)
<AmeliaBR> s/RSOLUTION/RESOLUTION/
<krit> trackbot, stop telcon
<trackbot> Sorry, krit, I don't understand 'trackbot, stop telcon'. Please refer to <http://www.w3.org/2005/06/tracker/irc> for help.
<krit> trackbot, end telcon