Enlarging an SVG Tag with Shadow DOM

I experimented with HTML5 and SVG; and I am very new to JavaScript and web development, so something is probably missing me. I'm trying to create reusable web components using some of the new features like HTML Imports, Shadow DOM, and an extension of existing web elements. I have two html files:

test.html

<html> <head> <title>Test HTML5</title> </head> <body> <link rel="import" href="Elements/tank.html"> <svg width="100%" viewBox="0 0 500 500" style="border: solid; border-width: thin; stroke-width: 2;"> <polyline points="0,300 100,300 100,100 250,100 250,150 500,150" style="fill:none;stroke:black;stroke-width:3" onclick="window.alert('you clicked line')" /> <svg is="my-tank" x="200" y="350" width="50" height="50"></svg> </svg> </body> </html> 

tank.html

 <html> <body> <template id="tank"> <rect fill="red" width="50" height="50"></rect> </template> <script type="text/javascript"> var tankElement = document.currentScript.ownerDocument.querySelector('#tank'); document.registerElement('my-tank', { prototype: Object.create(SVGSVGElement.prototype, { createdCallback: { value: function () { var root = this.createShadowRoot(); //Works root.innerHTML = tankElement.innerHTML; //Doesn't work //var tankTemplate = document.importNode(tankElement.content, true); //root.appendChild(tankTemplate); } } }), extends: 'svg' }); </script> </body> </html> 

The code under the comment //Works draws a red rectangle that I expect in the allocated SVG space. The code under //Doesn't work does not draw anything or does not give any error.

Screenshot //Works : Works

Screenshot //Doesn't work : Doesn't work

I tested Opera 41.0.

+7
javascript html5 svg web-component shadow-dom
source share
2 answers

You cannot do this because svg cannot be a shadow host. Only a limited number of elements can be a shadow host:

article , aside , blockquote , body , div , footer , h1 , h2 , h3 , h4 , h5 , h6 , header , main , nav , p , section , span .

Thus, not only svg , but others, such as input or textarea , cannot have shadow copies (I'm talking about Shadow-DOM v1 ).

See attachShadow definition for attachShadow : https://dom.spec.whatwg.org/#dom-element-attachshadow

Note that:

  • SVGSVGElement does not implement HTMLElement .
  • I also heard something about SVG already containing shadow-dom in their implementation, and with Custom Elements v1 you can only have one shadow house (see here: http://hayato.io/2016/shadowdomv1/ ).

Why don't you create a regular user element that can contain <svg> elements inside its shadow dom?

+3
source share

This is because in the <template> the <rect> <template> element is not inside the <svg> , therefore it is not recognized as an SVGRectElement , but instead is an HTMLUnknownElement .

To make it work, just add the <svg> :

 <template id="tank"> <svg> <rect fill="red" width="50" height="50"></rect> </svg> </template> 

Now you can import an element using importNode() or cloneNode() :

 //Works var rect = tankElement.content.querySelector('rect').cloneNode(); root.appendChild(rect); 

Refresh Import Multiple SVG Elements

Put the elements in the <g> :

 <template id="tank"> <svg> <g> <rect fill="red" width="50" height="50"></rect> <rect fill="blue" width="25" height="50"></rect> </g> </svg> </template> 

Clone <g> with its contents:

 var g = tankElement.content.querySelector('g').cloneNode(true); root.appendChild(g); 
+2
source share

All Articles