Which querySelector on <paper-toolbar> is better? - polymer

var toolbar = Polymer.dom(document).querySelector('#main-toolbar')
var toolbar = document.querySelector('#main-toolbar');
<paper-toolbar id="main-toolbar">
1) why does document.querySelector work on paper-toolbar when it's a shadow dom element? or another way to put it... why does it work on a element that is in local dom?
2) since both of these querySelector work, which is better to use?

The toolbar is not inside a polymer element.
You can juste use document.querySelector('#main-toolbar');
No need to use Polymer API here (polymer element are HTML elements).
The polymer API is useful to access the shadow/shady DOM (inside your polymer elements).

Related

Shadow Dom and CSS3 :target selector

I should start off by saying that I don't really have an issue that I'm trying to work through. I just had an interesting thought about how Shadow Dom and the CSS3 :target selector might / should / currently do work together.
I know that HTML specification says that there should only ever be one element with a particular ID value in a valid HTML document. But when we start using webcomponents with shadow dom we could very easily find ourselves using multiple elements with the same ID. This is especially true when we use the same component multiple times in the same page. So the question that I have is this: what should happen to an element inside a shadow dom region that has an ID value which matches the current hash and which is styled with a :target rule?
For example, if I wrote a webcomponent (my-element) that contained
<style>
#debug {display:none}
#debug:target { display:block; background-color:yellow; border 2px solid red; }
</style>
<div id="debug">some debug data</div>
What should happen to all the instance of my-element that I put on a page and navigated to #debug on? Should the debug element in each component show? Should none of them show? Should only the first element's debug div show (the same one I'd expect the browser to try and navigate to)?
My opinion is that if the page does not have an element with an ID=debug value that no scrolling navigation should appear on the page. As shadow dom is isolated from the rest of the page's styles the browser shouldn't try to navigate to such an element nested in shadow dom. Each my-element instance should be able to see the current page's URL though and should apply any matching :target rules, such that each my-elements' debug div should be visible.
If this were the case it would make for some interesting possibilities for sharing page state across all components, such as the debug example above. However, I doubt that is how Chrome is currently implementing things. And I'm pretty sure this Shadow Dom polyfill isn't going to handle things correctly as it basically shoehorns everything into the page's Dom tree and that would break the html specification.
Just curious if anyone has an answer for how this should work and how it works today...
(edited from my pc to add formatting... hard to do from my phone)
I think you can see the shadow DOM like a nested document. CSS can't address elements inside the shadow DOM from the outside (previously existing shadow piercing CSS selectors were deprecated).
This also encapsulates ids and therefore multiple components that contain elements with an id won't cause collisions or duplicates.
If you have the CSS with the :target selector inside a components style, it should be able to address the element with the matching id, otherwise it shouldn't.
So the question that I have is this: what should happen to an element
inside a shadow dom region that has an ID value which matches the
current hash and which is styled with a :target rule?
Adding to Günter Zöchbauer above answer an alternative is to use the Custom Element object when the style is encapsulated, if the style is global it will work just fine. Use the define method to create a custom component as shown in the the docs. This will not encapsulate your elements so be aware that your styles can be shared across files.
So instead of doing this:
const shadow = this.attachShadow({ mode: "open" });
shadow.appendChild(pTag)
Use this:
this.appendChild(pTag);
both previous examples suppose you're in a HTMLElement class or a class that inherits it.

Cannot add ::after pseudo-element to slotted element in shadow dom

I was experimenting with Eric Bidelman's <fancy-tabs> shadow dom example: https://developers.google.com/web/fundamentals/getting-started/primers/shadowdom
And was trying to add Material Design styling to it, which would require adding an :after pseudo element to the tabs.
After some experimentation I found that the internal styles for applying pseudo elements do appear to work when using Polymer, but not when using vanilla JS...
Polymer example:
https://jsbin.com/maqaze/edit?html,output
Vanilla JS example:
In this second example, applying the :after pseudo element does not work within the shadow dom <style> it apparently needs to be set externally.
https://jsbin.com/toxalu/edit?html,output
So my question is, how should you go about adding a pseudo element to a slotted / light dom element, without needing to use external styles?
(have tried these examples on Chrome and Safari)
If it seems to work in Polymer it's due to the fact that Polymer 1.0 doesn't really use native ::slotted pseudo-elements.
In fact Polymer uses native Shadow DOM "v0" and converts ::slotted to ::content. You can see it in the Dev Tools.
As you have noted you can add ::after pseudo-elements from the outside.
I suppose pseudo-elements are considered as complex selectors and therefore are not supported within ::slotted().

Light DOM styles "leaking" into Polymer component's shadow DOM

I have a polymer web component which has a div named content, within the component.
I have noticed that if the host page has a style for div.content then it applies that style to my component!
This is an unexpected turn of events since web components are supposed to prevent light DOM styling from leaking into the component. In addition, I am using the following css rule which is supposed to prevent such a thing from happening:
:host {
all: initial;
}
Any ideas?
Polymer by default doesn't use shadow-dom. It uses an approximation of it called shady dom, which doesn't provide style encapsulation and everything is dumped into light dom.
If you want to enable shadow dom by default, you can do so by using this config:
<script>
window.Polymer = window.Polymer || {};
window.Polymer.dom = 'shadow';
</script>

Polymer custom element tag appearing in the DOM

I've just started learning about Polymer custom elements.
I've created a very simple custom element, the usage of which is as follows:
<my_custom_element></my_custom_element>
The template for the custom element is:
<template>
<span>Hello</span>
</template>
If I inspect the DOM using Chrome Dev tools, I notice that my_custom_element tag appears in the DOM. I wasn't expecting this. I was expecting that this tag would be replaced by the template content. What does my_custom_element represent in its own right?
I also read that :host can be used to style a custom element internally from within its definition and it's used to style host element itself. But again I don't understand what it means to style the host element in its own right. Isn't the host element defined by its template content?
The web components model does not use <my-custom-element> as a placeholder, but as an actual and real HTML element with complex behaviors and its own contents.

Page doesn't render extended Polymer element

I am trying to extend the Polymer core-selector but it doesn't render on the webpage.
When I place <shadow></shadow> inside the template-tags it does render.
I don't know for sure if that is the real problem. What is the purpose of the shadow-tags? I don't find information about that in the API documentation.
Here is the link to an example: http://jsbin.com/qucitiwe/3/edit?html,console
You can find some information on how to extend elements in the Extending other elements section of the Polymer documentation.
The shadow element renders the shadow DOM of the parent element (the DOM inside the parent's template element) at this exact location. So without the shadow element you won't see any DOM from the parent element.
In addition, a child element can wrap the parent's shadow DOM with its own content, for example:
<template>
<div>Title</div>
<shadow></shadow>
<div>Footer</div>
</template>