Angular 2 SVG CSS rendering differently inside component - css

Transferring some designs to Angular 2 and am using the following code snippet:
<svg class="header__icon help__icon" viewbox="0 0 32 32">
<use xlink:href="images/icon/info-help_small.svg#help__icon"></use>
</svg>
When I use this code outside of the angular component with the exact same stylesheet applied the SVG element scales properly, but as soon as I add it to the inside of an Angular component, no scaling occurs at all. Is this an Angular issue?
This is an image of outside the Angular component with same styles:
This is an image of the SVG inside Angular component:

This should work,
<svg class="header__icon help__icon" viewbox="0 0 32 32">
<use [attr.xlink:href]="images/icon/info-help_small.svg#help__icon"></use>
</svg>

Related

React heroicons icons are always black

I'm using #heroicons/react: ^1.0.5 and I'm trying to style the icons by applying another color. I'm using tailwindcss to manage my CSS.
When I declare the following component inside a button tag
<PencilIcon className='text-white' />
I get the following result on my browser (Chrome 95)
The exact same code works when I access the app on my phone with Chrome 95 (the pencil icon is white).
This is the generated HTML for the icon:
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true" class="text-white">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"></path>
</svg>
When I open the devtools I can see that the computed color of the svg tag is indeed white but the computed color for the path tag is rgb(17, 24, 39) which is inherited from the following CSS rule I have in my global CSS file.
*
{
font-family: Inter, sans-serif;
#apply text-gray-900;
}
Commenting the #apply directive solves my issue but I'm curious as to why it's behaving in this way. Especially when the Chrome on my phone can handle it okay.

Import an SVG element from another document, without losing the CSS <style> from the original file

I need to create a number of SVG files and would love to keep a set of common symbols in one file and import them into the others.
I managed to do this using a <use> element:
<use href="common.svg#symbol1" />
The problem is that if common.svg has a CSS style that affects an element, the style has no effect in the file where the element is imported.
I uploaded two SVGs on svgur.com to show this:
https://svgur.com/i/bYv.svg
...defines a circle with id ball affected by a style that sets a red border around it.
<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<style>#ball { stroke:#ff0000; stroke-width:10; }</style>
<circle id="ball" cx="50" cy="50" r="45" />
</svg>
https://svgur.com/i/bXA.svg
...uses the circle. The circle is visible but the border is not.
<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<use href="bYv.svg#ball" />
</svg>
Questions:
Is this a bug of the SVG renderer I'm using or is it how it's supposed to behave?
Every renderer I tried (chrome, firefox, inkscape) shows the same result so I suspect this might be the intended behavior.
Is there any way to import an element from an external SVG file and the CSS styles that affect it too, so that it appears exactly like it does in its original document?
Is this a bug of the SVG renderer I'm using or is it how it's supposed to behave?
It is the intended behaviour. CSS rules do not apply across document boundaries. You are importing the SVG into your main document, but your CSS is in another document.
Is there any way to import an element from an external SVG file and the CSS styles that affect it too...
No.
Well I suppose you could technically write some Javascript to load the other file and extract the CSS rules. But I strongly suspect you don't want to do that.
You SVG "sprite document" should not have CSS rules in a <style> tag.
The best approach is to pre-prepare you SVGs to be used as sprites.
What I would do is import your common.svg into a vector editor and convert all your CSS attributes into presentation attributes. For example Illustrator lets you choose the method of styling when you export an SVG.
What you want is for something like this:
<svg>
<style>
.st0 {
fill: red;
}
</style>
<symbol id="whatever">
<path d="..." class="st0"/>
</symbol>
</svg>
to be converted to:
<svg>
<symbol id="whatever">
<path d="..." fill="red"/>
</symbol>
</svg>
According to the Scalable Vector Graphics (SVG) 2
specification (W3C Editor’s Draft, 08 June 2021) it seems that the style of the original document should be applied where an element is imported.
Section 5.5. The ‘use’ element:
The cloned content inherits styles from the ‘use’ element and can be the target of user events. However, these cloned element instances remain linked to the referenced source and reflect DOM mutations in the original. In addition, all style rules that apply in the scope of the referenced element also apply in the scope of the cloned shadow tree.
And 5.5.3. Style Scoping and Inheritance:
The use-element shadow tree, like other shadow trees, exhibits style encapsulation, as defined in the CSS Scoping module [css-scoping-1]. This means that elements in the shadow tree inherit styles from its host ‘use’ element, but that style rules defined in the outer document do not match the elements in the shadow tree. Instead, the shadow tree maintains its own list of stylesheets, whose CSS rules are matched against elements in the shadow tree.
When the referenced element is from an external document, the stylesheet objects generated when processing that document apply to the shadow tree, and are read-only. All URL references in the stylesheet, including fragment-only references, must be made absolute, relative to the URL of the document that contains the referenced element. User agents may re-use the same stylesheet objects for any shadow trees that reference that same external document.
So it's the browsers and SVG renderers I tried that are not conforming to the standard.
I'm still looking for a way to emulate this behavior on existing SVG user agents.
Your styles will be applied, provided your svg asset code is inlined
<svg style="display:none" class="svg-asset" width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<style>
#inline-ball { stroke:#ff0000; stroke-width:10; }
</style>
<circle id="inline-ball" cx="50" cy="50" r="45" />
</svg>
<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<use xlink:href="#inline-ball" />
</svg>
If you prefer not to inline svg code then "fragment identifiers" might be the better embedding approach.
It's basically a sprite concept:
So your image assets(like symbols) need to be positioned with some x or y offset on sprite pane (unlike symbols who could be positioned with overlapping).
You're actually loading a complete svg including embedded css style elements but choose a particular view frame.
See this articel on css.tricks.com
css.tricks.com: How SVG Fragment Identifiers Work
Your svg would be something like this
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 32 96" >
<g id="icon01">
<path d="M20.6,23.3L14,16.7V7.9h4v7.2l5.4,5.4L20.6,23.3z M16-0.1c-8.8,0-16,7.2-16,16s7.2,16,16,16s16-7.2,16-16S24.8-0.1,16-0.1z M16,27.9c-6.6,0-12-5.4-12-12s5.4-12,12-12s12,5.4,12,12S22.6,27.9,16,27.9z"/>
</g>
<g id="icon02">
<path d="M32,43.2c0,2.7-1.2,5.1-3,6.8l0,0l-10,10c-1,1-2,2-3,2s-2-1-3-2l-10-10c-1.9-1.7-3-4.1-3-6.8c0-5.1,4.1-9.2,9.2-9.2c2.7,0,5.1,1.2,6.8,3c1.7-1.9,4.1-3,6.8-3C27.9,33.9,32,38.1,32,43.2z"/>
</g>
<view id="icon-clock-view" viewBox="0 0 32 32" />
<view id="icon-heart-view" viewBox="0 32 32 32" />
</svg>
For using the fragment identifiers we need to add <view> elements with corresponding sprite area coordinates (defined in viewBox attribute).
Unlike symbol definitions we don't nest the actual path data in view elements.
Embedding in html works by adding the target ID to our src url.
<img class="svg-fragment" src="fragment-ready-1.svg#icon-heart-view">
However, inlining svg graphics in your html, still offers the best styling controls.
(e.g styling elements in your websites css file)
Maybe we'll see additional support for styling remotely embedded svg assets in the future ... Until then we still have to cope with some browser quirks.

Using CSS to style SVG element

All,
I'm pretty new to using SVGs, and I'm hoping someone here can explain to me how to target a particular element of my SVG with CSS?
What I'm trying to do is put together a country map where specific areas will appear darker when the user hovers over them. The map was made in layers in Photoshop, then imported in Illustrator and exported as a SVG file. So far, so good. But I'm running into trouble when I try to style their individual parts (which Illustrator put in "g" IDs and tags).
The code looks like this:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 1762 2043" style="enable-background:new 0 0 1762 2043;" xml:space="preserve" xmlns:xml="http://www.w3.org/XML/1998/namespace">
<g id="Area1">
<image style="overflow:visible;" width="378" height="272" id="Area1" xlink:href=".../.../121F7A955DACD041.png" transform="matrix(1 0 0 1 657 912)">
</image>
</g>
Followed by an "Area2", "Area3", etc.
Now I figured if I simply used "Area1:hover" in my stylesheet, it would work -- but it doesn't.
Oddly enough, when I set "display: none" for the same ID in my CSS, it DOES hide the area. So why won't the hover attribute work?
The <g> element defines a group of SVG elements. It doesn't actually take up any space in the rendered SVG image. So there is nothing for you to :hover over in order to activate this rule in your stylesheet.
You can fix this by setting :hover rules for the group's child elements, or by adding a child selector to the CSS rule, like #Area1 > *:hover, for example.
Here's a simple example (JSFiddle link)
CSS:
#a1 > *:hover {
fill:#fc0;
}
SVG:
<svg viewBox="0 0 200 200">
<g id="a1" style="fill:#e82">
<path d="M50,50v100h100v-100z" />
</g>
</svg>
Update: Creating SVG maps with :hover style attributes
If you try to create an SVG map from multiple overlapping <image> elements, you're going to have problems in the overlapping parts because the :hover style is only applied to the topmost element, even if it only contains transparent pixels.
To fix this, you will have to apply an SVG clipping mask to each section of the map. Alternatively, you could create the map entirely from SVG elements. Here's an example of the latter approach.
I think your problem is that your group id (g tag) is the same id of your image element
<image overflow="visible" width="209" id="Area1" height="248" xlink:href="//www.elige-argentina.com/assets/img/mapa-argentina.png" transform="matrix(1 0 0 1 612.6923 23.6923)">
</image>
Working Fiddle: http://jsfiddle.net/b2f2jx0f/3/

SVG element bound using knockout not appearing

This is my first project using knockout and i'm running into a problem trying to databind an svg object. This is being done in a partial view. I have an svg path defined at the top of the section as so:
<svg class="is-hidden">
<defs>
<path id="shape--sort-up" d="M 4 5 L 4 7 L 11 7 L 11 5 L 7.5 1.5 L 4 5 Z" />
</defs>
</svg>
inside a im trying to do a conditional visible bind on the svg as so:
<svg data-bind="visible: status == 'yes'" viewBox="0 0 16 16" class="icon shape--sort-up">
<title>status</title>
<use xlink:href="#shape--sort-up"></use>
</svg>
I have implemented it just using an image instead of a svg and it works fine that way. When I try to do it with an svg, nothing is shown on the page. Visual studio is telling me that it doesnt like the xlink attribute being used like this, but it doesn't if the svg is defined outside of a knockout binding.

How do I change the colour of an SVG image in a CSS content property?

I'd like to use an SVG image as a CSS sprite through a content property, bootstrap-style, like so:
i.rectangle-image {
content: url(rectangle.svg);
}
and here's my SVG:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect x="10" y="10" width="80" height="80"/>
</svg>
and proposed HTML:
<div><i class="rectangle-image"></i> Hello, world!</div>
I'd like to be able to re-colour the SVG in my application, for example to have the icon appear purple in some locations, and white in others. I know I can accomplish this by having three different SVG files (or data URIs) with the fill attribute set differently on the <rect> tag, but I'm wondering if there's a way for me to do this through CSS in my HTML?
I've tried adding a fill attribute to the i.rectangle-image selector, but that doesn't work.
I've looked at this answer and it's not quite what I want. They suggest embedding SVG throughout the page, and I'd prefer to do this via CSS content if possible. Any thoughts? Am I out of luck?
If you use the CSS content facility you're loading the SVG data basically as an image. For privacy reasons you can't affect how the image is displayed using external CSS or javascript.
If you want to change the contents of SVG data you'd either have to load it via an <object> or <iframe> tag or put it inline in the HTML file.
What abouth giving the SVG transparency and fill the background using css background color?
The sugested solution from #MMM looks great:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="13px" height="12.917px" viewBox="0 0 13 12.917" enable-background="new 0 0 13 12.917" xml:space="preserve">
<polygon fill="#000000" points="6.504,0 8.509,4.068 13,4.722 9.755,7.887 10.512,12.357 6.504,10.246 2.484,12.357 3.251,7.887 0,4.722 4.492,4.068 "/>
<script>
document.getElementsByTagName("polygon")[0].setAttribute("fill", location.hash);
</script>
</svg>
http://jsbin.com/usaruz/2/edit
http://codepen.io/Elbone/pen/fHCjs
You can use SVG Image Editor tool to edit the colors in front end and copy the code and use it where you wanna place it, which requires short time of period.. Try it surely it will work out

Resources