Setting icon className in leaflet when using Svelte doesn't have any effect - css

I'm using leaflet maps in conjunction with Svelte and have the problem that setting the className property of an Icon (L.Icon) that is used for a Marker (L.marker) doesn't have any effect. My code works fine without Svelte, so I assume that the source of the problem is the dynamic generation of a css class. My (abbreviated) code looks like this:
var myIcon = L.icon({
iconUrl: "./svg/My-Icon.svg",
iconSize: [48, 48],
iconAnchor: [24, 32],
className: "svgShadow",
});
...
marker = L.marker(
geoJsonPoint.geometry.coordinates.reverse(),
{
icon: myIcon ,
name: "Here is some text"
}).addTo(map);
<!-- Styles go at the bottom of the file with Svelte -->
<style type="text/css">
.svgShadow {
filter: drop-shadow(5px 5px 5px rgb(0 0 0 / 0.5));
}
</style>
Inspecting the element in the browser even shows that the class name is set for the img element contained in the marker, but it doesn't have any effect. Again, this works without Svelte in a static HTML page. With Svelte I can only find a dynamically generated css class containing the style definition for .svgShadow that isn't applied, but how can I make this work with leaflet and Svelte? Unfortunately I also can't set styles directly with the leaflet icon as only className is exposed.

Styles are scoped by default. If the elements are not created directly as part of the markup, they will not have the necessary classes that are added to the styles.
You can e.g. use :global(.svgShadow) { ... to circumvent this.
(Note that this of course will apply the the styles everywhere, even outside the current component.)

Related

Ionic 6 styling of ion-datetime

I have stumbled upon some difficulties styling ion-datetime component using ionic 6, and none of the posts seem to contain a solution for this. I would like to apply some custom styles to picker items that appear in the shadow-root part.
Applying CSS to classes like .picker-item and .picker-item-active doesn't do anything because they are in the shadow-root. And there don't seem to be any styling properties and variables for ion-picker that I could use.
I am using the standard ion-datetime component like this:
<ion-datetime presentation="time"></ion-datetime>
and in the simulator while inspecting the HTML it appears as:
Styling that I would like to change:
Color and font properties for picker items
Color, background and font properties for active picker item
Since they are all open shadowRoots, you can get in and inject a <style> sheet:
document.querySelector("ion-datetime")
.shadowRoot.querySelector("ion-picker-internal")
.shadowRoot.querySelector("ion-picker-column-internal")
.shadowRoot.prepend( Object.assign( document.createElement("style") , {
innerText : `
.picker-item {
background:hotpink
}
`
}));
After some more playing around, I have been able to find a solution and customize it to my project needs. Thanks to Danny '365CSI' Engelman for inspiration.
The use of ion-datetime and its customization in my project is complex due to using multiple ion-datetime elements appearing and disappearing dynamically. Therefore, applying custom styling of it required some additional logic not posted here. Please reach out if you need some help regarding this.
Here is the base logic that allowed me to apply some styles to ion-datetime:
document.querySelectorAll("ion-datetime").forEach(dt => {
var el = dt.shadowRoot.querySelector("ion-picker-internal");
el.shadowRoot.prepend(Object.assign(document.createElement("style"), {
innerText: `
.picker-highlight {
background: red !important;
}
`
}));
el.querySelectorAll("ion-picker-column-internal").forEach(col => {
col.shadowRoot.prepend(Object.assign(document.createElement("style"), {
innerText: `
.picker-item {
color: green !important;
}
.picker-item-active {
color: blue !important;
}
`
}));
});
});

Applying dynamic styling to injected HTML in Angular 2

For an Angular project I'm working on, I'm injecting HTML into a <div> like so:
<div class="myClass" [innerHTML]="htmlToInsert"></div>
The htmlToInsert contains a variety of things, notably <a> tags. Previously we were styling all these tags like so:
.myClass ::ng-deep a {
color: #f00;
text-decoration: none;
}
And this worked fine. But now I need the color of these links to be dynamically generated during component initialization, based on data coming in from elsewhere. All of the dynamic styling I've seen in Angular requires you to apply things directly to the HTML tag, but we don't have them here to work with.
How can I apply dynamic styling to HTML that is also dynamically generated? Can I directly change the CSS class somehow? Would using a pipe be the correct approach here? Is there another method I don't know about? I could maybe refactor code if there is absolutely no other way of doing this.
So if you can't modify the innerHTML you are passing in, you can achieve this functionality with a custom directive. Essentially you would tag your div that contains your innerHTML with a custom directive. That directive then looks for any anchor tags in it and changes the color based on an input.
// component.html
<div anchorColor [color]="dynamicColor" [innerHTML]="htmlToInsert"></div>
// directive.ts
#Directive({selector: '[anchorColor]'})
export class AnchorColorDirective implements OnAfterViewInit {
#Input() color: string;
constructor(private el: ElementRef){
}
// afterViewInit lifecycle hook runs after DOM is rendered
ngAfterViewInit(){
// get anchor element
let anchorEl = this.el.nativeElement.querySelector('a');
// assign color
if(anchorEl){
anchorEl.style.color = this.color;
}
}
}
Here is a working plunkr https://plnkr.co/edit/QSYWSeJaoUflP94Cy4Hm?p=preview

React Routes - different styling on body css tag

I have two routes on my React app: /a and /b.
For /a, I want the body css tag to have a background-color: red;.
For /b, I want the body css tag to have a background-color: blue;.
Both components a and b live in different .JSX files, and both import their own main.scss file which defines their own respective body background-color.
However, since the entire app is compiled into the body tag, there seems to be a conflict, and only one of the body tags is respected for both routes.
<body>
<script src="bundle.js" type="text/javascript"></script>
</body>
The reason I want it on the body tag and not just a container div is that I want the background-color to be visible when I scroll outside the bounds of the page (the bounce effect on Mac and iOS).
What's the proper way to do this?
That's happening because when you import your styles in your component without CSS Modules, the styles are global so your body style is defined two times (you can see all the styles in the <head> tag).
You can fix that by setting the background color in your component componentDidMount() method.
Example
componentDidMount(){
document.body.style.backgroundColor = "red"// Set the style
document.body.className="body-component-a" // Or set the class
}
or, if youre using functional components you can do the same with useEffect...
useEffect(() => {
document.body.className = 'class-name';
}, []);
I agree with what QoP said but, as an add on to that, you should also make sure to use componentWillUnmount to set it back to whatever it normally is outside that component.
for example:
if normally for the whole application text-align is left but for one component you want it to be center, but after the component it needs to return to being left, you will do the following:
componentDidMount() {
document.body.style.textAlign = "center"
}
componentWillUnmount(){
document.body.style.textAlign = "left"
}
Add this code
componentDidMount(){
document.body.style.backgroundColor = "white"
}
Hope to help.

How to use CSS :hover on a toolbar button in Addon SDK

My addon was originally built in XUL and I am trying to redesign it using the addons SDK, and am having troubles getting icons to change/highlight when I hover the mouse over them.
I know how to apply a css stylesheet to an Addon SDK toolbar and its elements (and how to fetch the right #id to use). This allows me to change the background-color on a button, but I can't seem to make :hover work to change the button image.
It works if I assign a javascript listener for a mouseover event to the button, but if I have lots of buttons or menu items then this is way overkill compared to css.
One problem is that the button image is set on the sdk button element and it is an attribute of the button.
Now, I have tried using a transparent image for the button element's attribute and then using css to supply the image. Using XUL I would apply the image for the button or menu item with list-style-image.
So, my question is: How do I get :hover working in my css for an SDK toolbar button?
Here is the toolbarbutton-icon XUL binding:
<binding id="toolbarbutton-image"
extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton">
<content>
<xul:image class="toolbarbutton-icon" xbl:inherits="src=image"/>
</content>
</binding>
xbl:inherits="src=image" means that the image inherits its src attribute from the image attribute of the <toolbarbutton> thus list-style-image CSS is ignored.
The image property is set when you create the button with SDK APIs. While it is true that you cannot create an SDK button without an image, you can cheat the system either by removing the image attribute afterwards or by using a transparent image and then styling it with background-image just like in the normal web:
const { browserWindows: windows } = require("sdk/windows");
const { viewFor } = require("sdk/view/core");
const { attachTo } = require("sdk/content/mod");
const { Style } = require("sdk/stylesheet/style");
const { ActionButton } = require("sdk/ui/button/action");
var myButton = ActionButton({
id: "my-button",
label: "My Button",
icon: { "24": "./transparent24.png" },
});
let self = require("sdk/self");
let path = self.data.url(); // alternatively use chrome.manifest to register resource or chrome path
let widgetId = "action-button--toolkitrequire-my-button"; // get this from the Browser Toolbox
let css = `
#${widgetId} .toolbarbutton-icon {
background-image: url(${path}/icon24.png);
max-width: 24px;
}
#${widgetId}:hover .toolbarbutton-icon {
background-image: url(${path}/icon24-hover.png);
}`;
let style = Style({ source: css }); // or { uri: `${path}/style.css` }
for (let w of windows)
attachTo(style, viewFor(w));
Keep in mind that other styling may apply to the image so you better use Browser Toolbox to inspect the DOM. I am overriding max-width in this example.

YUI StyleSheet doesn't change content of tag style

I'm trying to use YUI StyleSheet to change some content of the style tag but it doesn't change. Visually, everything works but when I inspect the code in chrome Dev Tools there are no changes. Am I doing something wrong?
My code:
Style
<style id="myStyle">
h1
{
background-color: red;
}
</style>
JavaScript with YUI
YUI().use('node','stylesheet', function (Y)
{
var sheet = Y.StyleSheet(Y.one("#myStyle"));
sheet.set(
"h1",
{
backgroundColor: "#aabbcc",
paddingLeft: "100px",
paddingTop: "100px"
});
});
After YUI does its magic, content of the tag remains the same. I even don't know where all the style goes.
It is ok. YUI StyleSheet works with styleSheets objects but not with the inner text of style DOM element. So visually everything works, but Dev Tools doesn't show the changes. Check the styles of your h1 element - you should see, that your changes is applied.

Resources