Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for ShadowDOM features in SVG #942

Open
trusktr opened this issue Sep 19, 2021 · 3 comments
Open

Adding support for ShadowDOM features in SVG #942

trusktr opened this issue Sep 19, 2021 · 3 comments

Comments

@trusktr
Copy link
Contributor

trusktr commented Sep 19, 2021

I think at least something like the following, f.e. distributing SVG content to a slot element inside SVG markup, should be possible:

<div>
	<svg>
		<rect x="120" width="100" height="100" rx="15" slot="content" />
	</svg>
</div>

<script>
	// User code //////////////////////////////////
	const div = document.querySelector('div')
	const rect = document.querySelector('rect')
	div.append(rect)

	// Web Component code /////////////////////////
	const root = div.attachShadow({mode: 'open'})
	root.innerHTML = /*html*/`
		<slot name="content"></slot>
		<svg viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg" fill="red">
		  <rect width="100" height="100" />
		</svg>
	`
	const slot = root.querySelector('slot')
	const svg = root.querySelector('svg')
	svg.append(slot)
	
	console.log(rect instanceof SVGElement) // true
	console.log(rect.parentElement instanceof SVGElement) // false
	console.log(rect.parentElement instanceof HTMLElement) // true
</script>

codepen example

Although the composition actually works (notice in the element inspector in Chrome that the SVGRectElement <rect> instance is in fact composed to the <svg> element, and the <slot> that is inside of the <svg> element does have the <rect> as an assignedNode. However the rectangle does not appear on screen, although the composition mechanics are in place and functioning.

The ability to compose non-HTMLElement elements like this would be nice. Non-web-component frameworks don't have this limitation when composing from a higher tree to a lower tree.

What's the plan for composition with SVG?

@Danny-Engelman
Copy link

Danny-Engelman commented Sep 20, 2021

I presume it is a sh*load of Namespace issues.

It looks like Vue has a ApplyNS function; no experience with it.

I have faked "slots" with:

<div>
  <svg>
    <circle cx="50%" cy="50%" r="35%" fill="yellow" slot="content"></circle>
    <circle cx="50%" cy="50%" r="15%" fill="green" slot="content"></circle>
  </svg>
</div>
<script>
  const host = document.querySelector('div');
  const root = host.attachShadow({mode:'open'});
  root.innerHTML = `
		<svg viewBox="0 0 100 100">
		  <rect width="100%" height="100%" fill="blue"/>
		  <slot name="content"/>
		</svg>`;
  root.querySelectorAll('slot').forEach(shadowSlot => {
    let name = shadowSlot.getAttribute("name");
    let slotFragment = new DocumentFragment();
    slotFragment.append(...host.querySelectorAll(`[slot="${name}"]`));
    shadowSlot.replaceWith(slotFragment);
  });
</script>

See: https://jsfiddle.net/WebComponents/d7xp5noq/

But since it moves lightDOM content it certainly is not a Polyfill.

For Web Component users that <svg> in lightDOM to get the Namespace correct is a biggie.

In the <pie-chart> Web Component I did for Dev.to
I went with Unknown Elements in ligthDOM:

<pie-chart>
  <slice size="90" stroke="green">HTML</slice>
  <slice size="1" stroke="red">JavaScript</slice>
  <slice size="9" stroke="blue">CSS</slice>
</pie-chart>

This is code end-users understand;
but requires a bit more code in the Web Component to convert it to proper SVG.

@GeorgeTailor
Copy link

GeorgeTailor commented Nov 29, 2021

this seems to be related: #6226
Somewhere in the depths of W3C spec for HTML I've found that there are 2 types of elements, ones that require a strict structure, and some that can be composed more loosely (or something like that).
table requires a strict structure, so does SVG, plus, it's not even HTML.

Anyway, the response I've got is:

This is being discussed in #630 but it's largely a dead end as it requires changes to the HTML parser. I think we best keep the discussion there so I'll close this.

@trusktr
Copy link
Contributor Author

trusktr commented Feb 19, 2022

I presume it is a sh*load of Namespace issues.

I dislike the namespace stuff. If only svg were merely a subset of html. It currently hampers the dev experience. A <rect> element inside HTML should always just be an svg element (with one meaning, not necessarily rendering anything if not in the proper parent though).

No way to fix it? (Although that would be a whole other discussion.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants