Bug 23113

Summary: Layer content inside HTML in SVG foreignObject renders in the wrong place
Product: WebKit Reporter: Simon Fraser (smfr) <simon.fraser>
Component: SVGAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: agafvv, apple, artem.babich, bdakin, bernhard, b.houdusse, bramus, bruckner.roman, colsen.sean, comexk, eda-qa, eric, esprehn, fabien.snauwaert+webkit, fmalita, fred.wang, hyatt, info, jay, jcubic, john.j.reilly, karlcow, kbr, kdolan, kerry, knorton, mark, mattgwwalker, mokone91, olivier_lamothe, pnormand, rezunenkotimur, rjohnston, rob, sabouhallawa, sheinlinphyo, silvan.muehlemann, silviapfeiffer1, simon.fraser, sinish, terrence, thorton, vikramhegden, w07m, webkit-bug-importer, william.spitzer, xiao.hk1997, xidorn-webkit, zalan, zimmermann
Priority: P2 Keywords: BrowserCompat, CanvaBug, InRadar
Version: 528+ (Nightly build)   
Hardware: Mac   
OS: OS X 10.5   
See Also: https://bugs.webkit.org/show_bug.cgi?id=165516
https://bugs.webkit.org/show_bug.cgi?id=213788
https://bugs.webkit.org/show_bug.cgi?id=270317
https://bugs.webkit.org/show_bug.cgi?id=149388
Bug Depends on: 90738    
Bug Blocks:    
Attachments:
Description Flags
Testcase
none
Work-in-progress patch
none
Another work-in-progress patch
none
foreignObject and positioning bug
none
Showing defect using scrolling section none

Description Simon Fraser (smfr) 2009-01-04 20:17:43 PST
When HTML content inside an SVGForeignObject gets a RenderLayer for whatever reason, then it renders in the wrong place.

I guess this happens because the RenderLayer hierarchy does not extend through the SVG renderers, so the HTML RenderLayers have no knowledge of the SVG transforms etc.
Comment 1 Simon Fraser (smfr) 2009-01-04 20:18:13 PST
Created attachment 26421 [details]
Testcase
Comment 2 vikram hegde 2009-02-25 23:07:38 PST
Hi,
i have found out that in the html code if i remove the sytle attribute for div element the text inside the div element is renderred in the correct place and the bug is not seen> also if i change the opacity value of div to 1.0 the bug is not seen.

It looked strange. could anyone put more light on this.
Comment 3 Simon Fraser (smfr) 2009-02-25 23:24:13 PST
Yes, the problem is that the RenderSVGForeignObject does not have a RenderLayer, so that layers inside the HTML are not positioned correctly.
Comment 4 vikram hegde 2009-02-26 00:41:57 PST
Actually i dont think its the case in every html object, the bug is seen only when we apply opacity, if we remove opacity everrything works perfectly fine.And also other html elements are getting rendered properly.

could you please brief more on this.
Comment 5 Simon Fraser (smfr) 2009-02-26 08:42:35 PST
Opacity makes a RenderLayer in the HTML. That RenderLayer is parented currently in the SVGRoot's layer, not the foreignObject's layer, so ends up in completely the wrong places.

Are you planning to work on this bug?
Comment 6 vikram hegde 2009-02-26 10:26:59 PST
(In reply to comment #5)
> Opacity makes a RenderLayer in the HTML. That RenderLayer is parented currently
> in the SVGRoot's layer, not the foreignObject's layer, so ends up in completely
> the wrong places.
> Are you planning to work on this bug?

yes i am planing to work on this bug.which would be the better place or approach to resolve the issue?
Comment 7 Simon Fraser (smfr) 2009-02-26 10:30:07 PST
I have a hacked-up patch that I can attach when I get home. It has a number of issues, though.
Comment 8 Simon Fraser (smfr) 2009-02-27 09:37:02 PST
Created attachment 28077 [details]
Work-in-progress patch

Here's a work-in-progress patch. There are a number of things wrong with it:
* The RenderBox.cpp change needs cleaning up (see bug 23111 for some comments about that)
* The way that the layer paints with the ancestor transform seems weird
* Some SVG layout tests are broken
Comment 9 Simon Fraser (smfr) 2009-02-27 09:37:37 PST
Note that if you fix this bug, you'll probably fix bug 23111 too.
Comment 10 Nikolas Zimmermann 2010-07-08 02:19:28 PDT
Changed component to SVG, so it shows up in my all-svg-bugs search.
Comment 11 Silvia Pfeiffer 2010-08-12 01:59:12 PDT
I have a similar problem, where I have a foreignObject in a <defs> and cannot apply a mask to it, because the foreignObject keeps getting rendered. I hope it can be fixed with the same fixes - if not, I can open a new bug.


<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="270px" width="480px">
  <mask id="c1" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse">
    <circle id="circle" cx="240" cy="135" r="135" fill="white"/>
  </mask>
  <defs>
    <g id="videoGroup">
      <foreignObject width="100%" height="100%">
        <body xmlns="http://www.w3.org/1999/xhtml">
          <video id="vid" class="target" height="270px" width="480px" controls="controls" autoplay="autoplay">
              <source src="http://annodex.net/~silvia/itext/chocolate_rain/chocolate_rain.mp4"  type="video/mp4"/>
              <source src="http://annodex.net/~silvia/itext/chocolate_rain/chocolate_rain.ogv"  type="video/ogg"/>
          </video>        
        </body>
      </foreignObject>
    </g>
  </defs>
  <use xlink:href="#videoGroup" mask="url(#c1)"/>
</svg>
Comment 12 Eric Seidel (no email) 2010-08-12 05:51:49 PDT
The foreignObject inside a defs sounds like a separate bug, please file. :)

CCing Ken, because his latest work needs to be aware of the possible interaction issues between layers and SVG.
Comment 13 Silvia Pfeiffer 2010-08-12 06:07:07 PDT
OK, done, see https://bugs.webkit.org/show_bug.cgi?id=43911
Comment 14 Tim Horton 2011-07-28 15:44:07 PDT
<rdar://problem/8912810>
Comment 15 Florin Malita 2012-02-03 13:55:39 PST
Created attachment 125408 [details]
Another work-in-progress patch

I've updated Simon's patch and it works pretty well for the issue at hand (still a couple of rough edges to fix).

There's a major limitation with this approach though: the SVG paint context is lost with a separate layer - hence masks, filters, etc. on the FO's ancestor elements are not applied to embedded content.

I can't think of a way around this that doesn't involve some major RenderLayer surgery, so any ideas/comments are much appreciated.
Comment 16 Simon Fraser (smfr) 2012-02-04 09:51:14 PST
(In reply to comment #15)

> I can't think of a way around this that doesn't involve some major RenderLayer surgery, so any ideas/comments are much appreciated.

I don't think there is an easy way. We'll probably have to glue RenderLayers together across foreignObject boundaries. We'd need one layer that knows all about the SVG transforms.
Comment 17 Florin Malita 2012-02-15 11:07:55 PST
There is also a stacking problem: SVG specifies that elements are rendered in implicit order (elements should be "covering" their same-fragment predecessors). To preserve these semantics, we'll probably have to group FO sibling elements into additional synthetic layers to be composited in implicit order - pre-FO layer, FO layer, post-FO layer. Otherwise regular elements following a FO will be covered by it.
Comment 18 Nikolas Zimmermann 2012-02-15 14:47:48 PST
(In reply to comment #17)
> There is also a stacking problem: SVG specifies that elements are rendered in implicit order (elements should be "covering" their same-fragment predecessors). To preserve these semantics, we'll probably have to group FO sibling elements into additional synthetic layers to be composited in implicit order - pre-FO layer, FO layer, post-FO layer. Otherwise regular elements following a FO will be covered by it.
Exactly! I had fO + layers working until this point :-) This is the really problematic thing. Any SVG renderer would need to check if it follows a <fO/> - if yes, it has to return true for requiresLayer - probably requires some plumbing in RenderSVGBlock, RenderSVGInline, RenderSVGModelObject (+ another base class I probably forgot).

Once that works, we need testcases which moves <svg><g id="g1"/><fO/><g id="g2"/>.... eg. g1 behind g2, etc, to make sure we handle updates of the "pre-Fo layer, FO-layer, post-fO-layer" states properly. I could think of more tricky test cases as well...

Are you planning to work on that?
Comment 19 Florin Malita 2012-02-16 07:52:31 PST
(In reply to comment #18)
> Exactly! I had fO + layers working until this point :-) This is the really problematic thing. Any SVG renderer would need to check if it follows a <fO/> - if yes, it has to return true for requiresLayer - probably requires some plumbing in RenderSVGBlock, RenderSVGInline, RenderSVGModelObject (+ another base class I probably forgot).

My initial thought was to group the elements following a FO into a hidden container and only create one additional layer. But that can be probably implemented later as an optimization (if needed at all) - your idea seems much more straightforward.


> Are you planning to work on that?

Sure, I've been chipping at this issue long enough now that I might as well keep doing it :) Do you have a saved patch that you can share?
Comment 20 Elliott Sprehn 2012-11-05 11:22:47 PST
*** Bug 101237 has been marked as a duplicate of this bug. ***
Comment 21 Philip Rogers 2014-04-15 20:24:08 PDT
*** Bug 131492 has been marked as a duplicate of this bug. ***
Comment 22 Said Abou-Hallawa 2019-08-02 15:29:37 PDT
*** Bug 165516 has been marked as a duplicate of this bug. ***
Comment 23 Said Abou-Hallawa 2019-08-02 15:31:14 PDT
*** Bug 200383 has been marked as a duplicate of this bug. ***
Comment 24 Said Abou-Hallawa 2019-08-02 15:33:58 PDT
*** Bug 32218 has been marked as a duplicate of this bug. ***
Comment 25 Said Abou-Hallawa 2019-08-02 15:35:39 PDT
*** Bug 198660 has been marked as a duplicate of this bug. ***
Comment 26 Jay Wang 2019-12-19 17:24:37 PST
Having the same issue with <foreignObject>. Any work on this issue?
Comment 27 fabswt 2020-02-21 08:46:44 PST
Created attachment 391404 [details]
foreignObject and positioning bug

Attaching a test case.

It demonstrates the issue with `transform` breaking the positioning of foreignObject's children.

It also shows a workaround: `position: fixed` can be used to prevent the issue. Problem is it can't be used just anywhere.

In any case… This is a basic SVG functionality that's broken. Any chance to get a fix? It's been open for 11 years now.
Comment 28 Timur 2020-03-24 06:23:00 PDT
I encountered this problem. When will it be resolved? There has been no progress for 11 years. Please speed up the solution of this problem.
Comment 29 chototoro 2020-03-30 11:43:51 PDT
I was about to file a bug regarding foreignObject content not being correctly scaled when using the zoom command +/- in Safari, but i think it is related to this bug.
As previous comments said, it occurs on elements with positioning, opacity, or transform.
Here is a test-case where the layout is fine, until you zoom in or out the page: https://codepen.io/chototoro/pen/gOpqjEX
Comment 30 Edaqa Mortoray 2020-07-17 00:11:23 PDT
Created attachment 404542 [details]
Showing defect using scrolling section

This shows the defect using a div which contains a scrollable section.

The inner-document has these CSS settings:

```
	.inner-document {
		font-size: 28px; 
		overflow-y: auto;
		width: 100%;
		height: 100%;
	}
```

The moment the size exceeds the space to the foreignObject the render error happens.
Comment 31 Nikos 2020-09-01 12:40:46 PDT
any updates? no wonder people call safari the new ie)
Comment 32 eldar 2020-10-05 09:33:10 PDT
Same issue in Safari v14.0
is there any chance to get this fixed?
Comment 33 terrence 2020-12-06 01:47:29 PST
This issue was also on chromium but has now been fixed in chrome 87 - which was stable as November 17th, 2020

The chromium bug is here:
https://bugs.chromium.org/p/chromium/issues/detail?id=976224

which is a duplicate of this related bug:
https://bugs.chromium.org/p/chromium/issues/detail?id=738022&q=foreign-object

The test case used for this bug was:
https://codesandbox.io/s/chrome-foreignobject-defect-wf91j

This test currently passes on the chrome 87 but fails on safari 14.

Would be great if this could fixed to have standardized SVGForeignObject behavior.
Comment 34 terrence 2020-12-06 02:00:40 PST
this test:
https://srguiwiz.github.io/foreignobject-zoom-issue/foreignobject-zoom.htm

seems like the best way to reproduce issue. this test was comment in:
https://bugs.chromium.org/p/chromium/issues/detail?id=976224
Comment 35 terrence 2020-12-06 02:00:58 PST
this test:
https://srguiwiz.github.io/foreignobject-zoom-issue/foreignobject-zoom.htm

seems like the best way to reproduce issue. this test was comment in:
https://bugs.chromium.org/p/chromium/issues/detail?id=976224
Comment 36 William Spitzer 2020-12-10 14:46:54 PST
I encountered this bug as part of my workflow and found that the issue that was causing it was due to position: relative/absolute elements in the foreignObject. 

I made a demo to show the differences in behavior (try in chrome vs safari)
https://jsfiddle.net/hkctay9z/2/

This is a pretty big blocker which prevents usage of foreignObject in Safari for our project. Hopefully the demo provided will help the bugfix.
Comment 37 Rob Johnston 2021-04-07 13:50:12 PDT
We've hit this one too.  We use SVG content that includes embedded iframes to deliver advanced "touchscreen" layouts to our users.  Now that this technique works on Chrome, we're shipping a product that works most everywhere except for Safari.
Comment 38 Artemy 2021-07-12 10:57:35 PDT
Hi,

Our customers faced the same issue when are using one of our HTML/JS components. I reproduced the issue using a simple HTML markup, Check the following sample:
https://codesandbox.io/s/templates-devextreme-diagram-forked-56vuc?file=/CustomShapeTemplate.vue

Would you please inform me if this issue is fixed?

Thanks,
Artemy
DevExpress
Comment 39 Mark 2021-08-06 21:38:53 PDT
Also experiencing this issue with a major customer, reading StackOverflow and elsewhere, I get the express feeling that many people are being affected by this.

Depends on 90738 which seems to be progressing at least. It's not great that customers have to use another browser, and of course you're out of luck on iOS and iPadOS.

Can anyone give any indication of what is happening with this bug?
Comment 40 Patrick Spiegel 2022-01-04 03:07:18 PST
This is a major issue. This is an issue that makes it impossible to user Safari properly. This should get a higher priority as there is no possible work around beside using a different browser.
Comment 41 kshetline 2022-03-17 19:59:40 PDT
I'm running into a problem with this issue here: https://shetline.com/orloj/

Changing positioning of a div inside my foreignObject from absolute to fixed helped some, but the sizing of a canvas inside the div inside the foreignObject is still wrong, and layering is completely ignored -- the canvas contents appear on top of all of the other SVG components, rather than being an intermediate layer, the way the canvas works in Chrome and Firefox.

Other suggestions like using a body tag, xmlns="http://www.w3.org/1999/xhtml", or requiredExtensions="http://www.w3.org/1999/xhtml" didn't help either.
Comment 42 kshetline 2022-03-18 18:42:55 PDT
(In reply to kshetline from comment #41)
> I'm running into a problem with this issue here: https://shetline.com/orloj/
> 
> Changing positioning of a div inside my foreignObject from absolute to fixed
> helped some, but the sizing of a canvas inside the div inside the
> foreignObject is still wrong, and layering is completely ignored -- the
> canvas contents appear on top of all of the other SVG components, rather
> than being an intermediate layer, the way the canvas works in Chrome and
> Firefox.

The sample website above will no longer displaying the bug. My not-very-satisfactory workaround for now is to draw to an off-screen canvas, turn the contents of that canvas into a data URL, then assign that URL to an SVG <image>. The performance of this workaround is very slow compared to using a canvas directly. Fortunately fast animation is not vital for this particular website, but where fast animation is needed my workaround would be totally unsatisfactory.
Comment 43 Jakub T. Jankiewicz 2022-03-28 10:40:12 PDT
I have a demo that can confirm this. Safari/Webkit doesn't render HTML inside SVG foreign Object properly:

This is my app, SVG laptop with Terminal inside.
https://terminal.jcubic.pl/laptop/

The position and scale of the terminal are way off.

I use CSS custom properties and calculate pixel density to fix the scaling of the terminal inside the SVG Laptop. More or less it works correctly in Firefox and Chrome (Chrome has some issues, but they were reported).
Comment 44 Simon Fraser (smfr) 2022-03-28 11:00:16 PDT
*** Bug 238461 has been marked as a duplicate of this bug. ***
Comment 45 Simon Fraser (smfr) 2022-03-31 12:15:48 PDT
*** Bug 238499 has been marked as a duplicate of this bug. ***
Comment 46 Simon Fraser (smfr) 2022-06-01 19:37:25 PDT
*** Bug 83189 has been marked as a duplicate of this bug. ***
Comment 47 Simon Fraser (smfr) 2022-06-03 21:14:28 PDT
<rdar://8912810>
Comment 48 Simon Fraser (smfr) 2022-06-17 20:35:29 PDT
*** Bug 93358 has been marked as a duplicate of this bug. ***
Comment 49 Simon Fraser (smfr) 2022-07-18 16:02:44 PDT
*** Bug 103117 has been marked as a duplicate of this bug. ***
Comment 50 Anthony Johnston 2023-08-12 10:15:21 PDT
I am using this to create a dataUrl to share an image of an element in my project.
Its an important part of the app, and does not work correctly on Safari iOS

https://8bit.antix.co.uk/ completing a bitmap will show the share button
Comment 51 Simon Fraser (smfr) 2023-09-06 13:45:15 PDT
*** Bug 241983 has been marked as a duplicate of this bug. ***
Comment 52 Silvan Mühlemann 2024-01-05 08:41:10 PST
On https://codepen.io/silvanm75/pen/KKbBqzB you can see how to reproduce the issue and how I worked around it. 

The workaround lead to odd side effects on my project. That's why I would appreciate it if this bug could be fixed.