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

Allow creating <polymer-element>s without Shadow DOM #222

Closed
ebidel opened this issue Jul 26, 2013 · 32 comments
Closed

Allow creating <polymer-element>s without Shadow DOM #222

ebidel opened this issue Jul 26, 2013 · 32 comments
Assignees

Comments

@ebidel
Copy link
Contributor

ebidel commented Jul 26, 2013

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.

@sjmiles
Copy link
Contributor

sjmiles commented Jul 26, 2013

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.

@ebidel
Copy link
Contributor Author

ebidel commented Sep 9, 2013

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

@ebidel ebidel closed this as completed Sep 9, 2013
@ebidel
Copy link
Contributor Author

ebidel commented Oct 1, 2013

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!?

@ebidel ebidel reopened this Oct 1, 2013
@sjmiles
Copy link
Contributor

sjmiles commented Oct 1, 2013

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.

@ebidel
Copy link
Contributor Author

ebidel commented Oct 1, 2013

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.

@jmesserly
Copy link
Contributor

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)

@jmesserly
Copy link
Contributor

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.

@ebidel
Copy link
Contributor Author

ebidel commented Oct 2, 2013

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.

@jmesserly
Copy link
Contributor

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" notifications@github.com 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//issues/222#issuecomment-25507605
.

@ghost ghost assigned sjmiles Oct 2, 2013
sjmiles pushed a commit that referenced this issue Oct 3, 2013
@ebidel
Copy link
Contributor Author

ebidel commented Oct 4, 2013

d8d0a4d works great @sjmiles. Thanks.

We cool to close this?

@sjmiles
Copy link
Contributor

sjmiles commented Oct 4, 2013

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.

@ebidel
Copy link
Contributor Author

ebidel commented Oct 4, 2013

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 notifications@github.comwrote:

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//issues/222#issuecomment-25675814
.

@sjmiles
Copy link
Contributor

sjmiles commented Aug 18, 2014

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

@sjmiles sjmiles closed this as completed Aug 18, 2014
@sartaj
Copy link

sartaj commented Dec 22, 2014

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?

@arthurevans
Copy link

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.

@graphicbeacon
Copy link

@arthurevans Thanks for this information. Was what I was looking for 👍

@antitoxic
Copy link

@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.

@addyosmani
Copy link
Member

@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.

@antitoxic
Copy link

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" 😃 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.

@arthurevans
Copy link

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

@antitoxic
Copy link

@arthurevans thank you.

@fernandopasik
Copy link

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

@arthurevans
Copy link

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" notifications@github.com 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
#222 (comment).

@fernandopasik
Copy link

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>

@ebidel
Copy link
Contributor Author

ebidel commented Sep 14, 2015

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

On Mon, Sep 14, 2015, 6:08 PM Fernando Pasik notifications@github.com
wrote:

How would this change in order to do that?

I am x-foo! <script> Polymer({ is: 'x-foo' }); </script>


Reply to this email directly or view it on GitHub
#222 (comment).

@fernandopasik
Copy link

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>

@fernandopasik
Copy link

@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>

@ebidel
Copy link
Contributor Author

ebidel commented Sep 18, 2015

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 notifications@github.com
wrote:

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

This one doesn't have shadow dom and without Polymer. <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>


Reply to this email directly or view it on GitHub
#222 (comment).

@fernandopasik
Copy link

ok thanks for your help!

@roxanalascu
Copy link

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

@mrdevin
Copy link

mrdevin commented Oct 16, 2017

👍

@gavinmcfarland
Copy link

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. 😢

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

No branches or pull requests