SVG object change color from external CSS - html

I am playing around with SVGs (trying to replace icon fonts with SVG.) I got it to render the image/svg using object tag. However, I can't get it to change color from CSS. Assuming, I prefer coloring it from CSS, is there a way to do that while I use to embed SVG.
<object class="partnerLogo" type="image/svg+xml" data="assets/logos/sample.svg">
Your browser does not support SVG
</object>
CSS, I tried so far:
.partnerLogo {
width: 100%;
height: 100px;
color: red;
color-fill: red;
}
In sample.svg file, I added, <?xml-stylesheet type="text/css" href="../css/styles.css"?> just before
styles.css is being added to the page.
Thanks!

It isn't possible to directly modify the fill if you're using the SVG using the <object> method. The SVG is included as a document fragment inside the object tag, so your properties aren't passed as you can see in this image.
However, there are two ways you can modify the colors of an external SVG.
1) Use Javascript (recommended)
Using Javascript you can fetch the SVG contents via an XHR, and then inject it as inline SVG. As it's inline SVG technically, you can modify the fill color. There's a library I have written (svg-loader) that make it really easy to do this.
You just need to include the library and use data-src attributes to load SVGs.
Example:
Here, I have included a logo in three different formats, modifying the fill color.
<script type="text/javascript" src="https://unpkg.com/external-svg-loader#latest/svg-loader.min.js" async></script>
<div style="display:flex;">
<div style="background:black;">
<svg data-src="https://s2.svgbox.net/assets/logo-white.svg" fill="yellow"></svg>
</div>
<div style="background:purple;">
<svg data-src="https://s2.svgbox.net/assets/logo-white.svg" fill="white"></svg>
</div>
<div style="background:green;">
<svg data-src="https://s2.svgbox.net/assets/logo-white.svg" fill="red"></svg>
</div>
</div>
2) Use filter CSS property
You can use the filter CSS property to reach any color using bunch of operations (brightness, contrast, hue-rotate..). There an existing stack overflow discussion on this.
Example:
.red {
filter: invert(20%) sepia(97%) saturate(4013%) hue-rotate(353deg) brightness(93%) contrast(127%);
}
<img src="https://s2.svgbox.net/assets/logo-white.svg" class="red" />
The big drawback here is that you'd need to calculate this for every color (using this) and doesn't make it obvious how it works. Also, it won't work well with SVGs having multiple colors.

As far as I know, color in SVG-CSS should be stroke for borders and fill for backgrounds:
.partnerLogo {
width: 100%;
height: 100px;
stroke: red;
fill: red;
}

You can't use external CSS classes to style a SVG called within an < object > element, despite a lot of blog posts in the subject says you can interact with, buit this is misleading for this particular case. You must add the formattings inline, inside the actual SVG.
If you need to access and alter the actual objects and paths of an SVG from your main css file, you must embedd it inline, using the < svg > tag.
Here's a post that covers it all:
https://vecta.io/blog/best-way-to-embed-svg

I know this is an old question now - but this is for any future readers who want to colour their SVGs with pure CSS rather than have to use JS. I find this method quite convenient compared to other methods - and you can even colour your SVGs with a gradient etc.!
I simply make a div which will contain my SVG and give it a class.
HTML:
<div class="colourful-svg"></div>
Then the colour is done using masks and background colour in your CSS.
CSS:
.colourful-svg {
mask-image: url("path/to/your/svg-file.svg");
background: green;
// Make sure you define dimensions for your div otherwise it won't show up
height: 500px;
width: 500px;
mask-size: contain;
mask-position: center;
mask-repeat: no-repeat;
}
This will make your SVG fill the div you had made and therefore be the size you need it to. It then uses a mask to essentially only show your background colour through the SVG you have linked to using the url() function.
Masks now have pretty good support with prefixes (about 94% globally from caniuse.com at the time of writing), so I think this is quite a simple and easy way to implement colour SVGs - I hope someone finds this useful!

Related

Can I optimise repeating SVG elements in an html page?

I'm using inline <svg> for my icons on an html page. I have a component which renders a table, often with hundreds of rows. In this case, every row of the table has the same inlined svg. Usually they are simple icons with just a few paths, but it got me wondering if there is some way to optimise this. In this scenario inlining is important, I don't want to have references to any external files. Is there some way for me to have the inlined svg just once, and refer to that same element somewhere else? Is this something I should even be worried about? Is the overhead of repeating inline svgs minimal?
If you have hundreds of table rows with one SVG, they all are (SVG) DOM elements you have to duplicate/repeat. There is no equivalent to SVGs use in HTML (you could built that yourself with a Custom Element)
If performance really really is an issue you need to test if creating SVGs Server Side (SSR) performs better (in your use case) than creating SVGs Client-Side... but you're probably talking micro-seconds..
The Custom Element IconMeister (one of my pet projects) creates all used SVG icons Client side
(you can cherry pick from 7000+ icons)
Or if all your SVGs are 100% duplicates just a one liner with native JS cloneNode could be enough.
Or create a very simple IconMeister yourself in a W3C Standard Custom Element
for clean semantic HTML:
(100% supported in all modern Browsers, supported by all Frameworks... except React)
<style>
svg-icon svg {
--size: 120px;
width: var(--size);
height: var(--size);
}
[bg=blue] svg{
width:1px;
}
[bg=yellow] svg{
width:5px;
}
</style>
<h3>Who is afraid of Red, Yellow and Blue</h3>
<svg-icon bg="red" ></svg-icon>
<svg-icon bg="yellow" ></svg-icon>
<svg-icon bg="blue" ></svg-icon>
<script>
customElements.define( "svg-icon", class extends HTMLElement {
connectedCallback() {
this.innerHTML =
`<svg xmlns='http://www.w3.org/2000/svg'>` +
`<rect width='100%' height='100%' fill='${this.getAttribute("bg")}'/>` +
`</svg>`;
}});
</script>

Recolor an SVG image via CSS "fill" doesn't work

I'm trying to recolor a simple SVG image with CSS (as I saw here http://codepen.io/chriscoyier/pen/evcBu ):
My HTML:
<img src="http://dl.dropbox.com/u/12091580/rwdicon/icon-menu.svg" class="myMenu" alt="menu">
My CSS:
.myMenu { fill: red; }
It's not working (see http://jsfiddle.net/sexyzane/1hojaccb/ )!
What am I doing wrong?
fill is used for svg element markup, you have an img element with an svg source, as such you cannot use fill to change the image color.
Instead, if you want to colorize the image, you may want to look into applying a CSS filter effect to the img tag, although this may not be able to achieve the exact result you're after.
Demo Fiddle

SVG still receives clicks, even if pointer-events: visible/painted

Basically, I have a couple .svg images put into an <img> tag on my HTML page like that:
<img src="images/corner.svg" alt="menu" class="menu" onClick="Fade();"/>
All of those images are overlapping with each other. They have the same size but different content.
I'm now trying to make only the content of those images clickable.
With pointer-events: visible; or pointer-events: painted; in CSS that seemed to be possible, but i can't get it work like that. The image still receives clicks at every point in it and not only on the content part.
I tried pointer-events: none; on the top image and that disabled clicks on the top image, which sounded like there was no mistake in the HTML or CSS code.
I created those .svg images in Illustrator CC with a transparent background, so normally there can't be content, and I exported it with the following options:
(sorry for this being in german)
I have no idea where the problem could be.
I've had success inlining the SVG, setting the pointer-events to none for the SVG elements, and then setting the pointer-events for the path element within the SVG to fill. Here's a CodePen example.
svg {
cursor: pointer;
pointer-events: none;
}
path {
pointer-events: fill;
}
The problem is that you're using an <img> tag. They work like rasters even when the data is SVG i.e. the individual items don't really exist, it's just a picture which you can either have as entirey clickable or not.
If you want the drawing to be interactive you'll need to use an <object> or <iframe> tag and then you can make the individual shapes clickable or not by using the pointer-events attribute.
You could also include all the svg data inline in the html file but if you did that you'd need to make sure all the id attributes were unique.
This is what worked for me
svg {
pointer-events:none;
}
svg *{
pointer-events:auto;
}
don't hesitate to add !important in case it has conflict with your current style.

Injecting HTML via CSS

I need to basically set the content of something with HTML from CSS. I'm currently doing the following:
.myclass {
content "<img src=\"hello.png\"/>";
}
However, instead of the image, I see the literal text:
<img src="hello.png"/>
How can I inject arbitrary HTML using CSS?
HTML stores the data, and is the Model
CSS stores the styles, and is the View
JS stores the interactions, and is the Controller
If you're trying to add data to the page, it should be done via HTML. If you're simply trying to add an image as a style, use the background-image property. You don't need to inject an <img> element in the page to do that.
Don't ever do this, ever
As far as being able to inject HTML into the page via CSS, it's not directly possible, however it's possible to add JavaScript into the page using CSS, which can then add HTML to the page.
I can't emphasize enough how wrong that approach would be.
Unless there is some strange hack that I am not aware of, this cannot be done with pure CSS.
The content property is only able to insert text; if you try to put in HTML, it will be escaped.
That said, you can do something like this with pure CSS:
This is the CSS that can perform that effect:
.myClass:before {
display: inline-block;
width: 32px;
height: 32px;
content: "";
background-image: url("img.gif");
}
You can see this in action on this jsFiddle page.
In this particular case, you can use a pseudo-class (eg ::before), background-image, display:block and a fixed width and height to show the image.
Also, make sure that the colon : is added between content and its value.
A relatively new concept at the horizon is the element() value for backgrounds. This will display HTML as if it were an image: See also -moz-element.
This can be done. For example with Firefox
css
#hlinks
{
-moz-binding: url(stackexchange.xml#hlinks);
}
stackexchange.xml
<bindings xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml">
<binding id="hlinks">
<content>
<children/>
<html:a href="/privileges">privileges</html:a>
<html:span class="lsep"> | </html:span>
<html:a href="/users/logout">log out</html:a>
</content>
</binding>
</bindings>
ref 1
ref 2
You can't. It's not what it's for. The CSS is for the presentation layer while the HTML is the data layer.
Actually, you can, but just for characters, not HTML. You can use the content property. With some CSS selectors like :before, you can do nice stuff like adding your own character as a bullet for your list. But not much more.

Replace HTML IMG with CSS IMG?

I'm reworking a site but only have permission to change the CSS. Most of the elements I need to change are properly tagged as id's or classes, but a few places have ids or classes listed inside an img tag.
I want to replace that image in the img tag using only css. Is there a way to do this? ie, hide the src img and have only my css referenced image visible?
sorry for such a late post, (almost a year, i know..), but i had the same exact problem Dreamling,
Some of the html used on our site is called up externally, so editing the html was not an option for me either. Here's how i solved the problem... Using only CSS.
Use Firebug if you have it.
Now look for the image you'd like to replace in the HTML. (firebug will show the id's and classes of the elements)
Your HTML should look something like this for it to work. (with an img src element inside a span element)
<span class="Dreamlings_ClassA Dreamlings_ClassB">
<img src="http://www.dreamlingsSite.com/dreamlingspic.png" alt="Dreamling's Pic">
<span>[This is just an extra span!] </span>
</span>
Now for the CSS :)
Call up the first element by class in the css. (use the last class name to be more specific in with editing [if you have multiple span elements with same first class name])
<span class="Dreamlings_ClassB">
should look something like this..
span.Dreamlings_ClassB {
background-image: url('../dreamlingsnewpic.png') !important;
}
and to hide that pesky image in the img src element..
span.Dreamlings_ClassA img {
display: none !important;
}
And thats it! :)
p.s. I was using the !important tags in my css to overwrite other external stylesheets..
but you don't have to use the tags if yours css will work without them. (you just have to be more specific in the css with id's and classes)
Hope this helped!
-tony
If your image tag is inside a container, anything that's a block, then use this:
<style>
#container {
background: url('image.png') no-repeat;
text-indent: -9999;
}
</style>
<div id="container">
<img src="image.png" alt="image to be replaced" />
</div>
As others said, it's really not good practice, but it works. Only tested in Chrome.
I want to replace that image in the img tag using only css.
Not that I know of, no. An image's src attribute can't be altered from CSS.
I also can't think of a workaround to do this, not even a terribly kludgy one. You can of course assign a background-image to the image element, but the actual image will always be in front of it,
You would have to have the original HTML altered in a way so the original button is a <button> element with a background-image property - that you can override using CSS.
Restricting access to the HTML but allowing access to edit CSS is odd practice. Both elements go hand in hand to produce the page.
Anyway, you could try removing or changing the name of "btn_next.png" so that it doesnt display when called from "src" and make the CSS the following:
#btn_next {
background: url('image.png') no-repeat;
display:block;
width:150px; /* for example */
height:30px; /* for example */
}
If that doesnt work, the only other way would be to hide the input button and replace the li row with a background image but then the button will cease to work. Unless you have access to an already included javascript file, then you can look at other solutions.