Install Eva Icons individually and keep dynamic colour states - css

I would like to use a handful of Eva Icons in my project because the package is quite large. From my understanding we can't install icons individually.
Instead, I've downloaded the svgs and registered the svg pack in the app.component which works:
export class AppComponent implements OnInit {
constructor(private iconsLibrary: NbIconLibraries) {
this.iconsLibrary.registerSvgPack('eva-icons', {
'arrow-back': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="arrow-back"><rect width="24" height="24" transform="rotate(90 12 12)" opacity="0"/><path d="M19 11H7.14l3.63-4.36a1 1 0 1 0-1.54-1.28l-5 6a1.19 1.19 0 0 0-.09.15c0 .05 0 .08-.07.13A1 1 0 0 0 4 12a1 1 0 0 0 .07.36c0 .05 0 .08.07.13a1.19 1.19 0 0 0 .09.15l5 6A1 1 0 0 0 10 19a1 1 0 0 0 .64-.23 1 1 0 0 0 .13-1.41L7.14 13H19a1 1 0 0 0 0-2z"/></g></g></svg>',
'book-open-outline': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="book-open"><rect width="24" height="24" transform="rotate(180 12 12)" opacity="0"/><path d="M20.62 4.22a1 1 0 0 0-.84-.2L12 5.77 4.22 4A1 1 0 0 0 3 5v12.2a1 1 0 0 0 .78 1l8 1.8h.44l8-1.8a1 1 0 0 0 .78-1V5a1 1 0 0 0-.38-.78zM5 6.25l6 1.35v10.15L5 16.4zM19 16.4l-6 1.35V7.6l6-1.35z"/></g></g></svg>',
'camera': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="camera"><rect width="24" height="24" opacity="0"/><path d="M19 7h-3V5.5A2.5 2.5 0 0 0 13.5 3h-3A2.5 2.5 0 0 0 8 5.5V7H5a3 3 0 0 0-3 3v8a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3v-8a3 3 0 0 0-3-3zm-9-1.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5V7h-4zM20 18a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1v-8a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1z"/><path d="M12 10.5a3.5 3.5 0 1 0 3.5 3.5 3.5 3.5 0 0 0-3.5-3.5zm0 5a1.5 1.5 0 1 1 1.5-1.5 1.5 1.5 0 0 1-1.5 1.5z"/></g></g></svg>',
'menu-outline': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="menu"><rect width="24" height="24" transform="rotate(180 12 12)" opacity="0"/><rect x="3" y="11" width="18" height="2" rx=".95" ry=".95"/><rect x="3" y="16" width="18" height="2" rx=".95" ry=".95"/><rect x="3" y="6" width="18" height="2" rx=".95" ry=".95"/></g></g></svg>',
'edit-outline': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="edit"><rect width="24" height="24" opacity="0"/><path d="M19.4 7.34L16.66 4.6A2 2 0 0 0 14 4.53l-9 9a2 2 0 0 0-.57 1.21L4 18.91a1 1 0 0 0 .29.8A1 1 0 0 0 5 20h.09l4.17-.38a2 2 0 0 0 1.21-.57l9-9a1.92 1.92 0 0 0-.07-2.71zM9.08 17.62l-3 .28.27-3L12 9.32l2.7 2.7zM16 10.68L13.32 8l1.95-2L18 8.73z"/></g></g></svg>',
'teams': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="Layer 2"><g data-name="people"><rect width="24" height="24" opacity="0"/><path d="M9 11a4 4 0 1 0-4-4 4 4 0 0 0 4 4zm0-6a2 2 0 1 1-2 2 2 2 0 0 1 2-2z"/><path d="M17 13a3 3 0 1 0-3-3 3 3 0 0 0 3 3zm0-4a1 1 0 1 1-1 1 1 1 0 0 1 1-1z"/><path d="M17 14a5 5 0 0 0-3.06 1.05A7 7 0 0 0 2 20a1 1 0 0 0 2 0 5 5 0 0 1 10 0 1 1 0 0 0 2 0 6.9 6.9 0 0 0-.86-3.35A3 3 0 0 1 20 19a1 1 0 0 0 2 0 5 5 0 0 0-5-5z"/></g></g></svg>',
});
this.iconsLibrary.setDefaultPack('eva-icons');
}
However the nb status is no longer automatically changing the icon colours like before. Please can you advise on how to do this efficiently?

Alternative is to extract the SVG of only the icons you want (from any icon set);
wrap that in a modern W3C Custom Element/WebComponent that recreates the SVG dynamically,
allowing you to alter presentation any way you want, with attributes, properties or CSS properties.
https://iconmeister.github.io/ now has 5000+ icons you can pick from
You then have No dependencies, No external SVG files
As a test I did all your 6 EVA icons: https://jsfiddle.net/WebComponents/5ct36swL/
(and cleaned up the bloated SVG from EVA icons)
Usage:
<style>
svg-icon {
display: block;
background: grey;
--svg-icon-stroke:darkslategray;
}
</style>
<div id=toolBar class=icons>
<svg-icon is="arrow-back" stroke=green></svg-icon>
<svg-icon is="book-open-outline" fill=red></svg-icon>
<svg-icon is="camera" opacity=.2 stroke=red></svg-icon>
<svg-icon is="menu-outline" fill=gold></svg-icon>
<svg-icon is="edit-outline" rotate=45 fill=blue stroke=white></svg-icon>
<svg-icon is="teams" scale=.5></svg-icon>
</div>
Output:
Should work fine in Angular, Vue or Svelte. For React you have to jump through some hoops...
as React only for 71% supports this modern W3C standard (https://custom-elements-everywhere.com/)
(my) Related StackOverflow answers: Custom Elements and SVG

Related

How to create a transparent mask using shape

Given I have a svg as follows:
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#a)">
<path d="M0 0h20v20H0V0z" fill="#0D4AF9" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M2 14.666a1.334 1.334 0 1 1 2.669.001A1.334 1.334 0 0 1 2 14.666zm4.667.667a.668.668 0 0 1 0-1.334h10.667a.667.667 0 1 1 0 1.334H6.667zM2 9.998a1.333 1.333 0 1 1 2.666 0 1.333 1.333 0 0 1-2.666 0zm4.667.667a.667.667 0 1 1 0-1.333h10.667a.666.666 0 1 1 0 1.333H6.667zM2 5.333a1.333 1.333 0 1 1 2.666.001A1.333 1.333 0 0 1 2 5.332v.001zm4.667.666a.667.667 0 1 1 0-1.333h10.667a.666.666 0 1 1 0 1.333H6.667z"
fill="#fff"/>
</g>
<defs>
<clipPath id="a">
<rect width="20" height="20" rx="2"/>
</clipPath>
</defs>
</svg>
which renders like:
How can one make those white lines and circles transparent? I tried creating masks but a total noob.
You can join the d attributes of the 2 paths and use fill-rule="evenodd" so that the second part of the path became a hole.
body{background:silver}
<svg width="200" height="200" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#a)">
<path d="M0 0h20v20H0V0z
M2 14.666a1.334 1.334 0 1 1 2.669.001A1.334 1.334 0 0 1 2 14.666zm4.667.667a.668.668 0 0 1 0-1.334h10.667a.667.667 0 1 1 0 1.334H6.667zM2 9.998a1.333 1.333 0 1 1 2.666 0 1.333 1.333 0 0 1-2.666 0zm4.667.667a.667.667 0 1 1 0-1.333h10.667a.666.666 0 1 1 0 1.333H6.667zM2 5.333a1.333 1.333 0 1 1 2.666.001A1.333 1.333 0 0 1 2 5.332v.001zm4.667.666a.667.667 0 1 1 0-1.333h10.667a.666.666 0 1 1 0 1.333H6.667z"
fill="#0D4AF9" fill-rule="evenodd"
/>
</g>
<defs>
<clipPath id="a">
<rect width="20" height="20" rx="2"/>
</clipPath>
</defs>
</svg>
Observation: I've changed the size of the svg element. You can change it back to what you need.
Split out the element you want to another path, and then change the fill.

Resize SVG by changes in path

So I have a width and height of container and viewBox, can't change these things
Only thing I can do is send this component a path
For now the SVG is now adjusting in it's container due to the size being too big
Can I change the aspect ratio / size of SVG via the path ?
Sample Code
<svg viewBox="-2 -3 24 24" width="30px" height="30px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: inline-block; vertical-align: middle;"><path fill="#3E3E3E" d="M18.438 19.102a11 11 0 0 1-18.4-7.184c-.042-.504.372-.915.878-.915.507 0 .912.411.963.915a9.16 9.16 0 0 0 5.793 7.623A9.168 9.168 0 0 0 17.749 17.2h-2.663a.917.917 0 1 1 0-1.832h4.269a.917.917 0 0 1 .916.916v4.264a.916.916 0 0 1-1.833 0V19.1v.002ZM4.248 4.807H6.91a.917.917 0 1 1 0 1.832H2.64a.917.917 0 0 1-.917-.916V1.455a.916.916 0 0 1 1.833 0v1.448a11 11 0 0 1 18.407 7.184c.041.505-.373.915-.88.915-.505 0-.911-.411-.962-.915a9.161 9.161 0 0 0-5.794-7.623A9.168 9.168 0 0 0 4.249 4.807h-.002Z"></path></svg>
Again goal to achieve: make SVG to fit this viewBox and width height.
No you can't. You'd have to change the SVG path to fit the box, but you can't "resize" per-se.
I manually resized your path to fit the box.
<path fill="#3E3E3E" d="M1.2 3.3H4a1 1 0 1 1 0 1.8H.6a1 1 0 0 1-.9-.9V0a1 1 0 0 1 1.9 0v1.4A11 11 0 0 1 20 8.6c0 .5-.4.9-1 .9a1 1 0 0 1-.9-1A9.2 9.2 0 0 0 12.3 1a9.2 9.2 0 0 0-10 2.3ZM17.4 16.1A11 11 0 0 1-1 8.9c0-.5.4-.9 1-.9.4 0 .8.4.9 1a9.2 9.2 0 0 0 5.8 7.5 9.2 9.2 0 0 0 10-2.3h-2.6a1 1 0 1 1 0-1.8h4.3a1 1 0 0 1 .9.9v4.2a1 1 0 0 1-1.9 0v-1.4Z"></path>
How I did it:
I used svgomg with precision: 1, to simplify the path to a point where it was small enough for me to actually manually edit.
Then I split it into two separate paths (top and bottom arrows) (using
the Z as the path separator), wrapped them in <g transform="translate(x, y)"></g> until it looked right, copied the
remainder back into svgomg where it is smart enough to convert the
transforms into a single path.
You can set the transform attribute of the <path> (using scale and translate):
document.querySelector('path').setAttribute('transform', 'scale(0.9)')
See the snippet for example:
document.querySelector('path').setAttribute('transform', 'scale(0.9)')
<svg viewBox="-2 -3 24 24" width="30px" height="30px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: inline-block; vertical-align: middle;"><path fill="#3E3E3E" d="M18.438 19.102a11 11 0 0 1-18.4-7.184c-.042-.504.372-.915.878-.915.507 0 .912.411.963.915a9.16 9.16 0 0 0 5.793 7.623A9.168 9.168 0 0 0 17.749 17.2h-2.663a.917.917 0 1 1 0-1.832h4.269a.917.917 0 0 1 .916.916v4.264a.916.916 0 0 1-1.833 0V19.1v.002ZM4.248 4.807H6.91a.917.917 0 1 1 0 1.832H2.64a.917.917 0 0 1-.917-.916V1.455a.916.916 0 0 1 1.833 0v1.448a11 11 0 0 1 18.407 7.184c.041.505-.373.915-.88.915-.505 0-.911-.411-.962-.915a9.161 9.161 0 0 0-5.794-7.623A9.168 9.168 0 0 0 4.249 4.807h-.002Z"></path></svg>

Change color of the heart of Like with css on c# and ASP.Net Core

I have vote(like) on my code on C# (ASP .NET Core)
Now I want , when I click on heart , the heart changes its color.
How do I do just with CSS (Not jQuery) with checking of If Condition
this is my Code on View :
<div>
<form method="post" asp-controller="Article" asp-action="AddArticleVote" asp-route-id="#article.Id">
<button type="submit">
<svg xmlns="http://www.w3.org/2000/svg" width="32.044" height="32" viewBox=" 0 32.044 32">
<path id="prefix__comment-heart" d="M18.016 12.16a4.912 4.912 0 0 0-5.664.848 4.8 4.8 0 0 0 0 6.784L16.88 24.4a1.6 1.6 0 0 0 2.272 0l4.528-4.528a4.8 4.8 0 0 0 0-6.784 4.912 4.912 0 0 0-5.664-.928zm3.392 5.376l-3.392 3.392-3.392-3.392a1.6 1.6 0 1 1 2.256-2.272 1.6 1.6 0 0 0 2.272 0 1.6 1.6 0 1 1 2.256 2.272zM18.016 2a16 16 0 0 0-16 16 15.823 15.823 0 0 0 3.617 10.127l-3.2 3.2A1.56 1.56 0 0 0 3.617 34h14.4a16 16 0 1 0 0-32zm0 28.8H7.473l1.488-1.488a1.6 1.6 0 0 0 0-2.256 12.8 12.8 0 1 1 9.055 3.744z" transform="translate(-1.972 -2)" style="fill: #ccc"></path>
</svg>
</button>
</form>
</div>
You can target the path element and add :active styles:
path#prefix__comment-heart:active {
fill: blue;
}
For this to work remove the style attribute inline fill styles as this takes precedence over the fill styles shown above.
If you want to keep the greyish fill color you have now for when the button is not being clicked you can aditionally target path#prefix__comment-heart without the :active suffix.

How to transform bootstrap icons from outline to fill using CSS

I have been trying to change the bootstrap icon from outline to fill using stroke and fill.
For instance:
<svg width="22" height="22" viewBox="0 0 16 16" class="bi bi-house-door" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M7.646 1.146a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 .146.354v7a.5.5 0 0 1-.5.5H9.5a.5.5 0 0 1-.5-.5v-4H7v4a.5.5 0 0 1-.5.5H2a.5.5 0 0 1-.5-.5v-7a.5.5 0 0 1 .146-.354l6-6zM2.5 7.707V14H6v-4a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5v4h3.5V7.707L8 2.207l-5.5 5.5z"/>
<path fill-rule="evenodd" d="M13 2.5V6l-2-2V2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5z"/>
</svg>
I have an outlined home icon:
How can I transfer it to this:
Dynamically using fill, stroke, and fill-rule. I have already tried changing the stroke and fill rule but I still cannot transform the first object to the second one. Is there any way I can do this?
The answer is no. There is no way to fill the inside of the house using CSS. At least not in a generic sense that would work with any shape *.
The reason is because the outline is the shape. The SVG contains two <path> elements.
the house outline.
the chimney
The house outline path consists of two subpaths. The first It contains two subpaths, one is the very outside border of the house shape and the second is the transparent hole in the middle.
If we split the first path into those two subpaths and colour them differently, you will see what is happening.
svg {
width: 300px;
height: 300px;
}
path:nth-child(1) {
fill: red;
}
path:nth-child(2) {
fill: yellow;
}
path:nth-child(3) {
fill: blue;
}
<svg width="22" height="22" viewBox="0 0 16 16" class="bi bi-house-door" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<!-- path 1 subpath 1 - the outline (red) -->
<path fill-rule="evenodd" d="M7.646 1.146a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 .146.354v7a.5.5 0 0 1-.5.5H9.5a.5.5 0 0 1-.5-.5v-4H7v4a.5.5 0 0 1-.5.5H2a.5.5 0 0 1-.5-.5v-7a.5.5 0 0 1 .146-.354l6-6z"/>
<!-- path 1 subpath 2 - the house inside (yellow) -->
<path fill-rule="evenodd" d="M2.5 7.707V14H6v-4a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5v4h3.5V7.707L8 2.207l-5.5 5.5z"/>
<!-- path 2 - the chimney (blue) -->
<path fill-rule="evenodd" d="M13 2.5V6l-2-2V2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5z"/>
</svg>
If you want a filled version of the house, you would need to modify the SVG itself. Just remove the subpath for the "inside" of the house.
svg {
width: 300px;
height: 300px;
}
<svg width="22" height="22" viewBox="0 0 16 16" class="bi bi-house-door" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M7.646 1.146a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 .146.354v7a.5.5 0 0 1-.5.5H9.5a.5.5 0 0 1-.5-.5v-4H7v4a.5.5 0 0 1-.5.5H2a.5.5 0 0 1-.5-.5v-7a.5.5 0 0 1 .146-.354l6-6z"/>
<path fill-rule="evenodd" d="M13 2.5V6l-2-2V2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5z"/>
</svg>
* Technically, you can achieve this with CSS. But the CSS would be specific to this particular icon, and not be generally applicable to other icons with the same issue.
Also, modifying paths this way is a new feature that is not supported by all browsers yet.
For instance, this example works in Chrome, but not Firefox.
svg {
width: 300px;
height: 300px;
}
path:nth-child(1) {
d: path('M7.646 1.146a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 .146.354v7a.5.5 0 0 1-.5.5H9.5a.5.5 0 0 1-.5-.5v-4H7v4a.5.5 0 0 1-.5.5H2a.5.5 0 0 1-.5-.5v-7a.5.5 0 0 1 .146-.354l6-6z');
}
<svg width="22" height="22" viewBox="0 0 16 16" class="bi bi-house-door" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M7.646 1.146a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 .146.354v7a.5.5 0 0 1-.5.5H9.5a.5.5 0 0 1-.5-.5v-4H7v4a.5.5 0 0 1-.5.5H2a.5.5 0 0 1-.5-.5v-7a.5.5 0 0 1 .146-.354l6-6zM2.5 7.707V14H6v-4a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5v4h3.5V7.707L8 2.207l-5.5 5.5z"/>
<path fill-rule="evenodd" d="M13 2.5V6l-2-2V2.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5z"/>
</svg>

Using icon tag and reusing them via css

Bootstrap 5 (with the alpha release) has introduced their own Icon-Set. For example for edit icon it has svg tag like below:
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-pencil-square" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456l-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/>
<path fill-rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z"/>
</svg>
For the project I am working upon, I need around 8-10 icons and for the same I do not want to include 100s of KBs of CSS Icon library like Fontawesome (which is really awesome) etc.
Question:
Is it possible that I can use a small css and put those 8-10 tags in it? Something like (say myicon.css) this:
myicon.css
<svg foo ></svg>
.....
<svg bar ></svg>
So that I can include that "small" css in my htmls wherever I need.
If yes how? Any relevant info/hint/solution will be greatly appreciated.

Resources