SVG text, tspan font-size and centered - html

I have an issue with font size on SVG as us can see in svg the font-size:16px different from paragraph font-size but the they have the same value 16px. I would like to have font size in svg such on paragraph.
The second issue, it's how to center <tspan text-anchor="middle" class="tc-label-value">85</tspan> when I delete <tspan class="label-text" text-anchor="middle" x="0" y="50" dy="15">Text in SVG</tspan>
I mean the is a case when I have Text in svg and have not
https://codepen.io/palaniichukdmytro/pen/BaaKbze

SVG text, & span font-size and center solution
body {
margin: 0;
}
.wr {
width: 180px;
margin: 0 auto;
}
.label-text {
font-size: 12px;
text-align: center;
}
.tc-label-value {
font-size: 12px;
text-align: center;
}
.par {
font-size: 16px;
text-align: center;
}
<div class='wr'>
<svg viewBox="0 0 100 100" width="100%" height="100%" style="display: block;">
<path d="M 95.5 50 A 45.5 45.5 0 1 1 11.315120324302569 26.047336589080288" stroke-width="9" stroke-dasharray="168.16760675098308" stroke-dashoffset="2.842170943040401e-14" stroke="#a3bfff" stroke-linecap="round" fill="none" style="transition: stroke-dashoffset 500ms ease-out 0s;"></path>
<path d="M 11.315120324302569 26.047336589080288 A 45.5 45.5 0 0 1 95.5 49.999999999999986" stroke-width="9" stroke-dasharray="117.71732472568812" stroke-dashoffset="0" stroke="#66bb6a" stroke-linecap="round" fill="none" style="transition: stroke-dashoffset 500ms ease-out 0s;"></path>
<text transform="translate(50)" x="0" y="50">
<tspan text-anchor="middle" class="tc-label-value">85</tspan>
<tspan class="label-text" text-anchor="middle" x="0" y="50" dy="15">Text in SVG</tspan>
</text>
</svg>
<p class='par'>Text Paragraph</p>
</div>

The font size for the svg element should be 8.88px. Why? Because the svg's width is 100 units or px ( viewBox="0 0 100 100" ) and is scaled up to 180px ( .wr{width: 180px;} ). Since you need the font size inside the svg to look like 16px, the real font size should be 16 * 100 / 180 = 8.88
.wr {
width: 180px;
}
.par{
font-size: 16px;
}
svg{font-size: 8.88px;}
<div class='wr'>
<svg viewBox="0 0 100 100" style="display: block;">
<path d="M 95.5 50 A 45.5 45.5 0 1 1 11.315120324302569 26.047336589080288" stroke-width="9" stroke-dasharray="168.16760675098308" stroke-dashoffset="2.842170943040401e-14" stroke="#a3bfff" stroke-linecap="round" fill="none" style="transition: stroke-dashoffset 500ms ease-out 0s;"></path>
<path d="M 11.315120324302569 26.047336589080288 A 45.5 45.5 0 0 1 95.5 49.999999999999986" stroke-width="9" stroke-dasharray="117.71732472568812" stroke-dashoffset="0" stroke="#66bb6a" stroke-linecap="round" fill="none" style="transition: stroke-dashoffset 500ms ease-out 0s;"></path>
<text transform="translate(50)" x="0" y="50">
<tspan text-anchor="middle" class="tc-label-value">85</tspan>
<tspan class="label-text" text-anchor="middle" x="0" y="50" dy="15">Text in SVG</tspan>
</text>
</svg>
<p class='par'>Text Paragraph</p>
</div>

Related

SVG fill / stroke

Need some help with filling my svg with color on hover.
On the left I have my test svg, on the right - the result I want on hover.
How to fill with color on hover only gray lines and let the space inside be transparent (empty)?
(that's strange that space inside is fillinbg with color, because there is no svg content there)
.container {
width: 50%;
margin: 0 auto;
display: flex;
justify-content: space-between;
background: gray;
padding: 20px;
}
svg:hover {
fill: #40bfff;
stroke:#40bfff;
}
<div class="container">
<div>
<svg width="20" height="20" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7.188 19a.562.562 0 100-1.125.562.562 0 000 1.125zM15.063 19a.562.562 0 100-1.125.562.562 0 000 1.125z" fill="#9098B1" stroke="#9098B1" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M1 1h2.25L5.5 14.5h11.25L19 4.375H4.375" stroke="#9098B1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
<!-- changing stroke and fill to color i need -->
<div>
<svg width="20" height="20" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7.188 19a.562.562 0 100-1.125.562.562 0 000 1.125zM15.063 19a.562.562 0 100-1.125.562.562 0 000 1.125z" fill="#40bfff" stroke="#40bfff" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M1 1h2.25L5.5 14.5h11.25L19 4.375H4.375" stroke="#40bfff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
</div>
All you have to do to change the wheel fill colour is add a second rule targetting the wheels.
Note: The SVG below is exactly the same as your original one. Except that I have reformatted it a little, and added a viewBox so that we can scale it up to see the wheels. I wanted to show that you can style the SVG how you want without having to change the SVG.
svg {
/* just here to make the svg large enough to see the wheel centres */
width: 200px;
height: 200px;
}
svg:hover path {
stroke: #40bfff;
}
/* Target the first path (the wheels) */
svg:hover path:nth-child(1) {
fill: #40bfff;
}
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.188 19a.562.562 0 100-1.125.562.562 0 000 1.125zM15.063 19a.562.562 0 100-1.125.562.562 0 000 1.125z"
fill="#9098B1" stroke="#9098B1"
stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M1 1h2.25L5.5 14.5h11.25L19 4.375H4.375"
stroke="#9098B1"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
try this:
.container {
width: 50%;
margin: 0 auto;
display: flex;
justify-content: space-between;
background: gray;
padding: 20px;
}
svg:hover path {
stroke: #40bfff;
}
<div class="container">
<div>
<svg width="20" height="20" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7.188 19a.562.562 0 100-1.125.562.562 0 000 1.125zM15.063 19a.562.562 0 100-1.125.562.562 0 000 1.125z" fill="#9098B1" stroke="#9098B1" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M1 1h2.25L5.5 14.5h11.25L19 4.375H4.375" stroke="#9098B1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
<!-- changing stroke and fill to color i need -->
<div>
<svg width="20" height="20" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M7.188 19a.562.562 0 100-1.125.562.562 0 000 1.125zM15.063 19a.562.562 0 100-1.125.562.562 0 000 1.125z" fill="#40bfff" stroke="#40bfff" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M1 1h2.25L5.5 14.5h11.25L19 4.375H4.375" stroke="#40bfff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
</div>
Put all your stroke & fill attributes into the svg element since that's where your hover is set.
.container {
width: 50%;
margin: 0 auto;
display: flex;
justify-content: space-between;
background: gray;
padding: 20px;
}
svg:hover {
fill: none;
stroke: #40bfff;
}
<div class="container">
<div>
<svg width="20" height="20" stroke="#9098B1" fill-opacity="0" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round">
<path d="M7.188 19a.562.562 0 100-1.125.562.562 0 000 1.125zM15.063 19a.562.562 0 100-1.125.562.562 0 000 1.125z" />
<path d="M1 1h2.25L5.5 14.5h11.25L19 4.375H4.375"/>
</svg>
</div>

animating an SVG <path> element in a <g> tag

I'm attempting to use :hover in CSS to get a slice of a circle to rotate.
The CSS I'm attempting to use will cause the slice to rotate as I would expect. However, when I add the :hover selector, it doesn't rotate.
My HTML and CSS is below:
transform-origin: 190px 50px;
transform: rotate(360deg);
transition: transform 10s;
}
#box:hover {
fill-opacity: 0%;
stroke: black;
}
#circle:hover {
transform-origin: 10% 10%;
transform: rotate(90deg);
transition: transform 2s;
stroke: black;
}
<div id="divThree">
<svg id="box" version="1.1" width="500" height="300" viewBox="0 0 500 300" xmlns="htp://www.w3.org/2000/svg">
<g class="slice">
<path d="M 50 50 H 190 V 190 C 190 190, 58.99 189.99, 50 50"></path>
</g>
<circle id="circle" cx="190" cy="50" r="140" fill-opacity="0.0" stroke="red "fill="black"/>
</svg>
</div>
My codepen is here.
Your CSS code is fine. You can do #box .slice:hover.
But you should look at your SVG: there is <g class="slice"> before <circle .... So circle overlaps your slice, in this case slice will never be hovered.
Simplest solution will be to just move circle before slice:
<svg id="box" version="1.1" width="500" height="300" viewBox="0 0 500 300" xmlns="htp://www.w3.org/2000/svg">
<circle id="circle" cx="190" cy="50" r="140" fill-opacity="0.0" stroke="red "fill="black"/>
<g class="slice">
<path d="M 50 50 H 190 V 190 C 190 190, 58.99 189.99, 50 50"></path>
</g>
</svg>
or you can disable pointer events for circle:
#box circle {
pointer-events: none;
}
Working solution: https://codepen.io/emtei/pen/PoqObRp?editors=1100

SVG property vector-effect="non-scaling-stroke" still scales stroke

In SVG, I need the PATH stroke width to remain as is while viewBox property is changing. The SVG property vector-effect="non-scaling-stroke" should accomplish that but it is not working as it suppose to.
Can someone explain why in the code below (check the codepen.io) the stroke width still increases as viewbox changes? I would also appreciate a solution that makes strokes width constant regardless of viewbox.
https://codepen.io/anon/pen/eKQrYL
HTML
<div class="Item">
<div class="Item-graphic">
<svg id='scaling-stroke' width="200" height="200" viewBox="0 0 50 50">
<circle cx="25" cy="25" r="20" fill="none" stroke="#fff" stroke-width="2"/>
<path d="M25 15 L 25 35" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round"/>
<path d="M15 25 L 35 25" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round"/>
</svg>
</div>
<span>
50 x 50 view box<br>
200 x 200 dimensions<br>
no vector effect
</span>
</div>
<div class="Item">
<div class="Item-graphic">
<svg id='non-scaling-stroke' width="200" height="200" viewBox="0 0 50 50">
<circle cx="25" cy="25" r="20" fill="none" stroke="#fff" stroke-width="2" vector-effect="non-scaling-stroke"/>
<path d="M25 15 L 25 35" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" vector-effect="non-scaling-stroke"/>
<path d="M15 25 L 35 25" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" vector-effect="non-scaling-stroke"/>
</div>
</svg>
<span>
50 x 50 view box<br>
200 x 200 dimensions<br>
vector effect
</span>
</div>
CSS
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 100vh;
background-color: #2196F3;
font-family: Helvetica, sans-serif;
font-weight: 300;
line-height: 1.5;
}
svg {
display: block;
margin: 0 auto;
}
.Item {
flex: 0 0 200px;
padding: 0 1rem;
color: rgba(#fff, 0.6);
font-size: 11px;
text-align: center;
}
.Item-graphic {
display: flex;
align-items: center;
height: 220px;
}
JS
n=1;inc=1;
cvb = function(){
vb = '' + n
vb += ' ' + n
vb += ' ' + 2*(25-n)
vb += ' ' + 2*(25-n)
$('#non-scaling-stroke').attr('viewBox', vb)
$('#scaling-stroke').attr('viewBox', vb)
n += inc;
if (n<=1 || n>=24) inc *= -1;
setTimeout(cvb, 100);
};
cvb()
It is a bug in Chrome. The bug report is here https://bugs.chromium.org/p/chromium/issues/detail?id=849080. It was fixed in Chrome version 68.0.3440.25.

Flipping textPath direction from anti-clockwise to clockwise?

By default, SVG wraps text around a path in an anti-clockwise manner. The ceiling of the text sticks the path. How to change the direction to clockwise so that the floor of the text sticks to the circumference instead of the ceiling?
.textspace
{
letter-spacing: 5px;
font-family: fantasy;
font-size: 50px;
writing-mode: tb;
}
.curved-text
{
font-family: fantasy;
font-size: 20px;
letter-spacing: 5px;
word-spacing: 10px;
}
<svg height="400" width="400">
<defs>
<path d="M60,60
A50,50
0
1,0
61,60"
stroke="black"
stroke-width="2"
fill="none"
id="tracker-path"/>
</defs>
<text x="50" y="50" class="curved-text">
<textPath xlink:href="#tracker-path">
Tracking succesful.
</textPath>
</text>
</svg>
I managed to solve this. All you need to do is set the value of sweep-flag from 0 to 1. That will flip the direction of path
.textspace
{
letter-spacing: 5px;
font-family: fantasy;
font-size: 50px;
writing-mode: tb;
}
.curved-text
{
font-family: fantasy;
font-size: 20px;
letter-spacing: 5px;
word-spacing: 10px;
}
<svg height="400" width="400">
<defs>
<path d="M80,160
A50,50
0
1,1
81,160"
stroke="black"
stroke-width="2"
fill="none"
id="tracker-path"/>
</defs>
<text x="50" y="50" class="curved-text">
<textPath xlink:href="#tracker-path">
Tracking succesful.
</textPath>
</text>
</svg>

On hover change SVG from colour to gradient with a transition

I have an SVG image which I would like to change from a block colour to a gradient. I have got this working, however I would like to have a transition or animation. Is this possible - if so how would it be achieved?
http://jsfiddle.net/otaxjpa2/
HTML:
<svg width="96px" height="96px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
<defs>
<linearGradient id="gradient" gradientUnits="userSpaceOnUse" fy="90%" >
<stop offset="0" style="stop-color:#1EBEE0"/>
<stop offset="1" style="stop-color:#952491"/>
<animate attributeName="fy"from="0" to="1" dur="5s" repeatCount="indefinite" />
</linearGradient>
</defs>
<path id="time-3-icon" d="M256,50C142.229,50,50,142.229,50,256c0,113.77,92.229,206,206,206c113.77,0,206-92.23,206-206
C462,142.229,369.77,50,256,50z M256,417c-88.977,0-161-72.008-161-161c0-88.979,72.008-161,161-161c88.977,0,161,72.007,161,161
C417,344.977,344.992,417,256,417z M382.816,265.785c1.711,0.297,2.961,1.781,2.961,3.518v0.093c0,1.72-1.223,3.188-2.914,3.505
c-37.093,6.938-124.97,21.35-134.613,21.35c-13.808,0-25-11.192-25-25c0-9.832,14.79-104.675,21.618-143.081
c0.274-1.542,1.615-2.669,3.181-2.669h0.008c1.709,0,3.164,1.243,3.431,2.932l18.933,119.904L382.816,265.785z"/>
</svg>
CSS:
svg {
fill: blue;
transition: all 0.3s ease;
display: inline-block;
-webkit-transition: fill .4s ease;
-moz-transition: fill .4s ease;
-o-transition: fill .4s ease;
transition: fill .4s ease;
}
svg:hover {
fill: url(#gradient);
}
Any pointers would be much appreciated!
You can avoid using two rects by transitioning the stop-colors instead:
svg {
display: inline-block;
}
stop {
transition: .4s ease;
}
/* Use the colors to transition to */
svg:hover stop:first-child {
stop-color: #1EBEE0;
}
svg:hover stop:last-child {
stop-color: #952491;
}
<svg width="96px" height="96px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
<defs>
<linearGradient id="gradient" gradientUnits="userSpaceOnUse" fy="90%">
<stop offset="0" stop-color="blue" /> <!-- Colors to transition from -->
<stop offset="1" stop-color="blue" />
</linearGradient>
<mask id="clock-icon-mask" maskUnits="userSpaceOnUse" x="0" y="0" width="512" height="512">
<path d="M256,50C142.229,50,50,142.229,50,256c0,113.77,92.229,206,206,206c113.77,0,206-92.23,206-206C462,142.229,369.77,50,256,50z M256,417c-88.977,0-161-72.008-161-161c0-88.979,72.008-161,161-161c88.977,0,161,72.007,161,161C417,344.977,344.992,417,256,417z M382.816,265.785c1.711,0.297,2.961,1.781,2.961,3.518v0.093c0,1.72-1.223,3.188-2.914,3.505c-37.093,6.938-124.97,21.35-134.613,21.35c-13.808,0-25-11.192-25-25c0-9.832,14.79-104.675,21.618-143.081c0.274-1.542,1.615-2.669,3.181-2.669h0.008c1.709,0,3.164,1.243,3.431,2.932l18.933,119.904L382.816,265.785z"
fill="white" />
</mask>
</defs>
<g mask="url(#clock-icon-mask)">
<rect x="0" y="0" width="512" height="512" fill="url(#gradient)" />
</g>
</svg>
Here's a demo of the technique using a simplified shape (no mask required).
Put the two fill styles on overlapping <rect> objects, and use the clock icon as a mask object applied to both <rect> objects. You can then animate the apparent fill style by animating the opacity of the uppermost <rect>. Remember to apply a white fill to the mask object (white=opaque, black=transparent).
If the following snippet doesn't work, try this jsfiddle link.
#clock-gradient {
opacity: 0.0;
display: inline-block;
-webkit-transition: opacity .4s ease;
-moz-transition: opacity .4s ease;
-o-transition: opacity .4s ease;
transition: opacity .4s ease;
}
#clock-gradient:hover {
opacity: 1.0;
}
<svg width="96px" height="96px" viewBox="0 0 512 512" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="gradient" gradientUnits="userSpaceOnUse" fy="90%">
<stop offset="0" style="stop-color:#1EBEE0" />
<stop offset="1" style="stop-color:#952491" />
</linearGradient>
<mask id="clock-icon-mask" maskUnits="userSpaceOnUse" x="0" y="0" width="512" height="512">
<path d="M256,50C142.229,50,50,142.229,50,256c0,113.77,92.229,206,206,206c113.77,0,206-92.23,206-206C462,142.229,369.77,50,256,50z M256,417c-88.977,0-161-72.008-161-161c0-88.979,72.008-161,161-161c88.977,0,161,72.007,161,161C417,344.977,344.992,417,256,417z M382.816,265.785c1.711,0.297,2.961,1.781,2.961,3.518v0.093c0,1.72-1.223,3.188-2.914,3.505c-37.093,6.938-124.97,21.35-134.613,21.35c-13.808,0-25-11.192-25-25c0-9.832,14.79-104.675,21.618-143.081c0.274-1.542,1.615-2.669,3.181-2.669h0.008c1.709,0,3.164,1.243,3.431,2.932l18.933,119.904L382.816,265.785z" fill="white" />
</mask>
</defs>
<g mask="url(#clock-icon-mask)">
<rect x="0" y="0" width="512" height="512" fill="blue" />
<rect id="clock-gradient" x="0" y="0" width="512" height="512" fill="url(#gradient)" />
</g>
</svg>