In Google Chrome’s Developer Tools, I see a #shadow-root right under <html lang="en"> tag. what does it do and what is it used for? I don’t see it in Firefox nor in IE; only in Chrome, is this a special feature?
If I open it, it shows <head> and <body> and a link beside named reveal, by clicking, it points to the <head> and <body>, nothing else.
This is a special indicator that a Shadow DOM exists. These have existed for years, but developers have never been given APIs into it until recently. Chrome has had this functionality for a while, other browsers are still catching up. It can be toggled in the DevTools Settings under the "Elements" section. Uncheck the "Show User Agent Shadow DOM". This will at least hide away any Shadow DOMs created internally (like select elements.) I am unsure right away if it affects user-created ones, such as custom elements.
These come up in things like iframes as well, where you have a separate DOM tree nested inside of another.
The Shadow DOM is simply saying that some part of the page, has its own DOM within it. Styles and scripting can be scoped within that element so what runs in it only executes in that boundary.
This is one of the primary pieces needed for Web Components to work. Which is a new technology allowing developers to build their own encapsulated components that developers can use just like any other HTML element.
As an example of Shadow DOM, when you have a <video> tag on a web page, its shown as just one tag in the main DOM, but if you enable Shadow DOM, you will be able to see the video player's HTML(player DOM).
This is explained aptly in this article, http://webcomponents.org/articles/introduction-to-shadow-dom/
In the case of web components, there is a fundamental problem that makes widgets built out of HTML and JavaScript hard to use.
Problem: The DOM tree inside a widget isn’t encapsulated from the rest of the page. This lack of encapsulation means your document stylesheet might accidentally apply to parts inside the widget; your JavaScript might accidentally modify parts inside the widget; your IDs might overlap with IDs inside the widget and so on.
Shadow DOM addresses the DOM tree encapsulation problem.
For example, if you had markup like this:
<button>Hello, world!</button>
<script>
var host = document.querySelector('button');
var root = host.createShadowRoot();
root.textContent = 'こんにちは、影の世界!';
</script>
then instead of
Hello, world!
your page looks like
こんにちは、影の世界!
Not only that, if JavaScript on the page asks what the button’s textContent is, it isn’t going to get “こんにちは、影の世界!”, but “Hello, world!” because the DOM subtree under the shadow root is encapsulated.
NOTE: I have picked up above content from https://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/ as it helped me understand shadow DOM a little better than answers already here. I have added relevant content here so that it helps others but do take a look at the link for detailed discussion on same.
Related
In order to construct the render-tree, the browser requires both DOM and CSSOM. CSSOM can only be constructed, once the CSS is downloaded. In essence, once the CSS is downloaded the page should be rendered alright. But, why do we see Flash Of Unstyled Content(FOUC) on the page? In what time window does the browser show unstyled content?
Please help me understand this.
Ref:
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css
I still don’t agree with the accepted answer, because according to the critical rendering path nothing could be painted on a screen under normal circumstances until the render tree (DOM + CSSOM) is build.
I find that this Google article is somewhat confusing at the first glance but it becomes less contradictory if we take a look carefully at the following statement:
“What would happen if we try to render a typical page without blocking rendering on CSS?”. (Then NY Times FOUC as example of behaviour without blocking rendering follows.)
The thing is historically FOUC happened for different reasons in different browsers versions and on different circumstances.
For example according to this ancient article we could encounter FOUC in web kit if some JS attempted to access properties that have layout/style information.
Web Kit has the opposite behavior and will continue parsing a page
even after a style sheet directive has been encountered so that style
sheet and script loads can be parallelized. That way everything can be
ready for display much earlier.
The problem with this behavior is what to do when a script attempts to
access a property that involves having accurate layout/style
information to answer. Shipping Safari’s current behavior when this
happens is as follows: it will go ahead and lay out what it’s got even
though it doesn’t have the style sheet yet. It will also display it.
This means you see FOUC whenever a script tries to access properties
like scrollHeight or offsetWidth before the style sheet has loaded.
Therefore when we say “FOUC happens” there should be explications on
what circumstances and in what browser it happens, because it doesn’t
“just” happens everywhere.
The basic reason for FOUC is -> new/different styles are getting applied after elements were already painted on screen.
Now comes the question -> can FOUC happens when page is loading and page markup itself includes <link> tag for external css, at high level it appears this should not happen as css is render blocking and there should be no case where any element can get rendered without its computed styles, but it(FOUC) happens on page load in certain conditions.
Main reason for that is dom tree construction is incremental i.e. without having the full html markup browser can render partial html whatever is downloaded till the given point of time.
To understand that lets take example of following html -
<!DOCTYPE html>
<html lang="en">
<body>
<100 html tags block 1 />
<link href="css1" />
<100 html tags block 2 />
<link href="css2" />
<100 html tags block 3 />
<link href="css3" />
</body>
</html>
First 100 tags are converted to dom and with help of existing cssom(which was construed from user agent stylesheets) forms render tree, which will be painted and will be visible to user.
After that parsing will be blocked till css1 is downloaded and new cssom is created with useragent+css1 styles.
And with new render tree(formed via old dom + new cssom) html block 1 will be updated(FOUC)
Then html block 2 is similarly processed as it gets downloaded after that.
Now same things as step 3 is repeated with block 2 and block 3
And same goes on till the end of document
Credits - https://medium.com/jspoint/how-the-browser-renders-a-web-page-dom-cssom-and-rendering-df10531c9969
This should help.
DOM is constructed
If we are still waiting for the CSSOM to be constructed, then we see FOUC
CSSOM is constructed
DOM and CSSOM are coalesced into the Render Tree which renders the DOM with CSS (styled content)
So the browser shows FOUC when waiting for CSS. Once the CSS is loaded, the DOM and CSSOM are merged into one tree, called the Render Tree and this is styled content.
The very fact that HTML is rendered unstyled is clear evidence that the HTML can render in the browser separately from the render tree, thus causing FOUC.
According to the Google article, the NY times site shows FOUC until the CSSOM is constructed and then the render tree is rendered. This demonstrates that rendering the render tree is different from rendering the DOM tree. The DOM tree is rendered, but unloaded CSS blocks the render tree from being rendered (note the difference). This is why the FOUC shows before the CSS is unblocked and the render tree shows.
In my opinion, this is the most comprehensive talk about this subject out there, from David Baron, Chief Engineer at Mozilla: https://vimeo.com/103108124
I have made a small popup window that shows up at the bottom of the page (like a recommendation system). But whenever I embed my script to any of the client's website, it disturbs my CSS. Like the CSS which is on the client's website overshadows my CSS and this causes me to fix my CSS for each client. Is there a fix that I will have to install on my code?
Please help
Thanks
This is due to overlapping CSS properties of client's and your newly developed. I recommend you to inspect element of google chrome's very nice feature. You can individually identify your overlapping properties. If this is too much complex. Like James commented give a new id to your pop-up menu, which will separate your pop-up CSS from all other components on your web page
On of the ways I heard about is Shadow Dom, and in this article it describe it and at the beginning of the article he listed the problem in brief: http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/
But there is a fundamental problem that makes widgets built out of
HTML and JavaScript hard to use: The DOM tree inside a widget isn’t
encapsulated from the rest of the page. This lack of encapsulation
means your document stylesheet might accidentally apply to parts
inside the widget; your JavaScript might accidentally modify parts
inside the widget; your IDs might overlap with IDs inside the widget;
and so on.
Else which I did my self long time ago is: to name all your ids, classes with a special names for example 'mywebsite.myclass' this may minimize the issue. and I saw this way is used by many bookmarklets which import html,css and javascript to user opened page.
"All browsers" is a lot of browsers :P
CSS is going to get interesting soon thanks to shadow DOM. You are going to be able to create a web component that is completely isolated, DOM and CSS, from the rest of the document, which is exactly what you want.
Obviously, it's not in place in al browsers (only in Chrome at the time of me writing this). Meanwhile, this is what I would do:
Use shadow DOM components if available
Anyway, manually name-space everything you use (CSS classes, JavaScript, etc)
Try to use custom elements for everything. (that way, there's less risk of your e.g. <h2>s being styled by outer CSSs)
As a last resource, use very specific selectors (look up CSS specificity), and use !important. Just to be clear: never do this routinely!
Most of that stuff will fail for some value of "All browsers". You'll have to compromise somewhere, I guess.
Yes you can reset your div styles.
Something like this:
div.your-popup * {
/* your reset */
}
And try to set !important to styles or put them inline.
In addition create unique class names that no one can override it.
P.S. http://www.cssreset.com/
I want to validate a custom polymer element. To do this, I want in javascript to access all my nested polymer elements to see if they are valids.
I can't find an easy way to do this.
this.querySelectorAll does not find my inputs that are nested in other polymer elements. It seems I can't use "/deep/" in these selectors.
Is there an easy way to do this ? Or do I have to do a recursive javascript methods that will call a querySelectorAll in all elements with shadow roots ?? (I guess performances will get ugly...)
Thanks for your help.
If there is no fast solution, I will probably try the other way around (have my inputs register to the parent)
Answer:
element.querySelectorAll() will find some elements when using /deep/, however, it only goes so far (1 shadow dom level). This would indeed necessitate recursive calls from each ElementNode.
Note:
This type of behavior largely goes against the core tenets of HTML (i.e. that the web page works no matter how well-formed the content is). In other words, all elements are valid no matter their placement.
As an example, I have made a custom element that only renders specific child elements and hides all others. This still keeps in line with the above tenet, as an element's base rendering is controlled by the element/agent, but allows for the developer/designer to customize its presentation aside from the standard presentation.
Google suggests to use very important CSS inline in head and other CSS inside <noscript><link rel="stylesheet" href="small.css"></noscript>.
This raises few questions in my mind:
How to prioritize CSS in two files. Everything for that page looks important. Display, font etc. If I move it to bottom then how it helps page render. Wont it cause repaint, etc?
Is that CSS is required after Document ready event? Got it from here.
How 'CSS can' go inside <noscript></noscript>, which is for script? Will it work when JavaScript is enabled? Is it browsers compatible?
Reference
Based on my reading of the link given in the question:
Choose which CSS declarations are inlined based on eliminating the Flash-of-Unstyled-Content effect. So, ensure that all page elements are the correct size and colour. (Of course, this will be impossible if you use web-fonts.)
Since the CSS which is not inlined is deferrable, you can load it whenever makes sense. Loading it on DOMContentReady, in my opinion, goes against the point of this optimisation: launching new HTTP requests before the document is completely loaded will potentially slow the rest of the page load. Also, see my next point:
The example shows the CSS in a noscript tag as a fallback. Below the example, the page states
The original small.css is loaded after onload of the page.
i.e. using javascript.
If I could add my own personal opinion to this piece:
this optimisation seems especially harmful to code readability: style sheets don't belong in noscript tags and, as pointed out in the comments, it doesn't pass validation.
It will break any potential future enhancements to HTTP (or other protocol) requests, since the network transaction is hard-coded through javascript.
Finally, under what circumstances would you get a performance gain? Perhaps if your page loads a lot of initially-hidden content; however I would hope that the browser itself is able to optimise the page load better than this hack can.
Take this with a grain of salt, however. I would hesitate to say that Google doesn't know what they're doing.
Edit: note on flash-of-unstyled-content (abbreviated FOUC)
Say you a block of text spanning multiple lines, and includes some text with custom styling, say <span class="my-class">. Now, say that your CSS will set .my-class { font-weight:bold }. If that CSS is not part of the inline style sheet, .my-class will suddenly become bold after the deferred loading has finished. The text block may reflow, and might also change size if it requires an extra line.
So, rather than a flash of totally-unstyled content, you have a flash of partly-styled content.
For this reason you should be careful when considering what CSS is deferred. A safe approach would be to only defer CSS which is used to display content which is itself deferred, for example hidden elements which are displayed after user interaction.
I am working on an app for doing screen scraping of small portions of external web pages (not an entire page, just a small subset of it).
So I have the code working perfectly for scraping the html, but my problem is that I want to scrape not just the raw html, but also the CSS styles used to format the section of the page I am extracting, so I can display on a new page with it's original formatting intact.
If you are familiar with firebug, it is able to display which CSS styles are applicable to the specific subset of the page you have highlighted, so if I could figure out a way to do that, then I could just use those styles when displaying the content on my new page. But I have no idea how to do this........
Today I needed to scrape Facebook share dialogs to be used as dynamic preview samples in our app builder for facebook apps. I've taken Firebug 1.5 codebase and added a new context menu option "Copy HTML with inlined styles". I've copied their getElementHTML function from lib.js and modified it to do this:
remove class, id and style attributes
remove onclick and similar javascript handlers
remove all data-something attributes
remove explicit hrefs and replace them with "#"
replace all block level elements with div and inline element with span (to prevent inheriting styles on target page)
absolutize relative urls
inline all applied non-default css atributes into brand new style attribute
reduce inline style bloat by considering styling parent/child inheritance by traversion DOM tree up
indent output
It works well for simpler pages, but the solution is not 100% robust because of bugs in Firebug (or Firefox?). But it is definitely usable when operated by a web developer who can debug and fix all quirks.
Problems I've found so far:
sometimes clear css property is not emitted (it breaks layout pretty badly)
:hover and other pseudo-classes cannot be captured this way
firefox keeps only mozilla specific css properties/values in it's model, so for example you lose -webkit-border-radius, because this was skipped by CSS parser
Anyway, this solution saved lot of my time. Originally I was manually selecting pieces of their stylesheets and doing manual selection and postprocessing. It was slow, boring and polluted our class namespace. Now I'm able to scrape facebook markup in minutes instead of hours and exported markup does not interfere with the rest of the page.
A good start would be the following: make a pass through the patch of HTML you plan to extract, collecting each element (and its ID/classes/inline styles) to an array. Grab the styles for those element IDs & classes from the page's stylesheets immediately.
Then, from the outermost element(s) in the target patch, work your way up through the rest of the elements in the DOM in a similar fashion, eventually all the way up to the body and HTML elements, comparing against your initial array and collecting any styles that weren't declared within the target patch or its applied styles.
You'll also want to check for any * declarations and grab those as well. Then, make sure when you're reapplying the styles to your eventual output you do so in the right order, as you collected them from low-to-high in the DOM hierarchy and they'll need to be reapplied high-to-low.
A quick hack would be to pull down their CSS file and apply it to the page you are using to display the data. To avoid any interference you could load the page into an IFrame wherever you need to display it. Of course, I have to question the intention of this code. Are you allowed to republish the information you are scraping?
If you have any way to determine the "computed style" then you could effectively throw away the style sheet and, ****gasp****, apply inline styles using all of the computed styles' properties.
But I don't recommend this. It will be very bloated.