I'm using Angular 5 and i would fill my white svg image.
I have a svg file like this:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><title>ic_calendar</title><g id="Level_2" data-name="Level 2"><g id="screen"><path d="M18.5,5.11a2.55,2.55,0,0,0-.58-1.68,2.27,2.27,0,0,0-1.7-.71H14.85v-1a.68.68,0,1,0-1.35,0v1H6.39v-1A.67.67,0,0,0,5.72,1,.68.68,0,0,0,5,1.68v1H3.75A2.15,2.15,0,0,0,1.5,5.09V16.4a2.71,2.71,0,0,0,.69,2A2.08,2.08,0,0,0,3.7,19H16.34a2.14,2.14,0,0,0,2.15-2.26C18.51,15.07,18.5,5.57,18.5,5.11Zm-15.65,0h0c0-.71.27-1,.9-1H5v1a.69.69,0,0,0,.68.68.68.68,0,0,0,.67-.68v-1H13.5v1a.68.68,0,1,0,1.35,0v-1H16.2a1,1,0,0,1,.71.26,1.17,1.17,0,0,1,.24.72V6.84H2.85Zm14.3,11.64c0,.78-.52.9-.81.91H3.7a.73.73,0,0,1-.56-.2,1.49,1.49,0,0,1-.29-1V8.2h14.3Z" style="fill:#fff"/><rect width="20" height="20" style="fill:none"/></g></g></svg>
So, i'm importing it through this code:
<svg class="myClass">
<use xlink:href="assetFolder/ic_calendar.svg#Level_2"></use>
</svg>
However, i can't change the svg image style and i can't fill it.
I tried, via sass, to add the following:
svg { fill: blue; }
or
path { fill: blue; }
But nothing...
Can anyone help me?
Thanks
Presentation attributes svg have the highest priority and can not
be changed with thecss. Therefore, they need to be removed if you
want to change the color of the svg objects from the external table
CSS
When using the <use> command, svg objects fall into the shadow DOM
In order to stylize these objects, you must use forced inheritance
path {
fill:inherit;
stroke:inherit;
}
Below is an example where objects are called from the <defs> section with the use command and stylized from the external table css
path {
fill:inherit;
stroke:inherit;
}
#screen {
fill:dodgerblue;
}
rect {fill:#D5D5D5;}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<title>ic_calendar</title>
<defs>
<g id="screen">
<rect id="rect1" width="20" height="20" />
<path d="M18.5,5.11a2.55,2.55,0,0,0-.58-1.68,2.27,2.27,0,0,0-1.7-.71H14.85v-1a.68.68,0,1,0-1.35,0v1H6.39v-1A.67.67,0,0,0,5.72,1,.68.68,0,0,0,5,1.68v1H3.75A2.15,2.15,0,0,0,1.5,5.09V16.4a2.71,2.71,0,0,0,.69,2A2.08,2.08,0,0,0,3.7,19H16.34a2.14,2.14,0,0,0,2.15-2.26C18.51,15.07,18.5,5.57,18.5,5.11Zm-15.65,0h0c0-.71.27-1,.9-1H5v1a.69.69,0,0,0,.68.68.68.68,0,0,0,.67-.68v-1H13.5v1a.68.68,0,1,0,1.35,0v-1H16.2a1,1,0,0,1,.71.26,1.17,1.17,0,0,1,.24.72V6.84H2.85Zm14.3,11.64c0,.78-.52.9-.81.91H3.7a.73.73,0,0,1-.56-.2,1.49,1.49,0,0,1-.29-1V8.2h14.3Z" />
</g>
</defs>
<use xlink:href="#screen" />
</svg>
You have an inline style on your svg path - style="fill:#fff". Inline styles take precedence over styles in a CSS stylesheet. But thats what !important is for!
either update your style to this:
path { fill: blue !important; }
OR simply remove the inline styling.
Related
I have many SVG's on my page, that I imported as (in React):
import { ReactComponent as Logo } from "./../../../images/example.svg";
And them I use them this way:
<div className='someClassName activeClassName?'>
<Logo />
</div>
But all of them are different in their structure.
What do I mean? Some of SVG's are looks like:
<svg>
<path/>
</svg>
some like:
<svg>
<g>
<g>
<path/>
</g>
</g>
</svg>
some looks like:
<svg>
<g>
<circle/>
<triangle/>
</g>
</svg>
And there are millions of types like this.
I have a 'activeClassName' which fill SVG in different color, when it's active, but to make it work with all my SVG's, I have to describe my classname styles kinda like this:
&--active {
svg {
fill: $primaryBlue !important;
path {
fill: $primaryBlue !important;
}
g {
fill: $primaryBlue !important;
g path {
fill: $primaryBlue !important;
}
}
}
}
This looks awful. How can I change, for example, the fill option for all of those SVG's? Please, help me... thanks
As #Robert Longson and #chrwahl pointed out:
removing fill attributes from your svg child elements is recommended.
Not sure, how you could "pre/postprocess" your imported svg component.
In plain js you could easily query your child elements and remove attributes like so:
let svgAsset = document.querySelector(".svgAsset");
// query child elements – maybe includeother svg primitives like circles/rects
let svgChildEls = svgAsset.querySelectorAll("g, path, circle, rect, polygon");
function removeFills(els = svgChildEls) {
els.forEach(function (el, i) {
el.removeAttribute("fill");
});
}
function addElClass(els = svgChildEls) {
els.forEach(function (el, i) {
let nodeName = el.nodeName.toLowerCase();
if(nodeName!='g'){
el.classList.add("svgChild");
}
});
}
function toggleActive(){
svgAsset.classList.toggle('svgActive');
svgAsset.classList.toggle('svgInactive');
}
svg{
display:inline-block;
width:200px;
}
/* inactive */
.svgInactive{
fill: #ccc;
}
.svgActive{
fill: orange;
}
.svgActive
.svgChild{
fill: blue;
}
<p>
<button onclick="toggleActive()">toggle active</button>
<button onclick="removeFills()">Remove fill attributes</button>
<button onclick="addElClass()">Add element Class</button>
</p>
<div class="svgWrp">
<svg class="svgAsset svgInactive" viewBox="0 0 100 100">
<path id="path0" fill="red" d="M0 0 l50 0 l0 50 l-50 0 z" />
<path id="path1" class="hasClass" fill="green" d="M33 33 l50 0 l0 50 l-50 0 z" />
<g fill="purple">
<circle id="" cx="66.666%" cy="33.333%" r="25%" fill="none" stroke="#000" stroke-width="2" />
</g>
</svg>
</div>
In the above example I've also included <g> elements and other shape primitives like polygons:
let svgChildEls = svgAsset.querySelectorAll("g, path, circle, rect, polygon");
You benefit from a lower css specificity – so you don't need nested selectors like
svg g path{ ... }
Manually checking and optimizing your svg source material is always the best approach, since you can't expect graphics from different sources to have a coherent structure.
E.g svgs generated by GUI applications tend to have slightly quirky markup including way to many <g> nesting, unsused or too many transforms (making it hard to get or manipulate x/y offsets) etc.
So I'm trying to make it so that when you hover a list item, it changes the color of the corresponding svg shape. Since these are elements in separate divs is it possible to do this with just css?
Here's a Codepen of what I have so far:
http://codepen.io/rewerbj/pen/LVLRaK
Would I then have to give each svg section a different class name?
I've tried:
.region-list li:hover + .map-shape {
fill: #213A46;
}
That didn't work so I'm not sure if I'm going to have to use jQuery and if so what the most dynamic way to do this would be.
Any suggestions are welcome. Thank you!
You can not do this since the (+) sibling operator only works in adjacent div.
so to achieve this effect either you have to change your HTML in such a way so that shape comes just after the menu or you have to use Jquery
If you want to do this with CSS only you would have to restructure your titles to be adjacent to your SVG map pieces using the + operator (you can read more about that here). Here is an example of your code if you decide to go this route.
HTML
<div class="region-map-wrap">
<div class="region-map">
<div class="title1"><span class="num">1</span><span class="city">one</span></div>
<svg class="item1" 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="97.907px" height="102.533px" viewBox="0 0 97.907 102.533" enable-background="new 0 0 97.907 102.533"
xml:space="preserve">
<g>
<polygon class="map-shape" fill="#009A8B" stroke="#000000" stroke-miterlimit="10" points="4.559,101.959 0.513,25.768 33.772,0.623 97.33,47.07
84.834,90.274 "/>
<circle fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" cx="43.626" cy="55.002" r="24.27"/>
<text transform="matrix(1 0 0 1 35.839 65.252)" fill="#FFFFFF" font-family="'OpenSans'" font-size="28.0337">1</text>
</g>
</svg>
</div>
</div>
CSS
.title1 {
font-size: 18px;
font-family: verdana;
}
.title1:hover + .item1 .map-shape {
fill: #213A46;
}
Also added a JS.Fiddle if you want to play with it. Notice that the title is now just above your SVG item.
EDIT:
Messed around with JQuery using this Fiddle and you can hover SVG elements by setting the Attribute Fill element to a hexadecimal value.
$('.region-list .item').hover(function(){
$(this).addClass('active');
$('.region-map .map-shape').attr("fill", "#ff0000");
}, function(){
$(this).removeClass('active');
$('.region-map .map-shape').attr("fill", "#009A8B");
});
I use Inkscape for creating svg images and want to know how to use not embedded css rules.
For example
draw rectangle
in XML-editor add class attribute as
class="rect1"
to svg:rect object
How to add css like
.rect1 {
fill:#ffef00;
}
Here's an example of an SVG in an HTML page that you can style with CSS:
HTML page
<div id="mySvg">
<svg>
<use xlink:href="images/logo.svg#shape" />
</svg>
</div>
The SVG (located at images/logo.svg)
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<g id="shape">
<rect x="50" y="50" width="50" height="50" />
<circle cx="50" cy="50" r="50" />
</g>
</defs>
</svg>
The CSS
svg {
fill: currentColor;
}
#mySvg {
color: green;
}
See working example: plunker
Notes
If you use Inkscape to create your SVG, you'll probably have to do some hand-editing of the SVG to make it styleable with CSS.
Make sure the SVG code doesn't have any fill attributes in it (fill should be in the CSS). When making an SVG with Inkscape, it often has a fill:none or something. You'll have to manually remove those.
When using Inkscape, save files as "Optimized SVG" as described here.
When one write this SVG code, with embedded CSS:
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 100 100">
<style>
defs rect
{
fill: blue;
}
</style>
<defs>
<rect id="rectangle" x="5" y="10" width="3" height="3"/>
</defs>
<rect x="5" y="5" width="3" height="3"/>
<use xlink:href="#rectangle"/>
</svg>
Then, Chrome does apply the "fill:blue" rule to the second rect through the use tag (so first rect is black, second is blue), whereas firefox does not apply the rule (both rects remain black).
Is that a firebug? Is there something I don't get? Or does the standard say "defs tag should block CSS selectors"?
It's actually a bug from Firefox.
Rules apply to the defs rect elements, but they don't apply when the use tag clones the defs rect.
Replacing the defs with a g tag shows that the defs rect is filled; but the rules are not applied to the "-generated clone".
Correct behavior is Chrome's one, filling the use-generated clone; use-cloned version of the defs rect is wrongly not filled by firefox.
See https://bugzilla.mozilla.org/show_bug.cgi?id=997362#c4 for more explanations.
I am trying to create an SVG document containing groups of multiple elements with a variety of styles. I want to reuse these groups, but change out the color scheme with each use.
It occurs to me that I could give each element in the reusable group a different #class and apply a different style sheet (CSS) to each element. Now I just need to figure out if this is possible with the current specifications.
Here is an SVG that illustrates reuse of an element with styling.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="blocks-stackoverflow.svg">
<style type="text/css">
.one {
fill:#f00;
}
.two {
fill:#44f;
}
</style>
<defs
id="defs4">
<g id="bacon"> <rect
class="one"
id="rect3011"
width="31.428572"
height="51.42857"
x="108.57143"
y="209.50504" />
<rect
class="two"
id="rect3013"
width="80"
height="40"
x="120"
y="249.50504" />
</g>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<use xlink:href="#bacon" x="0" y="0"/>
<use xlink:href="#bacon" x="100" y="200"/>
</g>
</svg>
What the example does NOT accomplish is applying a different style sheet to the second . Is there a way to apply a different style sheet to each of a group? For example, how can I make the second pair of rectangles yellow and green instead of red and blue? Or maybe they're stroked instead of filled.
You can't set styles on elements referenced by a specific <use> element. You can style the original elements, but that affects all references to them.
However, you can change the default styles used when drawing the referenced content by setting styles directly on the <use> element itself. These styles will be inherited by any graphics content that doesn't have other styles set on it directly.
A demo I put together recently showing style possibilities on referenced icons.
To have two shapes within your referenced content have different fill colours that you can specify, you can have one of your rectangles use the default fill colour, and one of your rectangles use the currentColor keyword for fill. Then you need to specify both fill and color styles on each <use> element (or its ancestor), otherwise you'll get the system default fill and color, which are both black.
Example using your code.
<style>
.one {
fill:inherit;
}
.two {
fill:currentColor;
}
</style>
<use xlink:href="#bacon" x="0" y="0"
style="fill:red;color:blue" />
<use xlink:href="#bacon" x="100" y="200"
style="fill:green;color:yellow" />
Based on Apply style sheet to only a specific element trait the style sheet must include some #id syntax like this:
<style type="text/css">
.one {
fill:#f00;
}
.two {
fill:#44f;
}
#pencil .one {
fill:#0f0;
}
#pencil .two {
stroke:#ff0;
}
</style>
referencing the #id of the second
<use xlink:href="#bacon" x="100" y="200" id="pencil"/>
Although the second box will have both the fill from .two and the stroke from #pencil.two , so in my case I'd probably want to use the id qualifier on every clause of the style sheet to avoid them being combined.