Animate parts of SVG with CSS on hover - svg

I have a menu-icon in svg where I want a part of the icon to animate on hover, not the entire icon. How can I target with a keyframe-animation when hovering the icon?
I have another menu-icon where I'm animating the entire icon on hover, but the one I'm askin here only needs one part of it to move...

You can target inner svg elements by giving them id's and then you can select them with css.
i made this short fiddle to show how you can select the right element. i did not include keyframes because im not a animation guru with css.
http://jsfiddle.net/Z6zKd/
<svg width="100px" height="100px">
<rect id="rectangle" width="100px" height="100px" fill="#000"></rect>
<rect x="30px" id="subrectangle" width="50px" height="50px" fill="#DDD"></rect>
</svg>
css:
svg:hover #subrectangle{
transform: rotate(60deg);
transition: all 0.5s;
fill: #FFF;
left: 50px;
}

Related

Specify baseline position in SVG

Is there a possibility, in SVG, to determine a vertical position as being the "baseline" for that SVG graphics?
Context: we include a lot of inline SVG in tasks I prepare for students (see the attached screenshot, in which the circled 2 and 3 are actually SVG data). This text with inline SVG is published as HTML and in LaTeX. I'd like to find a way to include in my SVG files some marker such that later I don't have to manually specify a vertical offset for each graphic files to be perfectly aligned.
In this example, for instance, the bottom of the "2" within the circle should be determined as baseline, such that it can be automatically aligned with the bottom the of other characters that have no descender.
No, there is no such marker. The best you can do for a workaround is probably this: Set the bottom of the viewBox such that it represents the baseline. Then, if you globally set overflow: visible for all of your SVG icons, it doesn't matter if you have grafical content outside the viewBox, especially below the baseline.
p {
font-size: 40px;
}
svg {
width: 1em;
overflow: visible;
}
circle {
fill: none;
stroke: black;
}
text {
font-size: 14px;
}
<p>Example<svg viewBox="0 0 20 15">
<circle r="8.5" cx="10" cy="10" />
<text x="6" y="15">1</text>
</svg>text</p>

CSS transform-origin on <g> element for centered rotation?

I don't quite understand the transform-origin CSS rule.
If you have a plain <svg> with changing sizes (width, height) and some <rect> elements in it, how can you rotate a <g> element in it correctly?
It should be right next to the <rect>, so I am using transform: translate(x,y).
Then I'd like to rotate the group with rotate(45), but it ends up at strange places:
HTML
<div class="box">
<svg class="svg-main" width="600px" height="600px">
<rect x="0" y="50" width="90" height="40" fill="blue" stroke="blue"></rect>
<g transform="translate(100,50),rotate(7)"
transform-origin="center"
class="group">
<path d="M38.15,20.54,28.9,11.29a1.4,1.4,0,0,0-2.4,1v1.89a1.41,1.41,0,0,1-1.4,1.41H3.2A1.4,1.4,0,0,0,1.79,17v9.11a1.41,1.41,0,0,0,1.41,1.4H25.1a1.41,1.41,0,0,1,1.4,1.41v1.89a1.41,1.41,0,0,0,2.4,1l9.25-9.25A1.41,1.41,0,0,0,38.15,20.54Z" stroke="#000" strokeMiterlimit="10" strokeWidth="2"/>
</g>
</svg>
</div>
CSS
div.box {
padding: 30px;
background-color: #dfcfcf;
}
svg.svg-main {
background-color: white;
border: 2px solid #dedada;
}
svg.svg-main g.group path {
fill: rgba(215, 20, 45, 0.5);
}
JSFiddle
https://jsfiddle.net/bair_web/ajLgzoey/
Result for 17deg
Where is the origin?
Question
I would like to rotate the group with its <path> and using center for transform-origin.
MDN
How can I achieve a simple, centered rotation of a group in an SVG, which is also translated? It seems like transform-origin points to the parent element (the SVG)? So do I need to calculate the position of the<g> element relative to the <svg> elment and use it for transform-origin?
Because, when I just omit the origin, the rotated group also moves around and does not keep its center.

Remove space under svg icon - where to add "display: block;" in svg code

I have read a number of posts that answer how to remove the space under a .svg file. I have tried to use the "display: block;" without any luck. I think it is because I am not sure where to place the code to make it work.
A link to my js fiddle is at the following: [where do I put display block in .svg doc][1]
[1]: https://jsfiddle.net/bethabernathy/gsarhk4c/
Any help would be greatly appreciated. Thanks, Beth
Your main problem is that your viewBox is wrong.
If you want the circle to fill the area given to the SVG, then the viewBox has to match the dimensions of the circle. Your circle has a width and height of 75, but your viewBox describes an area 135 wide and high.
To avoid this in the future when using Illustrator, you should either:
Scale your image so that it fills the artboard, or
Uncheck the "Use artboards" option when saving as SVG.
The second problem (that display:block fixes) only becomes apparent when you have fixed the viewBox issue.
Have a look at the following example. There are three versions of the SVG wrapped in a <div>:
Your original SVG. I have simplified the SVG to remove some of the icon unneeded for this demo. I have also removed the SVG boilerplate that is not needed when SVGs are being inlined.
The SVG with fixed viewBox. Note the little gap at the bottom between the SVG and the bottom of the <div>.
Same as #2 but with display: block applied to the SVG. Note the gap at the bottom is now gone.
div {
border: solid 1px grey;
width: 300px;
float: left;
margin-right: 10px;
}
#example3 svg {
display: block;
}
<div id="example1">
<svg viewBox="0 0 135 135">
<style type="text/css">
.st0{fill:#398439;}
</style>
<circle class="st0" cx="37.5" cy="37.5" r="37.5"/>
</svg>
</div>
<div id="example2">
<svg viewBox="0 0 75 75">
<style type="text/css">
.st0{fill:#398439;}
</style>
<circle class="st0" cx="37.5" cy="37.5" r="37.5"/>
</svg>
</div>
<div id="example3">
<svg viewBox="0 0 75 75">
<style type="text/css">
.st0{fill:#398439;}
</style>
<circle class="st0" cx="37.5" cy="37.5" r="37.5"/>
</svg>
</div>

SVG is generating a viewbox even though there isn't one specified

I'm trying to create an SVG play button that is only the size of the button itself, but it seems that there is some kind of viewbox being auto-generated. This phantom viewbox isn't even the same dimensions as the the play button and seems to be a 2:1 ratio.
#play-button {
border: 1px dashed gray;
}
<svg id="play-button">
<style type="text/css">
.st0{fill:none;stroke:#010101;stroke-miterlimit:10;}
.st1{fill:#010101;}
</style>
<circle id="button-border" class="st0" cx="30" cy="29.9" r="29.3"/>
<polygon id="play-triangle" class="st1" points="21.9,15.7 46.6,29.9 21.9,44.1 "/>
</svg>
How can I size the viewbox to the size of the SVG without specifying a viewBox or a height/width?
The outer SVG element is a replaced element. If you don't provide anything to go on for size you'll get the default width which is 300px and the default height which is 50% of the width so if you've not supplied a width value either, that ends up being 150px.
There are a number of ways to indicate the height and width you want. The most obvious would be height and width attributes or CSS properties of the same name but you can also use a viewBox attribute to define a width and height.
#RobertLongson's answer explains why this is happening. Here are some things you can do about it:
Your circle's r="29.3" does in effect "specify a height/width" in the markup. If you can put a value there, I would imagine you actually can the same value in the svg's width or height instead. Here's a different approach you could take with that in mind. It does require a viewbox but one that doesn't change: 0 0 100 100 just lets us use percentage values for the polygon's points. To calculate them, I did yourpointvalue/yourradius (e.g. 21.9/58.6). Using a border on the svg instead of a circle element makes this lighter weight and makes the markup easier to read. I've specified the width in the CSS, but it could also be inline; you could also only specify the height, or have it relative to a parent, etc etc.
(If you check the svg with your browser's inspector, you'll see it's the same width and height as the circle)
#play-button {
fill: #010101;
border: 1px solid #000;
border-radius: 50%;
display: block;
/* specify a width or a height either here or inline */
width: 58.6px;
}
<svg id="play-button" viewbox="0 0 100 100">
<polygon points="37.3,26.8 79.5,50 37.3,73.2" />
</svg>
If you really can't use viewbox, width, or height, and need to keep all that markup, you can achieve this with javascript. This is adapted from a solution by #Almis (but see #PaulLeBeau's take on the issue). The overflow: visible is necessary because the circle's stroke extends a little beyond the bounds of the svg. (Eventually we may be able to specify where a stroke is drawn, but not yet.)
var playButton = document.getElementById('play-button');
var boundingRect = document.getElementById('button-border').getBoundingClientRect();
playButton.style.height = boundingRect.height + 'px';
playButton.style.width = boundingRect.width + 'px';
#play-button {
border: 1px dashed gray;
overflow: visible; /* added */
}
<svg id="play-button">
<style type="text/css">
.st0 {
fill: none;
stroke: #010101;
stroke-miterlimit: 10;
}
.st1 {
fill: #010101;
}
</style>
<circle id="button-border" class="st0" cx="30" cy="29.9" r="29.3" />
<polygon id="play-triangle" class="st1" points="21.9,15.7 46.6,29.9 21.9,44.1 " />
</svg>
It looks like the answer is that the default size of an SVG is 300x150, which seems bizarre to me.
If you don't want that sizing (and you probably shouldn't rely on that default) you have to specify the size as detailed in this CSS Tricks article:
https://css-tricks.com/scale-svg/

Auto height for a foreignObject in SVG

I have, in my SVG, a foreignObject which contains a p element. I want the height of this structure to be adapted to the height of my text.
The p element is already adapted : I've done nothing for that.
But I have troubles for the foreignObject. If I remove the field height, it doesn't work. height:auto doesn't work either.
Since there is no real use of scaling up and down the foreignObject itself, then you can set both foreignObject height and width to 1, and via CSS set foreignObject { overflow: visible; } to make its content visible whatever it is and do whatever you need to do it with it.
You can set height of the foreignObject element in em units, maybe that could help?
Right now the width and height attributes of a foreignObject are required, and must have values > 0, otherwise the element will not be rendered.
Update: An alternative is to just set the dimensions of the foreignObject to 100%, and use the fact that the foreignObject has a transparent background per default. Since other elements in svg are laid out in an absolute manner anyway they don't depend on the foreignObject size.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
p { position: absolute; top: 50%; left: 50%; width: 100px; }
</style>
<circle cx="50%" cy="50%" r="25%" fill="lightblue"/>
<foreignObject width="100%" height="100%">
<p xmlns="http://www.w3.org/1999/xhtml">
some wrapped text...
some wrapped text...
some wrapped text...
some wrapped text...
</p>
</foreignObject>
</svg>

Resources