Style SVG circle with CSS - css

So I have my SVG-circle.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="168" cy="179" r="59" fill="white" />
</svg>
I want it to be 120% when one hover the circle. I tried both with width, height and stroke. Haven't find any solution to make the circle bigger when hovering. Any suggestions?
circle:hover
{
stroke-width:10px;
}
circle:hover
{
height: 120%;
width: 120%;
}

Want to only use CSS? Use line instead of circle.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<style>
.circle {
stroke-width: 59;
stroke-linecap: round;
}
.circle:hover {
stroke-width: 71;
}
</style>
<line x1="168" y1="179" x2="168" y2="179" stroke="white" class="circle" />
</svg>
http://jsfiddle.net/rLk7rd8b/

As per the SVG 1.1 specification you can't style the r attribute of an SVG circle using CSS https://www.w3.org/TR/SVG/styling.html#SVGStylingProperties. But you can do:
<circle cx="168" cy="179" r="59"
fill="white" stroke="black"
onmouseover="evt.target.setAttribute('r', '72');"
onmouseout="evt.target.setAttribute('r', '59');"/>
In SVG 2, which is partially supported by some modern browsers, you can style the r attribute of circles using CSS. https://www.w3.org/TR/SVG2/styling.html#PresentationAttributes

It can be done in CSS(3), by setting the transform-origin of the circle to its center and then using scale transformation:
circle {
transform-origin: center center;
}
circle:hover {
stroke-width: 10px;
transform:scale(1.2, 1.2);
}

As Phillip suggested in the comment above you can do this with CSS 3 transform.
circle:hover {
-webkit-transform: scale(x, y);
}
("-webkit" prefix is for Chrome only)
See https://developer.mozilla.org/en-US/docs/Web/CSS/transform
Here's a working example with CSS transitions too: http://jsbin.com/sozewiso/2

Click "Run code snippet" to test it out:
.myCircle:hover {
r: 20
}
.myCircle {
transition: ease 1s
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle class="myCircle" cx="10" cy="10" r="5" fill="black" />
</svg>
I stumbled across this page but wanted to add my own answer that I think is easiest. Apparently it doesn't work in Firefox though, which is why someone downvoted.
Step 1: Add a class (e.g. "myCircle") to your circle
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle class="myCircle" cx="168" cy="179" r="59" fill="white" />
</svg>
Step 2: In your CSS file you can use "r" as a CSS property!
.myCircle:hover {
r: 100;
}
Step 3 (optional): Feel free to add a transition to make the radius grow smoothly:
.myCircle {
transition: all 1s;
}

This should work for you.
jsfiddle
You need to manipulate the radius and this can only be done via javascript:
$(function () {
$("svg circle").on("mouseenter", function () {
var oldR = $(this).attr("r");
var newR = (((oldR*2)/100)*120)/2; // 120% width
$(this).attr("r", newR);
});
});

I am not sure, but you can not full custom a svg only with css. However, if you will do it won't be cross browser.
In the past I used svg for creating a complex map and for me the solution was rapheljs.
EDIT:
Using #phonicx calculus for radius i modified the code, having something which is able to customize each circle ( in case if you have more ) :
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle data-precentage='100' cx="168" cy="179" r="59" fill="red" />
<circle data-precentage='120' cx="74" cy="100" r="59" fill="black" />
</svg>

You forgot the stroke color:
circle:hover {
stroke:white;
stroke-width:10px;
}

I was working on something else and came across this question. I'm doing something similar and using greensock. I animated the scale on a couple circles using Greensock, GSAP. I needed to animate tranformOrigin and the scale property:
TweenMax.staggerFrom(".circle",1,{scale:0,transformOrigin:"50% 50%",ease:Bounce.easeOut}, .08);
Example
https://codepen.io/grmdgs/pen/RgjdPv
Greensock
https://greensock.com/

If you want to scale it, try with transform: scale(1,5),
so you don't need to change cx,cy,r attributes.

Using JQUERY:
$(function () {
$('circle').hover(function() {
$(this).attr('r', 100);
}, function() {
$(this).attr('r', 59);
});
});
Demo Here

Related

How to define CSS style for ALL types of SVG'S structure?

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.

OpenLayers Icon className SVG - Change Fill Via CSS?

I'm trying to use CSS classes in openlayers to change an svg fill colour:
eg say in open layers I have
style = new Style({
image: new Icon({
src: styleConfig.image.src,
scale: styleConfig.image.scale,
offset: [styleConfig.offsetX, styleConfig.offsetY],
className: 'icon--blue'
}),
zIndex: styleConfig.zIndex
});
and then I have an SVG like so:
<svg xmlns="http://www.w3.org/2000/svg" width="49" height="44" viewBox="0 0 580 515" class="icon--blue"><circle fill="inherit" cx="475" cy="106.9" r="102.9"/><g class="cat"><circle fill="inherit" cx="475" cy="106.9" r="102.9"/></g></svg>
and some CSS like so:
.icon--blue circle {
fill: #0000ff !important;
}
.icon--blue .cat {
display: none;
}
Try as I might I cannot get the css based fill effect to be applied. I was wondering if this is supported?
Also the hiding of the grouping with the class name of "cat" also doesn't work.
Seeing is OpenLayers is rendering to canvas, debugging this kind of stuff is very difficult.
Start with a Proof of Concept SVG in a JSFiddle or CodePen, to get your SVG and CSS selectors right.
Learn CSS Specificity to understand why the .inner circle below is green and not red;
Most likely no need for fill attribute and hardly ever !important
<style>
svg {
width: 25%;
}
circle {
fill: green;
stroke: red;
}
#outer {
fill: blue;
}
.inner {
fill: red;
}
.hidden {
display: none;
}
</style>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<circle id="outer" cx="10" cy="10" r="8" />
<g class="inner">
<circle cx="10" cy="10" r="4" />
</g>
<circle class="hidden" cx="15" cy="15" r="4" />
</svg>

Can I fix cross-browser CSS issues with <use xlink>-based SVG sprite without resorting to full inline code?

SUMMARY: Some SVG-targeting CSS effects don't work in Chrome & IE (Firefox is fine) on a <use xlink> SVG sprite but the same CSS works absolutely fine when the same SVG code is truly inline.
JSFIDDLE: http://jsfiddle.net/x8vg8k4p/5/
I am currently using <svg><use xlink:href="#symbol-id" /></svg> blocks to call SVG code from an SVG sprite (as an external file) imported via PHP dynamically.
Some CSS effects are applied to the SVG, both as standard and on hover. All these effects work absolutely fine on Firefox, but on both IE and Chrome, they don't:
The fill attribute on the circle does not take effect
The opacity settings on two internal parts of the SVG (the cross by default and the thumb on hover) do not take effect
I believe there is nothing wrong with the CSS as the same code works absolutely fine if the SVG code is inline and not imported via sprite id reference, which the fiddle demonstrates very clearly.
I've struggled for hours, moving bits of code around, adding and removing extra attributes, and not been able to solve this.
What follows are the relevant excerpts of the full code which can be seen on the JSfiddle link - it seems detrimental to readability to include all code here in the question, but I'm happy to edit the question if someone tells me this is bad form.
not working:
<a><svg><use xlink:href="#thumbs-up" /></svg></a>
working:
<a><svg><!-- truly inline SVG code here --></svg></a>
these parts of the CSS are the bits that fail on Chrome and IE:
a svg circle {fill: #4291c2;}
a svg path#cross {opacity: 0;}
a:hover svg circle {fill: #91c142;}
a:hover svg path#cross {opacity: 1;}
a:hover svg g#hand {opacity: 0;}
finally the SVG code itself:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="thumbs-up" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="50"/>
<g id="hand">
<polygon fill="#FFFFFF" points="64.287,37.926 64.287,71.491 80.925,71.491 73.044,37.926 "/>
<path fill="#FFFFFF" d="M54.425,41.857c0-2.634-2.811-4.295-5.025-5.155c-2.728-1.059-4.069-4.203-1.565-8.379
c2.146-3.58-2.084-8.795-6.628-6.058c-5.205,3.134-4.073,11.161-2.468,15.889c0.61,1.798-0.435,1.743-1.756,1.743
c-1.081,0-5.646,0-5.646,0h-8.469c-0.998,0-3.288,6.399-2.289,6.399h10.729c-0.188,0.5-0.406,1.391-0.619,2.544H19.768
c-1.152,0-1.919,7.2-0.714,7.2h10.859c-0.035,0.842-0.049,1.695-0.038,2.544H19.372c-1.195,0-0.277,6.256,0.803,6.256h10.413
c0.245,0.95,0.561,1.813,0.962,2.544H21.331c-1.294,0,1.405,5.811,3.027,5.811h6.978c4.925,0,13.934,0,17.805,0
c3.872,0,5.378-5.477,11.86-5.477V43.891C61.001,43.891,54.425,44.12,54.425,41.857z"/>
</g>
<path id="cross" fill="#FFFFFF" d="M50.042,54.392L39.967,66.389c-0.659,0.854-1.478,1.281-2.454,1.281
c-0.879,0-1.612-0.306-2.198-0.915c-0.586-0.61-0.879-1.355-0.879-2.234c0-0.781,0.195-1.404,0.586-1.867l11.065-13.199
L35.864,37.311c-0.464-0.536-0.696-1.147-0.696-1.831c0-0.806,0.286-1.531,0.859-2.179c0.572-0.646,1.31-0.971,2.211-0.971
c1.023,0,1.852,0.382,2.485,1.145l9.285,11.188l9.547-11.273c0.586-0.706,1.318-1.06,2.198-1.06c0.781,0,1.49,0.275,2.125,0.824
c0.635,0.55,0.953,1.251,0.953,2.105c0,0.83-0.135,1.404-0.403,1.722L54.021,49.495l10.921,13.158
c0.415,0.463,0.623,1.041,0.623,1.729c0,0.937-0.312,1.718-0.935,2.345c-0.622,0.629-1.337,0.942-2.142,0.942
c-0.952,0-1.782-0.427-2.49-1.282L50.042,54.392z"/>
</symbol>
</svg>
I think the best you can do is to use css custom properties:
:root {
--circle-fill: #4291c2;
--hand-fill: #ffffff;
--cross-fill: #ffffff;
--cross-opacity: 0;
--hand-opacity: 1;
}
a {
text-decoration: none;
display: inline-block;
border: none;
cursor: pointer;
position: relative;
width: 25px;
height: 25px;
margin: 0 2px 0 5px;
}
a, a * {
transition: 0.2s all ease-in-out;
}
a svg {
position: absolute;
left:0;
top:0;
width:100%;
height:100%;
}
a:hover {
opacity: 1.0;
transform: rotate(-5deg) scale(1.5);
}
a:hover .thumb {
--circle-fill: #91c142;
--hand-opacity: 0;
--cross-opacity: 1;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="thumbs-up" viewBox="0 0 100 100">
<circle cx="50" cy="49.999" r="50" style="fill: var(--circle-fill)"/>
<g id="hand">
<polygon style="fill: var(--hand-fill); fill-opacity: var(--hand-opacity)" points="64.287,37.926 64.287,71.491 80.925,71.491 73.044,37.926"/>
<path style="fill: var(--hand-fill); fill-opacity: var(--hand-opacity)" d="M54.425,41.857c0-2.634-2.811-4.295-5.025-5.155c-2.728-1.059-4.069-4.203-1.565-8.379
c2.146-3.58-2.084-8.795-6.628-6.058c-5.205,3.134-4.073,11.161-2.468,15.889c0.61,1.798-0.435,1.743-1.756,1.743
c-1.081,0-5.646,0-5.646,0h-8.469c-0.998,0-3.288,6.399-2.289,6.399h10.729c-0.188,0.5-0.406,1.391-0.619,2.544H19.768
c-1.152,0-1.919,7.2-0.714,7.2h10.859c-0.035,0.842-0.049,1.695-0.038,2.544H19.372c-1.195,0-0.277,6.256,0.803,6.256h10.413
c0.245,0.95,0.561,1.813,0.962,2.544H21.331c-1.294,0,1.405,5.811,3.027,5.811h6.978c4.925,0,13.934,0,17.805,0
c3.872,0,5.378-5.477,11.86-5.477V43.891C61.001,43.891,54.425,44.12,54.425,41.857z"/>
</g>
<path id="cross" style="fill: var(--cross-fill); fill-opacity: var(--cross-opacity)" d="M50.042,54.392L39.967,66.389c-0.659,0.854-1.478,1.281-2.454,1.281
c-0.879,0-1.612-0.306-2.198-0.915c-0.586-0.61-0.879-1.355-0.879-2.234c0-0.781,0.195-1.404,0.586-1.867l11.065-13.199
L35.864,37.311c-0.464-0.536-0.696-1.147-0.696-1.831c0-0.806,0.286-1.531,0.859-2.179c0.572-0.646,1.31-0.971,2.211-0.971
c1.023,0,1.852,0.382,2.485,1.145l9.285,11.188l9.547-11.273c0.586-0.706,1.318-1.06,2.198-1.06c0.781,0,1.49,0.275,2.125,0.824
c0.635,0.55,0.953,1.251,0.953,2.105c0,0.83-0.135,1.404-0.403,1.722L54.021,49.495l10.921,13.158
c0.415,0.463,0.623,1.041,0.623,1.729c0,0.937-0.312,1.718-0.935,2.345c-0.622,0.629-1.337,0.942-2.142,0.942
c-0.952,0-1.782-0.427-2.49-1.282L50.042,54.392z"/>
</symbol>
</svg>
<a><svg><use class="thumb" xlink:href="#thumbs-up"/></svg></a>
You can not address an element that is referenced via use. Here is a detailed answer to your question.
Also, refer to this answer, which talks about a possible workaround.
you have to remove "fill" attribute from your svg icons.
Also my advice is using this one https://github.com/Keyamoon/svgxuse for cross-browser solution

Specifying an SVG rectangle's width and height in CSS [duplicate]

Here is a working demo of a rectangle. I'd like to move the height property to css and well, it doesn't work and gives me a blank. It happens in firefox and chrome.
Is there a different name for it? I don't understand why I can't use a css file. The fill color works.
Working example.
css:
rect {
fill:rgb(0, 0, 255);
/*doesnt work height:100;*/
}
html:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect width="100" height="100" style="stroke-width:1;stroke:rgb(0,0,0)"/>
</svg>
In SVG the x, y, width and height of <rect> elements are attributes rather than CSS properties. Only CSS properties can be styled using CSS.
The width of a <rect> element isn't a CSS property in SVG, it's only usable as an attribute. It's for example like the size of a <select> element in HTML. You can only set it as an attribute.
SVG doesn't have a straightforward support for CSS for setting shape dimensions.
However there's a workaround for rects, which can also be used to generate horizontal and vertical lines:
Set width and height to 1, and use CSS transform: scale(width, height)
Don't specify x,y location, and use transform: translate(x, y)
E.g.
.svg {
width: 100px;
height: 30px;
}
.rectangle {
transform: scale(30, 10);
fill: orange;
}
.horiz-line {
transform: translate(15px,5px) scale(50, 1);
fill: red;
}
.vert-line {
transform: translate(10px, 5px) scale(1, 30);
fill: blue;
}
<svg>
<rect class="rectangle" width="1" height="1" />
<rect class="horiz-line" width="1" height="1" />
<rect class="vert-line" width="1" height="1" />
</svg>
workaround for symmetric rectangles:
rect:hover {
stroke-width: 20 !important;
}
<svg width="100" height="100">
<rect
stroke-width="0"
fill="blue" stroke="blue"
x="30" y="30" width="40" height="40"
/>
</svg>
(darkreader will use different colors for stroke and fill)

SVG Rect Ignores Height?

Here is a working demo of a rectangle. I'd like to move the height property to css and well, it doesn't work and gives me a blank. It happens in firefox and chrome.
Is there a different name for it? I don't understand why I can't use a css file. The fill color works.
Working example.
css:
rect {
fill:rgb(0, 0, 255);
/*doesnt work height:100;*/
}
html:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect width="100" height="100" style="stroke-width:1;stroke:rgb(0,0,0)"/>
</svg>
In SVG the x, y, width and height of <rect> elements are attributes rather than CSS properties. Only CSS properties can be styled using CSS.
The width of a <rect> element isn't a CSS property in SVG, it's only usable as an attribute. It's for example like the size of a <select> element in HTML. You can only set it as an attribute.
SVG doesn't have a straightforward support for CSS for setting shape dimensions.
However there's a workaround for rects, which can also be used to generate horizontal and vertical lines:
Set width and height to 1, and use CSS transform: scale(width, height)
Don't specify x,y location, and use transform: translate(x, y)
E.g.
.svg {
width: 100px;
height: 30px;
}
.rectangle {
transform: scale(30, 10);
fill: orange;
}
.horiz-line {
transform: translate(15px,5px) scale(50, 1);
fill: red;
}
.vert-line {
transform: translate(10px, 5px) scale(1, 30);
fill: blue;
}
<svg>
<rect class="rectangle" width="1" height="1" />
<rect class="horiz-line" width="1" height="1" />
<rect class="vert-line" width="1" height="1" />
</svg>
workaround for symmetric rectangles:
rect:hover {
stroke-width: 20 !important;
}
<svg width="100" height="100">
<rect
stroke-width="0"
fill="blue" stroke="blue"
x="30" y="30" width="40" height="40"
/>
</svg>
(darkreader will use different colors for stroke and fill)

Resources