What are the drawbacks of using Shadow DOM? - javascript

In the tutorials I see only the benefits of Shadow DOM, but there should be drawbacks as well. In which cases should we avoid using Shadow DOM?

Shadow DOM features can be seen as drawback as much as benefits:
Style isolation is a benefit if you want it but a drawback if a user wants to style a component with Shadow DOM from a global CSS stylesheet.
DOM Shadowing is a benefit in some cases, but a drawback if an external script/library or extension needs to parse or select the content.
There are many 3rd party libraries (or extensions) that won't work with Shadow DOM content because they were not designed to deal with it, or need some additional configuration to work with Shadow DOM.
Examples:
Disqus comments integration
CodeMirror editor integration
Wiris math editor integration
Also, extensions that parse HTML will be blocked at the Shadow DOM boundary: a benefit if you don't want to spied, a drawback if you consider them as a useful service.
Event propagation is different inside and outside the Shadow DOM. So you may have some difficulties dealing with UI events.
Example :
TinyMCE integration
Conclusion
Use Shadow DOM only if you want CSS style or DOM isolation.
Don't use Shadow DOM if you need to interact with some not compliant third party components or library.

Uh, ah, this technology's specification has not stabilized and is not supported by many browsers. I would call that a drawback.
See: https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow
For now I would say; Avoid in most cases, except when you want to experiment with new stuff and it is not for the production environment.
UPDATE: By now all modern browsers support this feature.

Related

How to make JS tooltips work in Shadow DOM?

I am using Vue & Bootstrap for an app where I generate web components according to the official Vue documentation (https://cli.vuejs.org/guide/build-targets.html#web-component). For the most part Bootstrap and my business logic is working fine within the #shadow-roots of the web components as if it were in the light DOM.
However, Bootstrap tooltips (which are based on Popper.js https://popper.js.org/) are not working within the Shadow DOM at all. I have also tried to invoke tooltips directly with Popper.js and Tippy.js (https://atomiks.github.io/tippyjs/) in the Shadow DOM encapsulated code, sidestepping Bootstrap altogether, and I still cannot get them to work.
See example here: https://jsfiddle.net/mfep6rg9/
I can guess why -- the 3rd party tooltip libraries most likely aren't finding the target DOM element because it's in a Shadow DOM.
Is there a 3rd party solution out there that accounts for Shadow DOM / web component encapsulation?
Your guess is correct. 3party solutions using document. are not querying shadowDOM.
And there probably is no 3rd party solution as a solution requires either
WebComponents to communicate Mouse positions to the outside world.
Host querying shadowDOM (and nested shadowDOMs and nested shadowDOMs)
Not much different from an (even more restricted) IFRAME
I had the same problem while building LitElement-based Web Components and found the following solution:
$(this.shadowRoot.querySelectorAll("[data-toggle='tooltip']")).tooltip();
Make sure to target the respective element's shadowRoot and run a querySelectorAll to listen to all shadowRoot child elements that listen to "data-toggle='tooltip'".

Shadow DOM, aim of using it

I have studied Shadow DOM recently, and I was wondering what are the aims of using it instead of the main one.
What does it gives ? Why dont we use standard DOM instead of it (except for styling scoping) ?
It allows you to encapsulate functionality, effectively putting it in a black box. It means you can create [reusable] components whose inner workings aren't exposed; this is impossible using standard DOM.
As an example, take HTML input elements. So, say, the file type of input. To use it on an HTML page, you simply add <input type="file" />, and it works. You don't need to add any extra code or HTML or CSS to handle how it works, it just does, and you can't access the internal bits of it. If you were to write a piece of UI, using HTML/CSS/JS, that did the same thing, it would be fairly complex. But the file input is just a single tag that you can use anywhere, it always does the same thing. The web component family of specs allow you to create your own elements that work in this way, and the Shadow DOM is a critical part of this. You can create a new element, like <my-fantastic-file-input />, with its functionality encapsulated. It has its own internal DOM subtree, but that subtree isn't directly accessible; ditto with scoped styles. The new component does not expose its implementation details to the document.
You can do most of this stuff using the DOM, but the implementation will be wholly tied into the document/application structure. With components, you extract that implementation, and you can reuse it, pass it around, publish it and let other people drop it into their applications/documents, and be sure it will work in exactly the same way, anywhere. You cannot really do that as things currently stand by using the standard DOM.
This is from 2011, and slightly out-of-date, but it's a list of some possible use cases for the component model: http://www.w3.org/2008/webapps/wiki/Component_Model_Use_Cases

Shadow dom in HTML

I've been hearing about Shadow DOM recently. While watching a video about the release of Angular 2 the presenter repeatedly made mention of Shadow DOM without clear expressions. What does Shadow DOM really mean?
The best explanation I've found is this from What the Heck is Shadow DOM? shown below:
Shadow DOM refers to the ability of the browser to include a subtree
of DOM elements into the rendering of a document, but not into the
main document DOM tree.
An important use case would be with video controls on a web page. The markup only shows a video tag, with some attributes and source tags. The addtional code for all the video operations to work is hidden in the Shadow DOM and not available to the rest of the page. The actual markup, javascript, and styles for the tag are encapsulated, which hides the implementation details of the video controls that each browser vendor has already written.
So while it's there in the DOM, its hidden from the page that renders it. So, to view the Shadow DOM, you can enable it under Dev Tools in Chrome.
The short answer is that the Shadow DOM is one of four technologies that make up Web Components.
For a definition, Web Components are: A component platform from the W3C that allows Web sites to be constructed from standardized building blocks. Web Components comprise Custom Elements, Shadow DOM and HTML Imports and Templates.
Shadow DOM is a technology of Web Components (although each can be used separately):
Custom Elements: is a capability for creating your own custom HTML tags and elements. They can have their own scripted behavior and CSS styling. They are part of Web Components but they can also be used by themselves.
HTML Templates: The HTML template element is a mechanism for holding client-side content that is not to be rendered when a page is loaded but may subsequently be instantiated during runtime using JavaScript. Think of a template as a content fragment that is being stored for subsequent use in the document.
Shadow DOM: provides encapsulation for the JavaScript, CSS, and templating in a Web Component. Shadow DOM makes it so these things remain separate from the DOM of the main document. You can also use Shadow DOM by itself, outside of a web component.
HTML Imports: is intended to be the packaging mechanism for Web Components, but you can also use HTML Imports by itself. You import an HTML file by using a tag in an HTML document.
See Introduction to the Shadow DOM.
It refers to the ability to create a "child" DOM completely sandboxed from the rest of the page. Useful for web components, reusable "widgets" which allow to not worry about their css/js affecting things they shouldn't. http://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/
Check out https://www.polymer-project.org/ if you want to see it in action.
Think of shadow DOM is as an encapsulated (private) DOM.
You can't access the shadow DOM in the manner you access regular DOM, like 'document.querySelector()'.
Let's say, you defined a reusable custom element, (which contains its DOM trees). Then you use the custom element within your app HTML.
Now, the DOM under (which is now called a "host element") has become a shadow DOM subtrees (under a shadow root), hidden from the parent structure!
I hope this help you a bit.

Why does jQuery Mobile use data-role attributes instead of classes?

This may be a naive question, but I'm learning jQuery Mobile and unsure why everything is related to a data-role attribute. It seems that even times when the role is related to the style, they are using data-role over class
I understand that for semantics, data-role makes sense in a lot of cases but it just seems to be abused here. Wouldn't that kind of lookup also be slower?
Why do they use data-role over class?
Thanks for any insight.
Why data
They could simply use role as an attribute (like other frameworks do), but this would make
the resulting HTML invalid. Therefore a data- is added to every attribute name.
Why not classes
I think the main reason for that is to separate view from logic as far as it is possible. In larger projects, CSS and JavaScript are not written by the same person.
It provides a lot of control over powerful styling techniques especially when combined with jquery ui. I use jquery mobile, I used their tool to easily make a theme roller and now when I use elements like data-role-header, footer listview. I have great looking pages with no effort. There are hundreds of data-role attributes you can bring into your code to easily create uniform, user friendly pages. I personally like the data-role - page attribute to create multiple views in a single HTML page. They are easy to use so the best way to learn about them is to play with them.
Please find the explanation of data-roles here.
data-role attribute is used to control the behaviour of the widget of element. For example in case of button you can use input type="button" (no data-role="button" attribute required in this case, as this is standard behaviour of this element) but you can use a element, and then you need to explicitly provide it:
So for me it's rather useful solution, as buttons behavior on mobile devices can be same for different elements. You just need to provide data-role attribute, and jQuery will do the rest for you.
This is the quotation from main jQuery Mobile website:
jQuery mobile framework takes the "write less, do more" mantra to the
next level: Instead of writing unique apps for each mobile device or
OS, the jQuery mobile framework allows you to design a single
highly-branded web site or application that will work on all popular
smartphone, tablet, and desktop platforms.
They want to style every control you have in the same way, so write less, do more approach is fulfilled. So jQuery Mobile adds same styling for all elements with the same role to make things look the same way, but it doesn't mean you can't change it. It just means that they care about good look of your website, and they are aware that every button should be similar to others.
Also the page I mentioned earlier says:
The jQuery Mobile framework uses HTML5 data- attributes to allow for
markup-based initialization and configuration of widgets.
So you are reading HTML and you know how elements will behave without looking to CSS file - which I think is cool if you're not front-end dev. Of course front-end dev can overwrite CSS, but he must follow the rules, e.g. if data-inline is set to true he should style it regarding that elements must naturally follow this rule (be inline).
jQueryMobile adds a load event handler to the page, which processes the DOM looking for various data-xxx attributes. When it finds those, it does more than just stylize the elements.
In many cases it creates a type of widget tied to the data-role. For example, a <div data-role="header"> is turned into a toolbar widget, the creation of which may extensively modify the DOM within that element.
For some of the simpler widgets, like buttons, folks have seen that not much happens other than some classes get added, so why not just shortcut the process and do that directly? That can work, but it isn't future-proof. At different points in history, different versions of jQM had created buttons with different DOM structures. So I personally think it's best not to shortcut jQM, and let it process the data-attributes as it sees fit.
That being said, it would still have been possible to create widgets identified by classes rather than data-attributes, which was how people used to do these things before jQM. But then there might be an expectation that there would be CSS associated with those classes as well. Use of the data- attributes makes it clear that this is a structural/role thing rather than just styling.

Why not use inline CSS if all the HTML+CSS is generated at runtime by javascript and no developer will need to work with css and html?

The only reasons I see on the internet to not to use inline-css is because of the separation of html and css & management, but if this is not a problem in my case I don't care I will use.
Another pro I can say is this: imagine you want to load a widget made by another user, you will only need to load 1 file, the javascript and not the css.
But it might have other problems?
thanks
If you read your question again, you have answered it yourself. There is a reason for the "separation" of html and CSS. Because at some point in time, you will eventually want to change the look of what you have coded up. These are the times when having a separate CSS file would be very helpful so you are only ever making changes in one place and not throughout your application.
EDIT
Another usefulness of having the CSS separate is the caching. Most of the modern browsers cache the CSS files. This means there are less round-trips to the server and quicker response times. I'm not sure if same is the case for JavaScript, because JavaScript files would be cached, but the client browser will have to execute the code every time it loads.
I think this is a good question that is worth exploring. I don't think there is a performance or standards-based argument for not using inline CSS - it works perfectly well - the only (though considerable) argument for separated CSS is for maintainability / readability. And so if you are generating CSS from JavaScript, generating it inline is just as sound as any other way.
In fact, DOM APIs in general expose much simpler methods for assigning styles directly to elements ( https://developer.mozilla.org/en/DOM/element.style ) than for creating new stylesheets. Therefore almost all JavaScript libraries, like jQuery, when they have to manipulate styles they do it by adding inline styles to an element.
Having said that, I have never before seen a situation where the mark-up and styling for a whole page was generated with JavaScript. I would expect this to be rather inefficient. I can see that if you have a web application where all content is pulled in through Ajax (a perfectly good solution) then you might write a fair bit of the mark-up with JavaScript, but still it would be better/more efficient to load most of the surrounding mark-up for your content in the initial page load, and then use JavaScript to swap out content within existing elements.
In any case, I would recommend that you keep most of your CSS in an external stylesheet with relevant classes already defined, so that all your JavaScript does is create elements with the correct class. This would have a performance advantage and would also mean that all your style information was located in one place, and is separate from your JavaScript, which would make your code easier to maintain.
It's OK to use inline css. (in this specifice case)

Categories

Resources