The versatile custom Swiss Army Knife card for Home Assistant allows you to create your unique visualization using several graphical tools, styling options and animations.
The UserSvg tool can fetch external images and/or SVG files to be displayed in the SAK card.
The SVG images can have their own styling, which is not always suited to what we want them to be styled. However, you CAN"T style external SVGs, as these are 'protected' according to the SVG specification.
To overcome that problem, an external SVG must be 'injected' into the DOM, after which it CAN be manipulated depending on the SVGs definition.
Yup, CAN!
The SVG must allow external style manipulation for this to work, so there are no local inline styles. CSS classes would be great for styling each individual part of the SVG.
If the SVG uses inline styling, the SVG must be changed in order to allow styling from the UserSVG tool!
Additional background:
Height / Width
External SVGs are treated differently: they are treated as external images, which are automatically scaled to the parent's size, independent of the given height and width. Injected SVG however are not external images: they are local SVGs, and their width and height are respected, meaning they DON't scale to the parent's height and width!
As a result, none of the injected SVGs have the right size! The only possibility is to remove the height and width properties after the injection of the SVG.
Defines/classes
An external SVG might have extra defs for styling. This works per external SVG. However, if these SVGs are injected, each class definition overwrites the previous one!
Below is an example of this using the latest SVG Injector:
The first Tree Pollen Index has a red color. This is right.
The other Trees are NOT red. This is because the Grass and Weed SVGs are injected later, and are gray, and overwrite the previous class definitions
Overwriting class definitions seen from the Edge inspector from top to bottom:
class definition for Weed (gray) overwrites the class definition from Grass
class definition for Grass (gray) overwrites the class definition from Trees
class definition for Trees (red)
Lit has its own way of rendering
None of the SVG injectors can really handle the way Lit wants. The UserSvg tool handles this by doing a few steps behind each other:
specify the SVG to load by the SVG Injector in the first render
get the injected SVG and store it internally
use the cached SVG for consecutive renders
Clipping must be done on another level
The standard clipping/masking does not work anymore, as this refers to the actual external SVG 😄 .
So what you see below for the Trees are two SVGs super imposed on each other: one is injected (gray), and the yellow one is the original external SVG with working clipping and masking...
So, injected SVGs must be rendered differently from external SVGs when a mask is defined in the UserSvg Tool!
What does work?
Well, some style settings simply work for Injected SVGs:
opacity: 0.5 for example (so also fill-opacity!
filters like filter: drop-shadow(2px 4px 6px black); or blur, or any of the filter values.
Below is an example with opacity: 0.5 and the drop-shadow filter:
Related Issues (if any)
Be aware of the fact that:
Safari just won't apply CSS filters!!
You have to replace CSS filters with SVG filters.
And if you do that, Safari won't apply chained filters!!"
You have to combine the filters in a single SVG Filter.
Iterations of SVG IRI elements can be disabled. And that is a good thing, as this doesn't work with this SVG Injector and the SVGs I have tried...
(Automatic) Removal of width and height properties by the UserSvg tool is still needed to scale the SVG to its parent.
Problems with class definitions in the <defs> section is also still there, ie either the SVGs must be changed by the user using unique classes, or the UserSvg must have the ability to disable the SVG Injector. In the latter case, external styling is not possible of course.
added a style section with a CSS Variable using a default color of the original color in the class. So no change has to be done from a user point of view: everything works as before.
The Problem To Be Solved
The UserSvg tool can fetch external images and/or SVG files to be displayed in the SAK card.
The SVG images can have their own styling, which is not always suited to what we want them to be styled. However, you CAN"T style external SVGs, as these are 'protected' according to the SVG specification.
To overcome that problem, an external SVG must be 'injected' into the DOM, after which it CAN be manipulated depending on the SVGs definition.
Yup, CAN!
The SVG must allow external style manipulation for this to work, so there are no local inline styles. CSS classes would be great for styling each individual part of the SVG.
If the SVG uses inline styling, the SVG must be changed in order to allow styling from the UserSVG tool!
Additional background:
Height / Width
External SVGs are treated differently: they are treated as external images, which are automatically scaled to the parent's size, independent of the given height and width. Injected SVG however are not external images: they are local SVGs, and their width and height are respected, meaning they DON't scale to the parent's height and width!
As a result, none of the injected SVGs have the right size! The only possibility is to remove the height and width properties after the injection of the SVG.
Defines/classes
An external SVG might have extra defs for styling. This works per external SVG. However, if these SVGs are injected, each class definition overwrites the previous one!
Below is an example of this using the latest SVG Injector:
Overwriting class definitions seen from the Edge inspector from top to bottom:
Lit
has its own way of renderingNone of the SVG injectors can really handle the way
Lit
wants. The UserSvg tool handles this by doing a few steps behind each other:Clipping must be done on another level
The standard clipping/masking does not work anymore, as this refers to the actual external SVG 😄 . So what you see below for the Trees are two SVGs super imposed on each other: one is injected (gray), and the yellow one is the original external SVG with working clipping and masking...
So, injected SVGs must be rendered differently from external SVGs when a mask is defined in the UserSvg Tool!
What does work?
Well, some style settings simply work for Injected SVGs:
opacity: 0.5
for example (so alsofill-opacity
!filter: drop-shadow(2px 4px 6px black);
or blur, or any of thefilter
values.Below is an example with
opacity: 0.5
and the drop-shadow filter:Related Issues (if any)
Be aware of the fact that:
(Optional): Suggested Solution
After trying several SVG injectors, which all failed somehow, the currently tried SVG Injector seems to have potential.
(Automatic) Removal of width and height properties by the UserSvg tool is still needed to scale the SVG to its parent.
Problems with class definitions in the
<defs>
section is also still there, ie either the SVGs must be changed by the user using unique classes, or the UserSvg must have the ability to disable the SVG Injector. In the latter case, external styling is not possible of course.The class definition in the
<defs>
section can't be overwritten (see: https://stackoverflow.com/questions/5069006/change-attributes-defined-in-defs-on-use-element). In order to be able to overwrite the style, one has to use CSS Variables.Example:
I have changed the SVG
Manual change in the Edge inspector:
(Optional): Alternative Solutions