This answer mentions that /deep/ can be used to select elements across shadow DOM boundaries. However, I already have a stylesheet from a theme my client bought. Is it possible to make the selectors in the stylesheet work across shadow DOM boundaries without changing the stylesheets themselves? Other places suggest using applyAuthorStyles but this appears to be removed from the shadow DOM specification.
Since /deep/ and ::shadow selectors have been deprecated and you don't want to modify existing stylesheet anyway, I'd suggest you to use css #imports in your component templates(which I am assuming you'll be cloning and using as shadow roots) to include this external stylesheet.
This will essentially make this style local to your components and will be available inside shadow-dom.
If you are worried about performance implications, see this answer on same.
tl;dr;
With browser caching, there's essentially no penalty to so many
imports, in fact it is likely faster than cascading the styles through
multiple shadow trees using piercers.
Related
I'm actually using the FontAwesome 5 package, using the SVG+JS implementation with the "data-search-pseudo-elements" option.
I'm in a context where I use a "Select2" plug-in to display a <select> element, which is containing nearly 600 options (for a timezone selection). But when I try to open the select to choose an option, it takes a very very long time to open (which doesn't occur when using the CSS framework, or when pseudo-elements are disabled)!
A little look in browser performances panel seems to show that it's the FontAwesome script which is responsible of this, while there is no pseudo-element in the elements generated by Select2.
Is there any way to improve FontAwesome performance, or to avoid its activation for some HTML elements?
As long as you have data-search-pseudo-elements enabled, Font Awesome will scan the DOM when changes are made, looking for any pseudo-elements that represent icons that should be converted into <svg> elements.
Unfortunately, a scenario like you've described is the Achilles heel of this feature. Scanning the DOM for all possible pseudo-elements can be slow when there are many DOM elements. And the Mutation Observer causes re-scans to occur whenever the DOM changes--which is what sounds like is happening when you open that select control.
So it's probably best to avoid SVG/JS with pseudo-elements in a situation like this.
While I would not recommend putting more effort into trying a work around, if you're up against a wall and for some reason have a requirement to continue using SVG/JS and pseudo-elements together like this, then here are two possibilities:
If you don't need the MutationObserver to watch for changes, then you could disable it altogether using the Configuration API. For example, add data-observe-mutations="false" to your <script> tag.
If you do need the MutationObserver to watch for changes elsewhere in the DOM, but not on this select control, then after disabling the MutationObserver on load (using the above), you could kick it off programmatically on a smaller region of the DOM using the dom.watch() API with a observeMutationsRoot parameter that is more narrowly scoped. By default, the MutationObserver, when enabled, scans everything under a root of document.body, but this is a way that you can make it work on a smaller region of the DOM.
If you have a requirement to support pseudo-elements, and especially if you need to support that in a DOM with many elements, and especially especially if the DOM is changing a lot, it's almost certainly going to be best for you to use the CSS/Webfont technology.
As pointed out here:
Because of the isolation of styles, which is a feature of Shadow DOM, you cannot define a global CSS rule that will be applied in the Shadow DOM scope.
Is there any way to define simple CSS classes globally in some global styles.css file (for example) that we can use in all kinds of places and re-use them in individual components?
Currently, the simple answer would be to add a corresponding <link href="styles.css"> tag to every single component that we define. This has been proposed here to allow web components use bootstrap classes, and again here to support ionic. Is that a good approach? Would that not be terrible performance-wise, if we included big styles.css in tens or hundreds of components?
Constructable Stylesheets are a proposal to solve exactly that problem.
In a nutshell, it's a way to share the same stylesheet across components without requesting the stylesheet each time. Currently it's Chrome only, but there is a polyfill, and, Firefox at least, seem to support this proposal.
Maybe it could help you. From this link
https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM
You have the following:
Internal versus external styles
In the above example we apply style to the Shadow DOM using a
element, but it is perfectly possible to do it by referencing an
external stylesheet from a element instead.
For example, take a look at this code from our
popup-info-box-external-stylesheet example (see the source code):
// Apply external styles to the shadow dom
const linkElem = document.createElement('link');
linkElem.setAttribute('rel', 'stylesheet');
linkElem.setAttribute('href', 'style.css');
// Attach the created element to the shadow dom
shadow.appendChild(linkElem);
Note that elements do not block paint of the shadow root, so
there may be a flash of unstyled content (FOUC) while the stylesheet
loads.
Many modern browsers implement an optimization for tags either
cloned from a common node or that have identical text, to allow them
to share a single backing stylesheet. With this optimization the
performance of external and internal styles should be similar.
To make it as independent and modular as possible, I would propose something like that:
let myStyles = querySelector('rel[href="style.css"]');
shadowDOM.appendChild(myStyles);
Normally, you don't have another option except of adding the styles directly to the shadow DOM.
Is there any harm if custom tags are used and created based on one's choice?
like the one below
<hello>hi there!</hello>
I tried using CSS
hello{
color:red;font-family:arial;
}
The above code works
I have used the above and also can add CSS. is there any harm of doing this, or the CSS features these won't support?
This is purely out of curiosity so don't suggest CSS edits or solutions please.
Why you can't make up elements
It is not valid HTML. Therefore how it behaves will be unpredictable.
It may work in some browsers, currently, but if any of your users visit your site on a different browser, they may get a totally different experience. Further to that, support could be dropped, or change at any time without warning.
Other options for custom elements
It is actually possible to define your own Document Type Definition (DTD), however that too is not a good idea.
Your best bet is to either stick with normal, well-supported HTML elements (see here for list of valid elements), or to use a web component framework, such as Vue, Angular or React, for custom elements/ components.
Don't forget, that you can add the class attribute (as well as others) to any element for styling, so for your use-case, there isn't any need to have additional elements.
I'm currently working on a Polymer element for Prism.js (a syntax highlighter). The element is hosted here and is also in a GitHub repo. What I'm trying to do is allow a user to set an attribute theme which decides which theme file we pull in. A user should be able to set a different theme per element with those styles being correctly scoped.
For example, if you configure the element with <prism-js theme="tomorrow">, when the element initializes we read in the theme value and pull in prism-tomorrow.css by injecting it via an #import. If I have another instance <prism-js theme="coy">, the themes pulled in for each element shouldn't clash.
Unfortunately, although the output for this is correct in Canary (the styles for each element don't clash)..
The styles aren't scoped and clobber each other in Chrome stable:
I'm wondering if there's a reliable way to approach this problem.
To date I have attempted to:
Inject my styles with the scoped attribute - this either isn't supported or didn't work
Inject a link to the stylesheet which is appended to my shadowRoot - this had the same problem of styles clashing
Use shimStyling - same issue
Work against my template's stylesheet as per the Polymer docs:
var sheet = document.querySelector('style').sheet;
var hostRules = sheet.cssRules[0];
hostRules.cssText = '#import url("' + this.themepath + '");</style>';
Alternatively, I'm wondering if it is possible set up my element so that I can update {{theme}} in my template's #import as follows:
<style>
:host { display: block; };
#import 'bower_components/prismjs/prism-{{theme}}.css';
</style>
Though, I'm unsure if getting that to work would solve my scoping issues either. Unfortunately inlining all of the themes is not an option. Any ideas? :)
Sadly, it may not be practical to achieve per-instance theme selection under the ShadowDOM polyfill as it is today.
The CSS scoping available to native ShadowRoot is quite difficult to polyfill. Today the polyfill does lots of tricks and translations in order to provide some scoping while still remaining efficient.
However, there are two categories of scoping issues that are problematic:
per-instance scoping (today the CSS shim operates per-type)
lower-bound encapsulation (an element's styles can leak into other elements in it's subtree)
There are still a lot of things that work well given these constraints, but, in particular, consuming CSS like you want to do is not well supported.
Work is under way to explore imperative support for (simulated) per-instance scoping via the CSS shim. I will endeavor to update this issue if something lands.
Suppose A.css styles B.html. What tools/techniques are there to programmatically reduce the size of A.css while holding its styling effects on B.html constant? Here are some techniques I would imagine such a tool using:
Remove redundancies in A.css. For example, if the same class is defined twice you can remove the second definition without affecting semantics. This seems pretty easy.
Remove style definitions that aren't used. Does A.css style any elements that don't appear in B.html? If so, remove them.
Combine styles where appropriate. If A.css defines styles for div.x and div.y and every div that happens to have class x also has class y, one could combine the class definitions in A.css.
A different strategy would be to have a tool that examines the computed styles of each element in a piece of styled HTML and spits out the minimal style sheet that would preserve the computed styles. Does something like this exist?
UPDATE
Let me explain how I got in this situation. The CSS file in question is for an email, and it was created by basically copying a similar CSS file that we used in an associated web page. Because the HTML in the email is a proper subset of the HTML in the web page from which the CSS came, some of the CSS in the email is superfluous.
Generally you just remove all unnecessary whitespace. Remember to keep the original as well, so you don't lose readability when editing the site later.
I think making sure css files are gzipped by the webserver is your biggest bandwidth saver.
"Does something like this exist?"
Of course. See the CSS Tidy tool.
I do not believe that it removes unused css, though. See Sitepoint's Dust Me Selectors for that.
Unless you have an usually large CSS file, I would opt for readability and modifiability of the CSS file rather than having a smaller CSS file. Since CSS files are static (for the most part), most browsers will do a really good job of caching them. While all your suggestions are good ones, combining things that are the same now for different document elements can wreak havoc in the future when you only want to change one of those items.
I'm not aware of tools to remove redundant styles, but if you want to reduce file size for performance reasons there are several minifing tools out there:
See:
The art of Scaling
A better CSS minifier
A good idea is to compress your css.
This isn't zip-style compressing, it's actually re-writing the CSS (aka minification).
Of course, you can use mod_gzip or mod_deflate as well.
OK, you don't want a small file for the KB (using gzip compression is more effective!) but to prune the obsolete styles, which indeed would improve maintenance.
I don't know if the ideal tool you want exists, but Firebug (an extension for Firefox) can tell you want are the CSS elements used by a given HTML element. Not automated, but still a precious tool.
You can also edit the live CSS, to see if removing a style element alters the HTML page.