How to scope internal Vue application css from rest of the website? - javascript

I need to create a "plugin" that contains a user interface which will be displayed on many different vendor websites. This is a CMS agnostic plugin. I cannot use an iframe for SEO reasons. I need to isolate the plugin's css (and maybe js) from the rest of the website, and stop the rest of the website's css from getting to this plugin. How can I do this?
Update:
Ok, so I've asked a question that's a little too specific to my setup/tech. The question should have been: How do I isolate an html element from the rest of the document styles? This is answered here;
New Question: How do I scope Vue CSS so that it doesn't propagate up, but propagates to child components?
E.g I have the main Vue component which includes bootstrap.scss, i need that to apply to all child components, but I don't want it to leak into the main website. Adding scoped to style stops the leak upward, but I want it to apply to child classes as well.

Ok, I've figured it out.
Pretty simple really, combined with this answer to prevent parent -> child inheritance. I scoped all Vue css into #app { /*styles*/ } INCLUDING the bootstrap import. E.g.
<style type="text/scss" lang="scss">
#app {
#import '../node_modules/bootstrap/scss/bootstrap';
// rest of vue global styles go here.
// child components may use scoped
}
</style>
Note: I am NOT using scoped attribute on the root vue component.

I think this is what you’re looking for. In your .vue file you can add style tags to the template, then Vue will create Shadow DOM styles that only apply to your application. In the final product the styles are rendered via a data-v attribute to prevent class name conflicts.
https://vue-loader.vuejs.org/en/features/scoped-css.html
(Copied from my reddit answer)
https://www.reddit.com/r/vuejs/comments/76ss46/how_to_isolate_a_vue_application_from_the_rest_of/?st=J8UMA1JQ&sh=c3ebf5b1

Related

How can I scope CSS element selectors to component level in React?

Is there a way to scope all CSS selectors in a component to that component specifically? As far as I can tell various libraries that address the issue only work for class or ID selectors.
Our react front end uses some components owned by external teams that we fetch from a CDN. We use CSS modules to make class names unique but have issues with other teams using element selectors which are globally scoped and affect the rest of the page.

Can I detect if a specific CSS custom variable exists in the loaded styles?

I am creating some custom web components. One of the components is a light/dark theme switcher. However, this relies on a specific stylesheet being loaded.
I would like to output a warning if the correct stylesheet has not been loaded.
But, users have several different ways of loading stylesheets (e.g. link tag, #import statement, etc) and so it is not guaranteed that they will have loaded the correct sheet.
The stylesheet that is needed has some pretty specific custom variables and named styles in it. So I would like to know if there is any way from JavaScript (inside my web component), to check whether one of those variables or style names exists in the stylesheets loaded to the current page.
Many thanks to RedRex for giving me the pointer. Custom variables are accessible but not from the document.style. You have to use getComputedStyle.
So, in my web component Class, I have a connectedCallback function that runs whenever an instance of the component is added to the page.
connectedCallback() {
// Is the correct stylesheet loaded?
if ( !getComputedStyle(this).getPropertyValue('--uib-css').includes('uib-brand') )
console.warn('[uib-theme-changer] WARNING: It appears that you are not using uibuilder\'s uib-brand.css stylesheet. This component may not work as expected.')
} // ---- end of connectedCallback ---- //
In the CSS file, I have
:root, :root.light {
color-scheme: light dark;
/* Create a checkable var - helps web components know if this stylesheet is loaded.
* NOTE: no space between : and text! */
--uib-css:uib-brand;
}
Perhaps worth noting that web components are designed to limit the interaction between the light-DOM CSS and the shadowDom CSS. However, custom variables are designed to flow into your component.
 
Footnote: For the curious, I am writing some custom web components that will play nice with Node-RED and node-red-contrib-uibuilder.

Apply css style to all primeng dialogs in my angular app

I am using prime ng dialog all over my angular application. I can change each specific dialog style by using ng-deep. For eg I have contact us page for which I have these files:
contact.html
contact.component.ts
contact.css
So I place the below css in contact.css and it changes the contact us dialog title bar color.
:host ::ng-deep .ui-dialog .ui-dialog-titlebar{
background-color: red
}
I want to do this for all the dialogs in my application, how can I do this? I placed the same css in style.css file in src folder and it didn't work.
So angular components by default employ a very handy strategy of Style Encapsulation which makes it so that styles don't bleed out into other components and cause unwanted effects.
You can utilize ng-deep like you have to allow styles defined within it to be inherited by child components of where it's specified.
However for things to be globally inherited you'll want to define them highest up in the order of inception so those styles cascade down to selectors below. In a default angular application that's not using SCSS or another pre-processor one of the easiest ways to do this is to add them to one of the first files initialized that hosts the child components such as index.html or app.component to allow components initialized afterwards to inherit them when they're rendered.
Hope this helps, cheers!

Shadow DOM/Web component styling in Ionic 4

I'm trying to understand how and where ionic 4 is injecting the styling for the web components into the dom. I'm not interested in changing it via the CSS variables but I want to be able to inspect the component and see where the styling is coming from. For example on https://ionicframework.com/docs/demos/api/alert/index.html?ionic:mode=ios
If you inspect the button:
I can see the stlying being applied but I can't see where all the styling is coming from, it's not in the css bundle, style tags on the page or directly on the element or applied to the shadow-root. Normally the host styling is part of the component e.g.
So where is the :host styling being defined and how/where is it being injected into the DOM?
So as far as I know all the styles you apply to your component are usually set innerHTML. You already found the style tag which is the first tag after the component. This is super full with stylings as always thats why you usually see just a snippet. That depends on the browser but to see all the stylings you may have to do a double click into the stylings between the style tags.
Usually when I want to read something like this I copy it into my editor and take a look there:
As you can see all your stylings are defined there. Stenciljs also load some general stylings to make sure everything looks proper. These are instantiated into your head section:
So I think Ionic 4 is using: https://developers.google.com/web/updates/2019/02/constructable-stylesheets
Which is why the styling isn't visible directly in the DOM. Credit to Fraser for working this out.

Can Shadow DOM elements inherit CSS?

I was listening to this episode of JavaScript Jabber:
http://javascriptjabber.com/120-jsj-google-polymer-with-rob-dodson-and-eric-bidelman/
At one point Rob says:
And everyone has this first inclination, because it makes so much sense. You’re like, “Bootstrap is components. I’m just going to make them into tags.” But then you run into the fact that the Bootstrap style sheet is just one big long style sheet that was written assuming that it could touch every part of the document. And when you are suddenly scoping bits of the markup, scoping it so that the CSS can’t reach it, the CSS would actually have to be in the Shadow DOM with it and you would have to write that element from the ground up, that’s where people I think get really confused and really frustrated initially.
This made me wonder, how would you solve this problem with Web Components? Is there a way for Shadow DOM templates to inherit common styles, or would you have to repeat shared CSS for each separate component? Or something else?
Note: the substance of the answer below is no longer relevant, as the features discussed have been deprecated for some time. Don't use the sample code, but feel free to take a peek into the Internet past.
In a complete Shadow DOM implementation, CSS has a ::shadow pseudo-class, and also the /deep/ combinator.
The ::shadow pseudo-class lets you break into the shadow DOM under an element, and it matches the shadow root. The /deep/ combinator effectively opens up the shadow DOM completely.
Thus, if you had a <x-foo> element with <span> elements inside, you could make them red with
x-foo::shadow span { color: red; }
Or make all <spans> in any shadow DOM red:
body /deep/ span { color: red; }
Whatever hacks were necessary in the past, the current state of the shadow dom / CSS is that you can link to external stylesheets. More info at MDN: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM#Internal_versus_external_styles
You could, then, have some sort of utility stylesheet (Tailwind or similar) that all of your components reference, so you don't duplicate CSS. In theory, that CSS file would get downloaded once, cached, and then the custom elements would each be able to use the classes in it (as long as they each link to it).
Take a look at this lesser known method:
The <core-style> Polymer element
You can define the styles in an html import file:
<core-style id="x-test">
:host {
backgound-color: steelblue;
}
</core-style>
And then you can use them in more than 1 element:
<polymer-element name="x-test" noscript>
<template>
<core-style ref="x-test"></core-style>
<content></content>
</template>
</polymer-element>
In this well written article you can read more about how to use the technique.
However, a disadvantage I can think of is the impossibility of using SASS with this technique, since the styles are defined inside a <core-style> tag and not inside a <style> element, and there isn't a clear way to import an external stylesheet.
I think I understand what you ask about. You can use link in every custom element to include your main styles or extend existing element that includes it. For example (using Polymer):
<polymer-element name="ui-button" noscript>
<template>
<link rel="stylesheet" href="main.css"/>
<div class="class-from-main" style="">
<content></content>
</div>
</template>
</polymer-element>
I think it worth reading to you: https://github.com/necolas/normalize.css/issues/408
Here's one example of it working : http://jsbin.com/zayih/1/edit?html,css,output
Though it does not seem to work when targeting it with #placeholder
Turn on "Show user agent shadow DOM" in Chrome devtools config tab, then inspect the <input> to see what I mean

Categories