Polymer: Allow creating <polymer-element>s without Shadow DOM

Created on 26 Jul 2013  ·  32Comments  ·  Source: Polymer/polymer

I recently had some back and forth with Bruch Lawson on the overuse of wrapping everything in and element hidden by Shadow DOM. We need to do a better job of telling people to use Shadow DOM where it makes sense.

To that end, Polymer auto-creates Shadow DOM from the first <template> if find.
We should allow users to create <polymer-element>s that don't create Shadow DOM.

If there's a way to already do this, let me know so we can get it documented.

enhancement

Most helpful comment

Is it possible to create a Polymer element in the light DOM using Polymer 2 ?

All 32 comments

The template/shadowdom machinery is all exposed on the instance prototype so users can customize the behavior by overriding methods.

The key methods are parseElements, parseElement, and fetchTemplate, which are in the code here https://github.com/Polymer/polymer/blob/master/src/instance/base.js

The rabbit hole gets a little deep, we will have to work on documenting this thoroughly.

Closing this. It's already possible, just needs documenting.

Reopening this as it comes up a lot (what to put in SD and what to leave in light dom).

Big question: can we make creating elements w/o SD easier!?

Before we can answer that, I think we need to have a more nuanced problem description.

If the notion is that users want to be able to populate light DOM from a template, this is actually pretty easy, but I can't understand why it's a good idea.

In general, the notion that adding an element to DOM causes a whole bunch of elements to appear in DOM is unnatural (aka never happens traditionally). I'm not convinced we should promote this technique.

On the flip side, I'm no longer convinced we should _only_ be promoting custom elements created from shadow dom. SEO is the big one that comes up in this discussion. Adding markup to the light dom does feel unnatural, but custom elements are new and freakishly unnatural. There's no precedence!

One of Polymer's goals is to advocate Custom Elements. From that perspective we should enable/allow developers to create them any way they wish...with the use case dictating the approach. Fully agree that Polymer should keep it's opinionated way of creating elements. Take @sorvell's recent work on FOUC prevention. By default we help you, but now it's easy to override. My use case of ajaxifying polymer-project.org called for better controls.

Here are some pros for developer opt-out:

  • developers have been asking for elements without shadow dom
  • flexibility is good
  • don't need to create a separate tree for trivial elements. polyfill perf boost?
  • SEO advantages
  • similarities to how x-tags/bricks works <- not sure this matters, but threw it in there :)

I'm just hoping we can make the override hooks easier. If it's a question of technical challenge that's different.

So, if you create a ShadowDOM-free component, how does <content> work?

It seems okay(ish) for leaf nodes. I'm not sure about containers. Consider:

<polymer-element ...>
  <template>     
    <template if="{{something}}">
      <content select=".breaking-news"></content>
    </template>
    ...
  </template>
</polymer-element>

People expect <content> to interact correctly with data-binding, and that isn't possible without Shadow DOM.

(edit for clarity)

SEO is the big one that comes up in this discussion.

I've said this before but: Shadow DOM doesn't have _anything_ to do with SEO :). If we assume crawler doesn't run any code, the Shadow/Light DOM distinction is meaningless. The problems are a result of Custom Elements, and to a lesser extent HTML Imports. Even if you use 100% Light DOM it doesn't make the SEO situation any better.

In fact, Shadow DOM might make the SEO situation _better_, because it has <content>, so it's easy to create a custom element that expose the relevant SEO-stuff on the raw HTML page.

if you create a ShadowDOM-free component, how does <content> work?

I wouldn't expect this to work because it's a shadow dom feature. I'm advocating an easier opt-in path for _simple_ components. If a developer flips the noshadow swift, they smart enough to know <content> isn't going to do anything :)

The problems are a result of Custom Elements

The point I'm making is that Polymer creates Shadow DOM for its custom elements atm. The two are not decoupled at the moment and very much tied together.

the Shadow/Light DOM distinction is meaningless

I'm usually in this same bucket. I did some research on the subject last week and everything in light dom does make a difference: http://youtu.be/inIIyR7hN8M

Just as we suspected, engines are smart enough to run JavaScript and look at the composed tree (proof by the onebox results). Wait I failed to remember when I shot this video (why it's not published) is that Google is running a headless version of WebKit. This means the components on polymer-project.org are defaulting to the polyfill, not native Shadow DOM.

it's easy to create a custom element that expose the relevant SEO-stuff on the raw HTML page.

Also agree, but a perfect example where I've ran into issues is dogfooding elements in our docs. <polymer-ui-menu> does a good job of staying in light dom. However, to get the awesomeness of data-binding I wrapped it in a super simple element. Boom, our nav is now in Shadow DOM :( Instead, it would be super cool to have some flexibility.

Yeah, if we're going to assume crawlers can run JavaScript and they
implement a full DOM, then that changes the analysis. If they are then they
will need to be updated as HTML5 DOM spec evolves. So they will need to
understand Shadow DOM (or at least the polyfill).

In any case, I don't see how a JS polyfill can fool a crawler. Crawler
should use the _rendered DOM_, just like the browser does. In other words,
the DOM that C++ sees, not the illusion that exists in the JS world after
the DOM is madly monkeypatched. If it is trusting the JS view of the DOM, I
think its a crawler bug.

Just my opinion, but: I wouldn't mess up the framework for this reason,
until exploring other options. (Crazy idea: maybe something could be done
in Shadow DOM polyfill to recognize busted crawler user agents and do
something different?)
On Oct 1, 2013 6:32 PM, "Eric Bidelman" [email protected] wrote:

if you create a ShadowDOM-free component, how does work?

I wouldn't expect this to work because it's a shadow dom feature. I'm
advocating an easier opt-in path for _simple_ components. If a developer
flips the noshadow swift, they smart enough to know isn't going
to do anything :)

The problems are a result of Custom Elements

The point I'm making is that Polymer creates Shadow DOM for its custom
elements atm. The two are not decoupled at the moment and very much tied
together.

the Shadow/Light DOM distinction is meaningless

I'm usually in this same bucket. I did some research on the subject last
week and everything in light dom does make a difference:
http://youtu.be/inIIyR7hN8M

Just as we suspected, engines are smart enough to run JavaScript and look
at the composed tree (proof by the onebox results). Wait I failed to
remember when I shot this video (why it's not published) is that Google is
running a headless version of WebKit. This means the components on
polymer-project.org are defaulting to the polyfill, not native Shadow DOM.

it's easy to create a custom element that expose the relevant SEO-stuff on
the raw HTML page.

Also agree, but a perfect example where I've ran into issues is dogfooding
elements in our docs. does a good job of staying in
light dom. However, to get the awesomeness of data-binding I wrapped it
in a super simple elementhttps://github.com/Polymer/docs/blob/master/_includes/left-nav.html#L45-137.
Boom, our nav is now in Shadow DOM :( Instead, it would be super cool to
have some flexibility.


Reply to this email directly or view it on GitHubhttps://github.com/Polymer/polymer/issues/222#issuecomment-25507605
.

https://github.com/Polymer/polymer/commit/d8d0a4d works great @sjmiles. Thanks.

We cool to close this?

We can close this, but I expect some follow up issues.

It's probably a bad idea to use [lightdom] elements inside of another (Polymer) element's shadowdom. Bindings and event delegations may not work properly.

We will need to mature this feature over time and build a test suite.

Thanks Scott. I'll mark the feature as a WIP and add those notes.

On Thu, Oct 3, 2013 at 9:25 PM, Scott J. Miles [email protected]:

We can close this, but I expect some follow up issues.

It's probably a bad idea to use [lightdom] elements inside of another
(Polymer) element's shadowdom. Bindings and event delegations may not work
properly.

We will need to mature this feature over time and build a test suite.


Reply to this email directly or view it on GitHubhttps://github.com/Polymer/polymer/issues/222#issuecomment-25675814
.

This issue is too old and this territory is a bit better known, so I'm going to close it.

It seems that lightdom as an attribute for <polymer-element> has been deprecated. I can't seem to find it anywhere in the code or documentation. Is there any other way to get lightdom to work?

You can do this by overriding the element's parseDeclaration method.

Polymer({
  parseDeclaration: function(elementElement) {
    var template = this.fetchTemplate(elementElement);
    if (template) {
      var root = this.lightFromTemplate(template);
    }
  }
});

Here's the code in context:

http://jsbin.com/xidafo/1/edit?html,output

We don't have this in the documentation at present. However, there are good comments here:

https://github.com/Polymer/polymer/blob/master/src/instance/base.js#L261

We should have more of the Polymer built-ins documented for the 0.8 release, where I'm guessing we'll still have something like lightFromTempate. Perhaps @sjmiles or @sorvell can confirm.

@arthurevans Thanks for this information. Was what I was looking for :+1:

@arthurevans, @sjmiles, @sorvell does any of you have some idea for 0.8 release month? I'm not looking for an exactly pin-pointed date, but simply something I can use to orient myself

I know Polymer is in dev preview, but it is, by all indicators (w3c web components, ease of use, data-binding, html imports...), the library that will shape the web. I can't find anything that is nearly usable as Polymer. I desperately want to use it.

Few things stop me. One big thing is the low shadow-dom proliferation and webcomponents.js edge cases (firefox bugs I ran into, selector bugs, drag and drop things.. etc).

If the date on which polymer starts supporting lightdom (aka no shadowdom) is relatively known I can arrange future projects around it.

@antitoxic See https://github.com/Polymer/polymer/blob/0.8-preview/PRIMER.md for our current thinking around 0.8. It's a moving target, however if you read through you'll discover the team have been exploring an alternative to native ShadowDOM for unsupported browsers. In those targets, Polymer provides local DOM using an SD-like thing called ShadyDOM. Hopefully this will alleviate some of the concerns around native SD proliferation. FF are also working on a native implementation of it.

With respect to webcomponents.js and bugs, we're working on better continuous integration for our tests and hope to improve the stability of the polyfills for edge-cases. If there's anything specific that catches you out, please feel free to file a bug and we'll take a look at it.

Thank you @addyosmani . I had a read. It's tasty. It doesn't hint about dates but I guess that's how things are.

Is the "shady" :smiley: DOM expected before 0.8?

In the meantime I'm exploring options in SO but it's seem it's an offtopic there.

It seems that I have spend some time thinking about anguarjs directives way to go about it.

Nope. Shady DOM (working title) and the local DOM abstraction are 0.8 features.

@arthurevans thank you.

@arthurevans, @ebidel, @addyosmani is there a way to create a custom element without shadow DOM in the current polymer 1.0 ?

Yes. If your element doesn't have a local DOM template, it won't have a
local DOM tree (shady/shadow DOM).
On Sep 14, 2015 8:08 AM, "Fernando Pasik" [email protected] wrote:

@arthurevans https://github.com/arthurevans is there a way to create
custom elements without shadow DOM in the current polymer 1.0 ?


Reply to this email directly or view it on GitHub
https://github.com/Polymer/polymer/issues/222#issuecomment-140111086.

Thanks @arthurevans. How should I declare the template then to achieve that? For example how should this code change?

<dom-module id="x-foo">
  <template>I am x-foo!</template>
  <script>
    Polymer({
      is: 'x-foo'
    });
  </script>
</dom-module>

Remove the dom-module and just keep your script tag.

On Mon, Sep 14, 2015, 6:08 PM Fernando Pasik [email protected]
wrote:

How would this change in order to do that?





Reply to this email directly or view it on GitHub
https://github.com/Polymer/polymer/issues/222#issuecomment-140127235.

Thanks @ebidel. When I do that I don't have any html in the element. What I thought it would do, is that the template is appended.

http://plnkr.co/edit/NLnyoSrJQZ7Qlrp9oNVl

This one shows an empty element

<template>
  This one <b>doesn't have shadow dom</b>.
</template>
<script>
  Polymer({
    is: "without-shadow"
  });
</script>

This one shows the element with shadow dom

<dom-module id="has-shadow">
  <template>
    This one has shadow dom.
  </template>
</dom-module>
<script>
  Polymer({
    is: "has-shadow"
  });
</script>

@ebidel what I'm trying to achieve is this but with polymer helpers:

http://plnkr.co/edit/NLnyoSrJQZ7Qlrp9oNVl

<template>
  This one <b>doesn't have shadow dom</b> and <i>without Polymer</i>.
</template>
<script>
  var thisDocument = document.currentScript.ownerDocument;
  var proto = Object.create(HTMLElement.prototype, {
    createdCallback: {
      value: function() {
        var t = thisDocument.querySelector('template');
        var clone = document.importNode(t.content, true);
        this.appendChild(clone);
      }
    }
  });
  document.registerElement('without-polymer', {prototype: proto});
</script>

I see. We don't have easy mechanics for stamping templates outside of
Polymer. Closest is dom-bind.

On Fri, Sep 18, 2015, 5:16 PM Fernando Pasik [email protected]
wrote:

@ebidel https://github.com/ebidel what I'm trying to achieve is doing
this with polymer:


Reply to this email directly or view it on GitHub
https://github.com/Polymer/polymer/issues/222#issuecomment-141480261.

ok thanks for your help!

Is it possible to create a Polymer element in the light DOM using Polymer 2 ?

👍

Currently there is no way to achieve the same as the below from within a custom element without using the !important flag.

<style>
    h1 {
        color: green;
    }
    custom-element h1 {
        color: red;
    }
</style>

This is probably my biggest stumbling block with using Polymer at the moment. 😢

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nazar-pc picture nazar-pc  ·  4Comments

yairopro picture yairopro  ·  3Comments

abdonrd picture abdonrd  ·  4Comments

myuseringithub picture myuseringithub  ·  3Comments

augustoroman picture augustoroman  ·  4Comments