Use CSS hover with external SVG files? - css

I have an external SVG file with an inline stylesheet like so:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300.00006 244.18703" height="244.19" width="300" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs>
<style type="text/css"><![CDATA[
svg, svg * {
pointer-events: all;
}
svg g {
transition: fill 0.2s;
fill: #303030;
}
svg:hover g {
fill: #6CADDE;
}
]]></style>
</defs>
<g style="" transform="translate(-539.18 -568.86)">
<path d="m633.9 812.04c112.46 0 (...) 27.464"/>
</g>
</svg>
When I open this file by itself in Firefox, it works just as intended. However, if I use an element in an HTML file as <img src="image.svg"> and link it to the SVG, then the hover animation does not trigger. What am I doing wrong?

To get this working you need to insert the SVG in HTML code itself.
Adding an external SVG using src will only allow adding CSS to the overall SVG element and not the interior subtags.
also, can you show some more code? So that it will be better to understand the problem well.
eg:
<!DOCTYPE html>
<html>
<head>
<title>SVG</title>
<style media="screen">
circle:hover{
fill: blue;
}
</style>
</head>
<body>
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
</body>
</html>

Related

Viewbox placement in referencing SVG symbols and CSS dimensions

I edited my initial cry of despair into something more to the technical point, in order to turn it into a Q&A.
I'm using SVG symbols that I reference in the document with use elements. I'm styling these with CSS. I don't want to set both height and width in the CSS, I want to set only one of them with the other one scaling accordingly.
I do set a viewBox attribute on the symbol. But the graphic does not scale correctly.
<!DOCTYPE html>
<html>
<head>
<title>SVG Symbols</title>
<style>
body { margin: 20px; }
.svg-large { width: 500px; fill: yellow;}
</style>
</head>
<body>
<svg style="display:none;">
<symbol id="scary-smiley" viewBox="0 0 20 20">
<circle cx="10" cy="10" r="9.5" stroke-width="1"
stroke="black" />
<circle cx="6" cy="7" r="1.5" fill="black"/>
<circle cx="14" cy="7" r="1.5" fill="black"/>
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Teeth_by_David_Shankbone.jpg/320px-Teeth_by_David_Shankbone.jpg"
width="10" height="5.2" x="5" y="11"/>
</symbol>
</svg>
<svg class="svg-large">
<use xlink:href="#scary-smiley"/>
</svg>
</body>
</html>
The code below has been tested in current Firefox, Chrome and a Webkit-based browser named Midori.
For some reason, defining the viewBox on the symbol element does not have the full desired effect in Firefox and Chrome. It does have some effect, though, as it makes the element scaleable. So, if you want set both width and height in CSS, you can do that.
If the viewBox element is specified only on the symbol and you set only one of width or height, then in Firefox and Chrome the other dimension is set according the default object size in HTML 5 whis is 300x150 px. So, in the example in the question, you get a 500x150 px element and the graphic is scaled to fit that rectangle.
If you want to define only one width or height with the other one scaling accordingly, then defining viewBox on the referencing SVG element works:
<!DOCTYPE html>
<html>
<head>
<title>SVG Symbols</title>
<style>
body { margin: 20px; }
.svg-large { width: 500px; fill: yellow;}
</style>
</head>
<body xmlns:xlink="http://www.w3.org/1999/xlink">
<svg style="display:none;">
<symbol id="scary-smiley">
<circle cx="10" cy="10" r="9.5" stroke-width="1"
stroke="black" />
<circle cx="6" cy="7" r="1.5" fill="black"/>
<circle cx="14" cy="7" r="1.5" fill="black"/>
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Teeth_by_David_Shankbone.jpg/320px-Teeth_by_David_Shankbone.jpg"
width="10" height="5.2" x="5" y="11"/>
</symbol>
</svg>
<svg class="svg-large" viewBox="0 0 20 20">
<use xlink:href="#scary-smiley"/>
</svg>
</body>
</html>
Firefox' and Chrome's behaviour is standard compliant, according to the SVG 2 specification, according to which the <svg><use .../></svg> clause establishes a new SVG viewport.

SVG with multiple path tags ends up ignoring fill color in IE when base64 encoded

I have an svg which is base64 encoded and used as a background image. This is the code for the SVG:
body {
background: rebeccapurple;
}
<svg id="Something" data-name="Something" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<defs>
<style type="text/css">
path {
fill: #FFF !important;
}
</style>
</defs>
<title>Example</title>
<path class="cls-1" d="M16.79,17.28c-.08-1.78-.27-3.55-.33-5.32-.09-2.52,0-5-.3-7.52-.06-.54-.1-1.08-.12-1.62s.05-.72-.44-.81a21.21,21.21,0,0,0-2.15,0C12,1.94,10.48,2,9,2c-.35,0-.73-.14-.94.24A3.28,3.28,0,0,0,8,3.47,37.06,37.06,0,0,0,8,7.86,4.07,4.07,0,0,0,6.78,8,9.14,9.14,0,0,1,5.26,8,10.49,10.49,0,0,0,3.59,8c-.49.05-.39.34-.37.78,0,.62.13,1.21.2,1.83a23.4,23.4,0,0,1,0,4c0,.74,0,1.48-.07,2.22,0,.45-.06.84.45.92a6.36,6.36,0,0,0,1.41-.13,15.25,15.25,0,0,1,2.1-.11,4.07,4.07,0,0,1,.61,0c.11.08,0,.23.11.32.26.23.88,0,1.18,0,.67,0,1.32,0,2,0,1.23-.12,2.48.14,3.72,0C15.34,17.9,17,18.1,16.79,17.28Zm-3.24-2.7h0Zm.31-.06,0,.3M8.33,16.88A8.87,8.87,0,0,0,8.56,15c.05-.47,0-.94,0-1.41,0-1.07.07-2.13.1-3.2,0-1.39,0-2.78.07-4.17,0-.71.06-1.42.05-2.13a4.69,4.69,0,0,1,0-1.26c0-.08.75,0,.83,0a21,21,0,0,0,2.25-.1c.94,0,1.88,0,2.82-.11.11,0,.61-.16.71-.07s.09,1.16.12,1.39a25.86,25.86,0,0,1,.28,3.86c0,1.2-.11,2.39-.12,3.59s0,2.63.08,3.95a7,7,0,0,1,.11,1.43c0,.22,0,.1-.13.2a3.62,3.62,0,0,1-1.4,0,9.35,9.35,0,0,1,0-1.36,3.22,3.22,0,0,0-.17-1.42c-.22-.31-.59-.18-.9-.13a9.39,9.39,0,0,1-1.55.11c-.7,0-.77.36-.77,1s0,1-.05,1.45A1.13,1.13,0,0,1,11,17c-.17.27-.87.15-1.23.17S8.12,17.56,8.33,16.88ZM7.14,15a4.09,4.09,0,0,1,0,1.65c-.12.39.17.14-.25.31s-.29.12-.44-.14a3.33,3.33,0,0,1-.06-1.5c0-.35.08-.73.56-.51C7.19,14.88,7,14.7,7.14,15Zm.52,2.18c0-.7,0-1.41,0-2.11s-.26-.82-.86-.79-.88.1-1,.8a6.25,6.25,0,0,0,0,1.06,4.44,4.44,0,0,1,.1.95c-.33,0-1.66,0-1.79-.22s0-.54,0-.71,0-.62,0-.93c0-.51-.06-1-.08-1.53-.06-1.07.05-2.09.08-3.16,0-.45-.09-.92-.07-1.37,0-.07,0-.24,0-.29a4.3,4.3,0,0,1,1.29-.2,8.79,8.79,0,0,0,2.75-.38,21.64,21.64,0,0,1,0,2.72C8.07,12,8,13.13,8,14.21c0,.63-.1,1.24-.1,1.86,0,.18.07.4.06.57s-.12.35-.13.54Zm5.2.12c-.34.08-1.29.25-1.43-.08a5.2,5.2,0,0,1,.12-1.6c0-.25,0-.58.17-.69s.64.08.81.08a6.72,6.72,0,0,0,1-.1,10.65,10.65,0,0,1,0,1.78C13.55,17.19,13.39,17.14,12.87,17.27Z" />
<path class="cls-1" d="M10.29,5.76c.85,0,.63-.84.58-1.45-.07-.89-.93-.25-1-.4-.15-.32-.35,0-.4.15A5,5,0,0,0,9.39,5C9.3,5.72,9.61,5.75,10.29,5.76ZM9.93,4.33a3.5,3.5,0,0,1,.51-.13,3.23,3.23,0,0,1,0,.8c-.09.3.07.18-.22.26-.58.16-.46-.54-.56-.94Z" />
</svg>
In chrome/firefox the background render with white color but in IE the "path" is always black. If I remove the second "path" tag the image renders with correct colors. Is there any way to solve this?

Can't control SVG icon fill color with CSS styles

I have read all post in here about styling my svg fill color with CSS but without luck.
What I want is to able to make an icon with a link. My external svg file is grey, but I would like to make it red with css and change color to yellow when hovering.
I think I am targeting the SVG wrong. Please help. My test is here:
testpage
<%#LANGUAGE="VBSCRIPT" CODEPAGE="1252"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Test</title>
</head>
<style type="text/css">
<!--
.svgicon {
fill: red;
}
.svgicon:hover {
fill: yellow;
}
-->
</style>
<body>
<table width="100%" border="0" class="tabelform">
<tr>
<td width="100%"><object type="image/svg+xml" data="S/Images/new.svg" height="18" width="18"></object>test icon</td>
</tr>
</table>
</body>
</html>
Answer a little overdue, but worth having for reference for others.
Basically, the only type of SVG usage which can be used in conjunction with CSS is the inline usage.
This means you would literally put your SVG markup directly into the HTML source as follows:
<div class="my-svg">
<svg xmlns="http://www.w3.org/2000/svg" id="SVG-dropdown-icon" viewBox="0 0 15 11">
<title>
Expand
</title>
<path d="M1.758 1L7.5 6.582 13.242 1 15 2.709 7.5 10 0 2.709z"/>
</svg>
</div>
NOTE: This SVG has been optimised using SVGO and then manually edited to include and ID
You can now control the SVG using CSS like so:
.my-svg {
fill: pink;
}
.my-svg:hover {
fill: red;
}
currentColor
You can also use the currentColor keyword in the SVG to apply a colour to certain elements of it, for example:
<div class="my-svg">
<svg id="SVG-active-icon" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg">
<title>
Current Event
</title>
<g fill="none" fill-rule="evenodd">
<circle class="activeEventPulse" stroke="currentColor" fill="#EBEBED" cx="12.5" cy="12.5" r="11.5"/>
<ellipse fill="currentColor" cx="12.5" cy="12.5" rx="4.5" ry="4.5"/>
</g>
</svg>
</div>
.my-svg {
color: red;
}
JS Fiddle
This can be handy if you need to use the same SVG across different websites / themes, such as dark and light, for easily switching SVG colours with CSS.
Caching / performance consideration: SVG cloning
You should also keep in mind, it's not a good idea to use inline SVG for repetitive images, such as icons, because they can not be cached (the SVG code will be repeated throughout your HTML, increasing the ultimate file size).
Instead, one approach I like to use is to create an SVG index at the top of my page, which contains all the SVGs I want to use on the page, for example:
<svg xmlns="http://www.w3.org/2000/svg" class="svg-index">
<svg xmlns="http://www.w3.org/2000/svg" id="SVG-dropdown-icon" viewBox="0 0 15 11">
<title>
Expand
</title>
<path d="M1.758 1L7.5 6.582 13.242 1 15 2.709 7.5 10 0 2.709z"/>
</svg>
<svg id="SVG-active-icon" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg">
<title>
Current Event
</title>
<g fill="none" fill-rule="evenodd">
<circle class="activeEventPulse" stroke="currentColor" fill="#EBEBED" cx="12.5" cy="12.5" r="11.5"/>
<ellipse fill="currentColor" cx="12.5" cy="12.5" rx="4.5" ry="4.5"/>
</g>
</svg>
</svg>
Make sure you set the SVG index to display: none so it doesn't show up on the page.
You can now reuse these SVGs repetitively throughout the page using the xlink:href attribute as follows:
<svg class="dropDown">
<use xlink:href="#SVG-dropdown-icon" />
</svg>
<svg class="active">
<use xlink:href="#SVG-active-icon" />
</svg>
<svg class="active">
<use xlink:href="#SVG-active-icon" />
</svg>
<svg class="dropDown">
<use xlink:href="#SVG-dropdown-icon" />
</svg>
JS Fiddle
This is called cloning, and allows you to take advantage of cacheable SVGs which can be controlled with CSS!
Hope this helps!
try to use inline svg instead of external svg source then you can control

Apply a responsive SVG image mask to a HTML5 video

I have already did a one-day search before posting but with no luck
My problem:
I have a HTML5 video in a wrapper with a solid colour (e.g. blue) background (fig.1).
I want to apply a 2-colour .png 1440x900 image mask (fig. 2) over the video so to obtain, as a final result, a video with some transparent parts, corresponding to the black squares of the image mask (and the mask should scale proportionally with video, so as to be somehow responsive)
What actually happens
With the attempted solution (see below) I can see nothing (latest Chrome and Firefox): the page is completely blue coloured and the video starts
What I tried
I tried some demos found here and here but in both the examples the mask applied is not made with an image. Here's the basic code I'm trying.
<!DOCTYPE html>
<head>
<!--[if IE]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<style>
body {
background: #5a91b4;
}
div {
width: 1440px;
}
video {
width: 100%;
mask:url('#imask');
-webkit-mask:url('mask.svg');
}
</style>
</head>
<body>
<div>
<video autoplay controls>
<source src="http://www.html5multimedia.com/code/media/parrots-small.mp4" type="video/mp4">
<source src="http://www.html5multimedia.com/code/media/parrots-small.webm" type="video/webm">
</video>
</div>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1440 900">
<defs>
<mask id="imask" >
<image width="1440" height="900" xlink:href="http://copy.com/TCImDzmSoq8CrU8W/mask.png"></image>
</mask>
</defs>
</svg>
</body>
</html>
The mask.svg file:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="vmask" preserveAspectRatio="xMinYMin"
viewBox="0 0 1440 900"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<mask>
<image width="1440" height="900" xlink:href="http://copy.com/TCImDzmSoq8CrU8W/mask.png"></image>
</mask>
</defs>
</svg>
I'm also open to evaluate a different approach to obtain the same effect.
Thank you in advance guys
If you convert your mask in pure SVG, it will work line in this demo http://jsbin.com/xejiko/1/edit
The svg is at http://jsbin.com/laday/1/edit
This is the mask.svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg viewBox="0 0 1440 899" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group" transform="translate(720.000000, 449.000000) scale(1, -1) translate(-720.000000, -449.000000) " fill="#000000">
<path d="M0,830.648889 L0,-0.00222222222 L1440,-0.00222222222 L1440,830.65 L1440,853.1 L1440,898 L810,898 L180,898 L90,897.997778 L45,898 L0,898 L0,830.648889 L0,830.648889 Z M0,830.648889 L0,897.997778 L90,897.997778 L90,853.1 L90,808.2 L135,808.2 L180,808.2 L180,853.1 L180,897.997778 L1440,897.997778 L1440,830.65 L1440,808.2 L810,808.2 L180,808.2 L180,763.3 L180,718.4 L135,718.4 L90,718.4 L90,673.5 L90,628.6 L45,628.6 L0,628.6 L0,763.3 L0,830.648889 L0,830.648889 Z M1080,224.5 L1080,179.6 L1125,179.6 L1170,179.6 L1170,224.5 L1170,269.4 L1125,269.4 L1080,269.4 L1080,224.5 Z M1350,224.5 L1350,179.6 L1305,179.6 L1260,179.6 L1260,134.7 L1260,89.8 L900,89.8 L540,89.8 L540,44.9 L540,0 L990,0 L1440,0 L1440,134.7 L1440,269.4 L1395,269.4 L1350,269.4 L1350,224.5 Z M0,44.9 L0,0 L135,0 L270,0 L270,44.9 L270,89.8 L135,89.8 L0,89.8 L0,44.9 Z" id="Rectangle-1"></path>
</g>
</g>
</svg>
And in the css you call it
-webkit-mask-box-image: url(urlto/mask.svg)
Not sure about SVG but in CANVAS this would be easy. All you need to do is do is copy the video to the canvas and do the source-atop http://codepo8.github.io/canvas-masking/
Of course you'll run into the issue that you can not access the video that is not on the same domain :/

CSS attribute namespace selector in SVG

I'm trying to use the following CSS to automatically set the style for <g> Elements.
<style type="text/css">
g[inkscape|label="Site"] {
fill: blue;
stroke: red;
stroke-width: 3
}
g[inkscape|label="Building"] {
fill: black;
stroke: red;
stroke-width: 3
}
</style>
However the elements remain without fill or stroke settings set.
Selecting another attribute without a namespace works fine.
Thank you.
This depends what the context of the question is. Is the SVG a stand-alone file, embedded in an xhtml file (i.e. served as application/xhtml+xml) or embedded in an html file (i.e. served as text/html)
If it's standalone SVG, you can do
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<style>
#namespace inkscape "http://www.inkscape.org/namespaces";
g[inkscape|label="Site"] { fill: green; }
</style>
<g inkscape:label="Site" xmlns:inkscape="http://www.inkscape.org/namespaces">
<rect width="150" height="150" stroke-width="1" stroke="rgb(0, 0, 0)" />
</g>
</svg>
See http://alohci.net/static/svg_ns.svg
If it's in an XHTML file, you can do
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
#namespace inkscape "http://www.inkscape.org/namespaces";
g[inkscape|label="Site"] { fill: blue; }
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g inkscape:label="Site" xmlns:inkscape="http://www.inkscape.org/namespaces">
<rect width="150" height="150" stroke-width="1" stroke="rgb(0, 0, 0)" />
</g>
</svg>
</body>
</html>
See http://alohci.net/static/svg_ns.xhtml
If it's in an html file, it's a little different because the html parser doesn't support custom namespaces. Instead you have to treat the attribute's name as if it was just a normal name with a colon in it. So you'd do
<!DOCTYPE html>
<html>
<head>
<style>
g[inkscape\:label="Site"] { fill: yellow; }
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<g inkscape:label="Site" xmlns:inkscape="http://www.inkscape.org/namespaces">
<rect width="150" height="150" stroke-width="1" stroke="rgb(0, 0, 0)" />
</g>
</svg>
</body>
</html>
See http://alohci.net/static/svg_ns.html
Small addition to #alohci’s answer: The attribute names used in CSS must be all lowercase in some browsers. See the following example where the line is orange but not 10 px wide in Firefox 33 and IE 11. Google Chrome 39 does paint it 10 px wide.
<!DOCTYPE html>
<html>
<head>
<style>
/** Works **/
path[cwl\:feedtype="hello"] {
stroke: #fa0;
}
/** Does not work always; attribute name must be lowercase */
/** (names are case insensitive) */
path[cwl\:feedType="hello"] {
stroke-width: 10;
}
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:cwl="http://www.example.com/2014/cwl">
<path d="M0 0 L100 100" cwl:feedType="hello"/>
</svg>
</body>
</html>
Small update to #Alhoci's answer (2019). The relevant namespace for Inkscape SVG as XHTHML has changed from
#namespace inkscape "http://www.inkscape.org/namespaces";
to
#namespace inkscape "http://www.inkscape.org/namespaces/inkscape";
(p.s. For other people using SVGInject or other ways of dynamically loading SVGs, use #Alhoci's second answer for XHTML with the updated namespace!)

Resources