This article can help. It covers everything from styling and customizing Ionic 4 components, to building custom web components with Stencil and then use them in your Ionic 4 projects (or any other framework, as web components are framework agnostic!).
Thank you for the Good Tutorial. But i really hate this approach (CSS4 Variables in Web Components). For me there should be an option to disable the Shadow Stuff for Web Components.
The Problem ist that if the developers of the Web Component forget to add a CSS4 Variable (or if there are new CSS Stuff because of a new Release) to the Web Component, then the only way to change a Style is with Javascript, WTF?!
ive tried but got an error message âcannot read property âshadowRootâ of nullâ, can you help me with that ? sorry if im asking a dumb question.
Hey,
I found this sweet NPM Package which will help you do just that.
And this will work even when the CSS Variables are not pre-created.
It is super simple to use as well.
1: Install the package.
2: Import it in your TS file
import { injectStyles } from 'shadow-dom-inject-styles';
3: Add this kind of code in your Constructor or anywhere in the TS.
// Menu Styling in Shadow Root
setTimeout(() => {
// Select your Shadow Root
let toolbar = document.querySelector('ion-app ion-menu') as HTMLElement;
console.log(toolbar);
// define style tag text
let styles = `.menu-inner {
background: transparent !important;
}`;
injectStyles(toolbar, '.menu-inner', styles);
}, 200);
What this does is, it adds a style tag inside the selected Shadow root with your CSS String.
I had to put it inside a setTimeout because I was using it in the constructor of my app.component.ts, and by the time the code was executing, the Shadow Roots were not created yet.
But yea, this works !
Thanks @abhayamin. This works somehow, even itâs super hacky and it causes a small UI glitch due to the timeout.
I had to fix a padding on item-item, as it has a fixed padding of 8px to the right wich I couldnât get rid of. And I need a ion-item there as itâs part of a sliding list⌠gna!
I overcame the glitch by keeping the element hidden till I could apply my style inside the Shadow Dom. Havenât found any other way of doing it yet. This has become a regular piece of code for me. No other choice till the Ionic team gives more Variables to support styling Shadow Domâs.
You do have another choice: Upgrade to Ionic 5 and use CSS shadow parts https://ionicframework.com/blog/customize-your-ionic-framework-app-with-css-shadow-parts/
Thatâs the issue with the new Shadow Parts: you can only style elements that are exposed to the outside. In this case, the class with the padding is not exposed and thus we canât style it / remove it.
@abhayamin I change my whole page and all of its elements to âno paddingâ and then added the padding to every element accordingly. Also not perfect, but better than a second ârebuildâ of the page. Has also some quirks, but itâs better than nothing.
This piece of code is for changing the parts that are not exposed by Ionic. Some cases, for a few designs you need that extra control.
Thatâs true if the thing youâre trying to style is not accessible through custom CSS properties or shadow parts, then youâre stuck. However, it seems like most things are accessible through one of these methods.
So neither --inner-padding-end
nor --padding-end
solved your problem? https://ionicframework.com/docs/api/item#css-custom-properties
Not sure what you were referring to when you said âthis piece of codeâ. You seemed to indicate that your only option to style shadow DOM elements was to use that hacky shadow-dom-inject-styles
package. What Iâm saying is that many parts of Ionic components inside the shadow DOM can be accessed either through custom CSS properties or CSS shadow parts. You havenât specified a specific shadow DOM element that you are trying to access though, so itâs unclear whether or not your case requires the hacky solution.
@wesleygoldsborough I am using Ionic 5 and I have a ion-button
and I want to target the span
with the class button-inner
which is within the shadow part native
of the ion-button
. How can I target button-inner
class to style it?
@noopurphalak You canât. But perhaps whatever you are trying to accomplish can be achieved through custom css properties or some other way. Feel free to elaborate on what youâre trying to do.
@wesleygoldsborough Thanks for your reply. In my case, I was able to resolve the issue with targetting the shadow part itself. I wanted to acheive something like this:
As you can see from the above image, the green button has a very minimum margin between the icon and the button itself. What I was actually getting was this:
I was eventually able to fix this by targetting the native
part in the ion-button
and setting padding:0;
and margin:0;
and incresing the size of the icon to that of the button.
Angular directive for cleaner development based on âshadow-dom-inject-stylesâ npm package
import { Directive, ElementRef, Input, OnChanges, SimpleChanges } from '@angular/core';
import { injectStyles } from 'shadow-dom-inject-styles';
@Directive({
selector: '[shadowDomInject]'
})
export class ShadowDomInjectDirective implements OnChanges {
@Input() shadowDomInject: string;
constructor(private el: ElementRef) {
console.log('ShadowDomInjectDirective constructor', el);
}
ngOnChanges(changes: SimpleChanges) {
if (changes.shadowDomInject) {
const value: string = changes.shadowDomInject.currentValue;
const clean = value.replace(new RegExp(`
`, 'ig'), '').replace(new RegExp(' ', 'ig'), '');
const split: string[] = clean.split('{');
injectStyles(this.el.nativeElement, split[0], changes.shadowDomInject.currentValue);
}
}
}