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.
Related
This question already has answers here:
How can I write 'a:hover' in inline CSS?
(24 answers)
Closed 1 year ago.
Is it possible to create inline pseudo styles?
For instance, can I do something like the following?
Coding Horror
The reason behind this is I'm developing a .NET library that creates UI elements. I want to produce HTML elements that can have their hover state set without the use of an external style sheet.
Unfortunately no, you can't implement hover effects using inline CSS.
A (poor) work-around for this problem is to have your controls render style blocks when they are rendered. For example, your control could render as:
<style type="text/css">
.custom-class { background-color:green; }
.custom-class:hover { background-color:Red; }
</style>
Coding Horror
If you could force your users to drop a "style control" at the top of their pages you could render all your custom classes there instead of rendering them next to each control, which would be a very, very bad thing (browsers will restart rendering every time they come across a style block, having a lot of style blocks scattered around your page will cause slow rendering).
Unfortunately there's no elegant solution to this problem.
This is kind of a Catch-22 situation.
On one hand, you can add a style block right before where your element is inserted into the page, but Chris Pebble points out the problems with that. (If you decide on this, make sure you pick unique IDs for your Elements so your selectors don't accidentally select or style anything else).
On the other hand, you could do something like this:
...
But, that's nasty in its own right as it ties together markup, presentation, behavior, and a whole bunch of other things.
You could also inject a stylesheet into the page by writing out a link tag or manipulating document.stylesheets, but that's going to trigger a download.
I've usually seen the first method (adding a style block) done on large. "Modular" portal sites do this sort of thing, so maybe it's the de-facto standard (it is at least more readable and maybe easier to maintain than cramming JavaScript in there?). The JavaScript method seems to have the least impact on the DOM and the overall page as you're keeping your presentation to yourself.
This is one of those front-end dev morasses where every answer you choose is wrong to some extent, so weigh the options and pick what's easiest for you to build and maintain.
I would dynamically create a CSS file as I parse all the controls, and I would add a server side attribute to the controls that contained the hover or other pseudoclass styles.
<a style="color:blue" styleHover="color:blue" id="a1">Click!</a>
Your code can look for these attributes and generate a css file on the fly
#a1:hover {
color:blue
}
I don't know if .NET allows for you to do this type of parsing of the attributes, but I do something similar in a framework I created for php.
Hacss effectively brings pseudo-selectors to inline styles.
You could send a static stylesheet with the built page that uses css variables to control specific states and generate those in your script. Sadly you have to do this for every state and property you want to use.
* {
background-color: var(--n-background-color);
}
:hover {
background-color: var(--hover-background-color);
}
Coding Horror
To avoid using !important we cannot define the normal state inline directly.
Or you can use jQuery's hover function and set the background color.
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/
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.
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.
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.