I'm trying to reproduce this piece of code (animated button using SVG and CSS):
https://codepen.io/jscottsmith/pen/azRObp/
To keep the code clean, I wanted to use xlink with that. My current code looks as follows:
#import "compass/css3";
body {background:violet}
#keyframes spin {
to { transform: rotate(360deg); }
}
.stroke-dotted {
opacity: 0;
stroke-dasharray: 4,5;
stroke-width: 1px;
transform-origin: 50% 50%;
animation: spin 4s infinite linear;
transition: opacity 1s ease,
stroke-width 1s ease;
}
.stroke-solid {
stroke-dashoffset: 0;
stroke-dashArray: 300;
stroke-width: 4px;
transition: stroke-dashoffset 1s ease,
opacity 1s ease;
}
.icon {
transform-origin: 50% 50%;
transition: transform 200ms ease-out;
}
#play:hover .stroke-dotted {
stroke-width: 4px;
opacity: 1;
}
#play:hover .stroke-solid {
opacity: 0;
stroke-dashoffset: 300;
}
#play:hover .icon {
transform: scale(1.05);
}
#PlayNow {
cursor: pointer;
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
width:10em;
height:auto;
display:block;
}
<a href="#">
<svg xmlns="http://www.w3.org/2000/svg" id="PlayNow" viewBox="0 0 100 100" x="0px" y="0px" ><use xlink:href="#play" id="playTrailerButton" /></svg>
</a>
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="play" viewBox="0 0 100 100">
<path class="stroke-solid" fill="none" stroke="white" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
C97.3,23.7,75.7,2.3,49.9,2.5"/>
<path class="stroke-dotted" fill="none" stroke="white" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
C97.3,23.7,75.7,2.3,49.9,2.5"/>
<path class="icon" fill="white" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z"/>
</symbol>
</svg>
But the animation doesn't work.. Any ideas or hints - why? jsfiddle is here:
https://jsfiddle.net/4ztwr3c9/6
You have this:
#PlayNow {
cursor: pointer;
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
width:10em;
height:auto;
display:block;
}
There is no element with the id #PlayNow. The example below has #PlayNow selector replaced by the original #play and your changes have been added, and I removed the Compass as well which I guess you can add it back, just be mindful of each change and retest so it's easier to debug and backtrack.
#keyframes spin {
to {
transform: rotate(360deg);
}
}
.stroke-dotted {
opacity: 0;
stroke-dasharray: 4, 5;
stroke-width: 1px;
transform-origin: 50% 50%;
animation: spin 4s infinite linear;
transition: opacity 1s ease, stroke-width 1s ease;
}
.stroke-solid {
stroke-dashoffset: 0;
stroke-dashArray: 300;
stroke-width: 4px;
transition: stroke-dashoffset 1s ease, opacity 1s ease;
}
.icon {
transform-origin: 50% 50%;
transition: transform 200ms ease-out;
}
#play:hover .stroke-dotted {
stroke-width: 4px;
opacity: 1;
}
#play:hover .stroke-solid {
opacity: 0;
stroke-dashoffset: 300;
}
#play:hover .icon {
transform: scale(1.05);
}
html {
height: 100%;
}
body {
height: 100%;
/*background-color: #30FF98;
background: radial-gradient(#71edb5, #30ff98);*/
}
#play {
cursor: pointer;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* Your Changes */
width:10em;
height:auto;
display:block;
}
body {background:violet}
<svg version="1.1" id="play" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" height="100px" width="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
<path class="stroke-solid" fill="none" stroke="white" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
C97.3,23.7,75.7,2.3,49.9,2.5"/>
<path class="stroke-dotted" fill="none" stroke="white" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7
C97.3,23.7,75.7,2.3,49.9,2.5"/>
<path class="icon" fill="white" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z"/>
</svg>
You can change/override some properties of a <use> element - provided these are not already set in your <symbol> element (see first example).
Since you need to change the dash-array values for different elements you can use css variables, that could be changed on hover.
body {
background: violet;
}
#keyframes spin {
to {
transform: rotate(360deg);
}
}
:root {
--fill: #fff;
--strokeWidth: 4px;
--scale: 1;
--strokeDashOffset: 10;
--strokeDashArray: 4 5;
--opacity: 0;
--strokeDashArraySolid: 300;
--strokeDashOffsetSolid: 0;
--opacitySolid: 1;
}
.PlayNow {
display: inline-block;
height: 10em;
}
.PlayNow2 {
--fill: #ccc;
--strokeWidth: 6px;
--scale: 1.5;
}
.PlayNow:hover {
--scale: 1.05;
--strokeDashOffset: 10;
--strokeDashArray: 4 5;
--strokeDashArraySolid: 300;
--strokeDashOffsetSolid: 300;
--opacity: 1;
--opacitySolid: 0;
}
#playTrailerButtonSimple:hover {
fill: green!important;
stroke: green!important;
stroke-dasharray: 10 5;
}
<a href="#">
<svg class="PlayNow PlayNowSimple" xmlns="http://www.w3.org/2000/svg" id="PlayNowSimple" viewBox="0 0 100 100">
<use href="#playSimple" id="playTrailerButtonSimple" stroke-width="4" fill="red" stroke="red"/>
</svg> Simple icon
</a>
<a href="#">
<svg class="PlayNow" xmlns="http://www.w3.org/2000/svg" id="PlayNow" viewBox="0 0 100 100">
<use href="#play" id="playTrailerButton" />
</svg>
</a>
<a href="#">
<svg class="PlayNow PlayNow2" xmlns="http://www.w3.org/2000/svg" id="PlayNow2" viewBox="0 0 100 100">
<use href="#play" id="playTrailerButton" />
</svg>
</a>
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="circle">
<path fill="none" style="stroke:var(--fill)" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7 C97.3,23.7,75.7,2.3,49.9,2.5" />
</symbol>
<symbol id="play" viewBox="0 0 100 100">
<use href="#circle" transform-origin="center" class="stroke-solid" style="stroke-width: var(--strokeWidth); stroke-dasharray: var(--strokeDashArraySolid); stroke-dashoffset: var(--strokeDashOffsetSolid); opacity:var(--opacitySolid); transition: stroke-dashoffset 1s ease, opacity 1s ease;" />
<use href="#circle" transform-origin="center" class="stroke-dotted" style="stroke-width: var(--strokeWidth); stroke-dasharray: var(--strokeDashArray); stroke-dashoffset: var(--strokeDashOffset); opacity:var(--opacity); animation: spin 4s infinite linear; transition: opacity 1s ease, stroke-width 1s ease;" />
<path class="icon" transform-origin="center" style="fill:var(--fill);transform:scale(var(--scale));transition:0.3s" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z" />
</symbol>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="circle2">
<path fill="none" d="M49.9,2.5C23.6,2.8,2.1,24.4,2.5,50.4C2.9,76.5,24.7,98,50.3,97.5c26.4-0.6,47.4-21.8,47.2-47.7 C97.3,23.7,75.7,2.3,49.9,2.5" />
</symbol>
<symbol id="playSimple" viewBox="0 0 100 100">
<use href="#circle2" transform-origin="center" class="stroke-solid" />
<path stroke-width="0" class="icon" transform-origin="center" d="M38,69c-1,0.5-1.8,0-1.8-1.1V32.1c0-1.1,0.8-1.6,1.8-1.1l34,18c1,0.5,1,1.4,0,1.9L38,69z" />
</symbol>
</svg>
External <use> reference
To some extent, you could also use external svg files like so:
<a href="#">
<svg class="svgBtn" xmlns="http://www.w3.org/2000/svg" id="PlayNow" viewBox="0 0 100 100" x="0px" y="0px">
<use href="button.svg#play" id="playTrailerButton" style="transition:0.3s"/>
</svg>
</a>
** Drawback:** Your animations/transitions won#t work in most browsers (Firefox can render them)
I have an SVG compass with an arrow in it. I want to be able to add a class to the arrow and have it rotate a certain degree then stay there and wiggle.
I have the rotation and wiggle working just not together. Not sure how to combine the two so they work together. Here is my code:
div {
max-width: 40%;
}
.st0 {
fill: none;
stroke: #505050;
stroke-width: 4.11;
stroke-linecap: round;
stroke-miterlimit: 10;
}
.st1 {
fill: none;
stroke: #808080;
stroke-width: 2.57;
stroke-linecap: round;
stroke-miterlimit: 10;
}
.st2 {
fill: #505050;
}
.st3 {
opacity: 0.5;
}
.st4 {
fill: none;
}
/* Fill Colors */
.green {
fill: rgba(21, 255, 0, 0.5);
}
.dgreen {
fill: rgba(12, 140, 0, 0.5);
}
.red {
fill: rgba(255, 42, 0, 0.5);
}
.dred {
fill: rgba(140, 23, 0, 0.5);
}
/* Arrow */
#arrow {
transform-origin: 50% 59.7%;
animation-name: wiggle;
animation-duration: 1s;
animation-fill-mode: forward;
-webkit-animation-fill-mode: forward;
-webkit-animation-iteration-count: infinite;
/* Safari 4.0 - 8.0 */
animation-iteration-count: infinite;
}
/* Rotations */
.north#arrow {
-webkit-transform: rotate(45deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.northEast#arrow {
-webkit-transform: rotate(90deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.west#arrow {
-webkit-transform: rotate(135deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.southWest#arrow {
-webkit-transform: rotate(180deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.south#arrow {
-webkit-transform: rotate(225deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.southWest#arrow {
-webkit-transform: rotate(270deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.west#arrow {
-webkit-transform: rotate(315deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.northWest#arrow {
-webkit-transform: rotate(0deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
/* Wiggle Animation */
/* safari and chrome */
#-webkit-keyframes wiggle {
0% {
-webkit-transform: rotate(4deg);
}
50% {
-webkit-transform: rotate(-4deg);
}
100% {
-webkit-transform: rotate(4deg);
}
}
/* firefox */
#-moz-keyframes wiggle {
0% {
-moz-transform: rotate(4deg);
}
50% {
-moz-transform: rotate(-4deg);
}
100% {
-moz-transform: rotate(4deg);
}
}
#keyframes wiggle {
0% {
transform: rotate(4deg);
}
50% {
transform: rotate(-4deg);
}
100% {
transform: rotate(4deg);
}
}
<div>
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 116.3 144" style="enable-background:new 0 0 116.3 144;" xml:space="preserve">
<title>compass</title>
<line id="N" class="st0" x1="58.2" y1="31.3" x2="58.2" y2="49.6"/>
<line id="NW" class="st1" x1="18.5" y1="46.1" x2="31.4" y2="59"/>
<line id="W" class="st0" x1="3.6" y1="85.7" x2="21.9" y2="85.7"/>
<line id="SW" class="st1" x1="18.3" y1="125.5" x2="31.3" y2="112.5"/>
<line id="S" class="st0" x1="58" y1="140.3" x2="58" y2="122"/>
<line id="SE" class="st1" x1="97.7" y1="125.6" x2="84.8" y2="112.6"/>
<line id="E" class="st0" x1="113.4" y1="85.9" x2="95.1" y2="85.9"/>
<line id="NE" class="st1" x1="97.8" y1="46.2" x2="84.9" y2="59.1"/>
<path id="compass" class="st2" d="M69.6,28.8c6.7-6.3,7-16.9,0.7-23.6s-16.9-7-23.6-0.7s-7,16.9-0.7,23.6c0.2,0.2,0.4,0.5,0.7,0.7
c-31.5,6.3-51.9,37-45.6,68.5s37,51.9,68.5,45.6c31.5-6.3,51.9-37,45.6-68.5C110.6,51.4,92.6,33.4,69.6,28.8z M58.2,6.5
c5.6,0,10.2,4.6,10.2,10.2H48C48,11.1,52.6,6.5,58.2,6.5z M58.2,138.3c-29,0-52.5-23.5-52.5-52.5s23.5-52.5,52.5-52.5
c29,0,52.5,23.5,52.5,52.5c0,0,0,0,0,0C110.6,114.8,87.1,138.3,58.2,138.3z"/>
<path id="inner_compass" class="st2" d="M58.2,130.8c-24.9,0-45.2-20.2-45.2-45.2s20.2-45.2,45.2-45.2c24.9,0,45.2,20.2,45.2,45.1
c0,0,0,0,0,0C103.3,110.6,83.1,130.8,58.2,130.8z M58.2,43.8c-23.1,0-41.9,18.8-41.9,41.9s18.8,41.9,41.9,41.9s41.9-18.8,41.9-41.9
C100.1,62.6,81.3,43.8,58.2,43.8L58.2,43.8z"/>
<g id="NNW" class="st3">
<path id="nnwPie" class="st4 green" d="M57.9,27.7v58.2l-41-41C27.8,33.9,42.5,27.7,57.9,27.7z"/>
</g>
<g id="WNW" class="st3">
<path id="wnwPie" class="st4 dgreen" d="M57.9,85.8H0.2v-0.2c0-15.3,6-30,16.8-40.8L57.9,85.8z"/>
</g>
<g id="WSW">
<path id="wswPie" class="st4" d="M57.9,85.8l-40.8,40.8c-10.8-10.8-16.9-25.5-17-40.8H57.9z"/>
</g>
<g id="SSW">
<path id="sswPie" class="st4" d="M57.9,85.8v57.8c-15.3,0-30-6.2-40.8-17L57.9,85.8z"/>
</g>
<g id="SSE">
<path id="ssePie" class="st4 red" d="M99,126.9c-10.8,10.8-25.5,16.8-40.8,16.8H58V85.8L99,126.9z"/>
</g>
<g id="ESE">
<path id="esePie" class="st4 dred" d="M116.2,85.8c0,15.4-6.2,30.2-17.2,41l-41-41H116.2z"/>
</g>
<g id="ENE">
<path id="enePie" class="st4" d="M116.2,85.7v0.2H57.9l41.2-41.2C110.1,55.5,116.2,70.3,116.2,85.7z"/>
</g>
<g id="NNE">
<path id="nnePie" class="st4" d="M99.1,44.6L57.9,85.8V27.7h0.2C73.5,27.6,88.3,33.7,99.1,44.6z"/>
</g>
<polygon id="arrow" class="st2 west" points="78.4,105.3 80.2,107.1 79.1,108.3 77.2,106.4 75.5,109.7 74.1,108.6 75.9,105.1 75.1,104.3
73.3,107.7 71.9,106.6 73.8,103 72.9,102.1 71.2,105.6 69.8,104.5 71.7,100.9 63.5,92.7 63.5,92.7 41.5,70.7 41.4,70.8 39,74.3
34.5,62.5 46.3,67.1 42.5,69.5 64.6,91.6 65.2,92.1 72.9,99.8 76.5,98 77.6,99.5 74.1,101.1 74.9,101.9 78.6,100 79.7,101.4
76.2,103.1 75.9,102.9 77.1,104 80.8,102.3 81.9,103.8 "/>
</svg>
</div>
You need to chain animations together and use a delay between them so one plays after the other has finished.
You were previously using a transition and then an animation which are two separate things. Also browser prefixes are now pretty redundant for animations, I personally would use the non-prefixed syntax.
Here is one example where the arrow moves to the south and then wiggles, you will need to add in the others:
Example CSS
.wrap:hover #arrow {
transform-origin: 50% 59.7%;
animation-name: spinSouth, wiggleSouth;
animation-delay: 0s, 1s;
animation-duration: 1s, 1s;
animation-iteration-count: 1, infinite;
}
/* Spin south Animation */
#keyframes spinSouth {
0% {
transform: rotate(4deg);
}
100% {
transform: rotate(225deg);
}
}
/* Wiggle Animation */
#keyframes wiggleSouth {
0% {
transform: rotate(225deg);
}
50% {
transform: rotate(220deg);
}
100% {
transform: rotate(225deg);
}
}
Fiddle:
http://jsfiddle.net/5cn9sm99/
I think this may be a shorter solution with the code you already have. You could wrap your arrow in an arrow container like this:
<g id="arrowContainer">
<polygon id="arrow" class="st2 west" points="78.4,105.3 80.2,107.1 79.1,108.3 77.2,106.4 75.5,109.7 74.1,108.6 75.9,105.1 75.1,104.3
73.3,107.7 71.9,106.6 73.8,103 72.9,102.1 71.2,105.6 69.8,104.5 71.7,100.9 63.5,92.7 63.5,92.7 41.5,70.7 41.4,70.8 39,74.3
34.5,62.5 46.3,67.1 42.5,69.5 64.6,91.6 65.2,92.1 72.9,99.8 76.5,98 77.6,99.5 74.1,101.1 74.9,101.9 78.6,100 79.7,101.4
76.2,103.1 75.9,102.9 77.1,104 80.8,102.3 81.9,103.8 "/>
</g>
Then add this styles to center the pivot point of the container:
#arrowContainer{ transform-origin: 50% 50%; }
Now replace the Rotations to target the arrowContainer and use Javascript or jQuery to add the classes you already created. Here is the full code.
var changeDirection = function changeClass(myClass){
$('#compass').attr("class", myClass);
}
div {
max-width: 300px;
}
.st0 {
fill: none;
stroke: #505050;
stroke-width: 4.11;
stroke-linecap: round;
stroke-miterlimit: 10;
}
.st1 {
fill: none;
stroke: #808080;
stroke-width: 2.57;
stroke-linecap: round;
stroke-miterlimit: 10;
}
.st2 {
fill: #505050;
}
.st3 {
opacity: 0.5;
}
.st4 {
fill: none;
}
/* Fill Colors */
.green {
fill: rgba(21, 255, 0, 0.5);
}
.dgreen {
fill: rgba(12, 140, 0, 0.5);
}
.red {
fill: rgba(255, 42, 0, 0.5);
}
.dred {
fill: rgba(140, 23, 0, 0.5);
}
/* Arrow */
#arrowContainer{
transform-origin: 50% 50%;
}
#arrow {
transform-origin: 50% 59.7%;
animation-name: wiggle;
animation-duration: 1s;
animation-fill-mode: forward;
-webkit-animation-fill-mode: forward;
-webkit-animation-iteration-count: infinite;
/* Safari 4.0 - 8.0 */
animation-iteration-count: infinite;
}
/* Rotations */
.north #arrowContainer {
-webkit-transform: rotate(45deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.northEast #arrowContainer {
-webkit-transform: rotate(90deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.east #arrowContainer {
-webkit-transform: rotate(135deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.southEast #arrowContainer {
-webkit-transform: rotate(180deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.south #arrowContainer {
-webkit-transform: rotate(225deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.southWest #arrowContainer {
-webkit-transform: rotate(270deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.west #arrowContainer {
-webkit-transform: rotate(315deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
.northWest #arrowContainer {
-webkit-transform: rotate(0deg);
-webkit-transition: -webkit-transform 0.5s ease-in;
}
/* Wiggle Animation */
/* safari and chrome */
#-webkit-keyframes compass {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(0deg);
}
}
#-webkit-keyframes wiggle {
0% {
-webkit-transform: rotate(4deg);
}
50% {
-webkit-transform: rotate(-4deg);
}
100% {
-webkit-transform: rotate(4deg);
}
}
/* firefox */
#-moz-keyframes wiggle {
0% {
-moz-transform: rotate(4deg);
}
50% {
-moz-transform: rotate(-4deg);
}
100% {
-moz-transform: rotate(4deg);
}
}
#keyframes wiggle {
0% {
transform: rotate(4deg);
}
50% {
transform: rotate(-4deg);
}
100% {
transform: rotate(4deg);
}
}
/* Button Styles */
.buttons{
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="buttons">
<button onclick="changeDirection('north')">North</button>
<button onclick="changeDirection('northEast')">NorthEast</button>
<button onclick="changeDirection('east')">East</button>
<button onclick="changeDirection('southEast')">South East</button>
<button onclick="changeDirection('south')">South</button>
<button onclick="changeDirection('southWest')">South West</button>
<button onclick="changeDirection('west')">West</button>
<button onclick="changeDirection('northWest')">North West</button>
</div>
<div id="compass" class="addClassHere">
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 116.3 144" style="enable-background:new 0 0 116.3 144;" xml:space="preserve">
<title>compass</title>
<line id="N" class="st0" x1="58.2" y1="31.3" x2="58.2" y2="49.6"/>
<line id="NW" class="st1" x1="18.5" y1="46.1" x2="31.4" y2="59"/>
<line id="W" class="st0" x1="3.6" y1="85.7" x2="21.9" y2="85.7"/>
<line id="SW" class="st1" x1="18.3" y1="125.5" x2="31.3" y2="112.5"/>
<line id="S" class="st0" x1="58" y1="140.3" x2="58" y2="122"/>
<line id="SE" class="st1" x1="97.7" y1="125.6" x2="84.8" y2="112.6"/>
<line id="E" class="st0" x1="113.4" y1="85.9" x2="95.1" y2="85.9"/>
<line id="NE" class="st1" x1="97.8" y1="46.2" x2="84.9" y2="59.1"/>
<path id="compass" class="st2" d="M69.6,28.8c6.7-6.3,7-16.9,0.7-23.6s-16.9-7-23.6-0.7s-7,16.9-0.7,23.6c0.2,0.2,0.4,0.5,0.7,0.7
c-31.5,6.3-51.9,37-45.6,68.5s37,51.9,68.5,45.6c31.5-6.3,51.9-37,45.6-68.5C110.6,51.4,92.6,33.4,69.6,28.8z M58.2,6.5
c5.6,0,10.2,4.6,10.2,10.2H48C48,11.1,52.6,6.5,58.2,6.5z M58.2,138.3c-29,0-52.5-23.5-52.5-52.5s23.5-52.5,52.5-52.5
c29,0,52.5,23.5,52.5,52.5c0,0,0,0,0,0C110.6,114.8,87.1,138.3,58.2,138.3z"/>
<path id="inner_compass" class="st2" d="M58.2,130.8c-24.9,0-45.2-20.2-45.2-45.2s20.2-45.2,45.2-45.2c24.9,0,45.2,20.2,45.2,45.1
c0,0,0,0,0,0C103.3,110.6,83.1,130.8,58.2,130.8z M58.2,43.8c-23.1,0-41.9,18.8-41.9,41.9s18.8,41.9,41.9,41.9s41.9-18.8,41.9-41.9
C100.1,62.6,81.3,43.8,58.2,43.8L58.2,43.8z"/>
<g id="NNW" class="st3">
<path id="nnwPie" class="st4 green" d="M57.9,27.7v58.2l-41-41C27.8,33.9,42.5,27.7,57.9,27.7z"/>
</g>
<g id="WNW" class="st3">
<path id="wnwPie" class="st4 dgreen" d="M57.9,85.8H0.2v-0.2c0-15.3,6-30,16.8-40.8L57.9,85.8z"/>
</g>
<g id="WSW">
<path id="wswPie" class="st4" d="M57.9,85.8l-40.8,40.8c-10.8-10.8-16.9-25.5-17-40.8H57.9z"/>
</g>
<g id="SSW">
<path id="sswPie" class="st4" d="M57.9,85.8v57.8c-15.3,0-30-6.2-40.8-17L57.9,85.8z"/>
</g>
<g id="SSE">
<path id="ssePie" class="st4 red" d="M99,126.9c-10.8,10.8-25.5,16.8-40.8,16.8H58V85.8L99,126.9z"/>
</g>
<g id="ESE">
<path id="esePie" class="st4 dred" d="M116.2,85.8c0,15.4-6.2,30.2-17.2,41l-41-41H116.2z"/>
</g>
<g id="ENE">
<path id="enePie" class="st4" d="M116.2,85.7v0.2H57.9l41.2-41.2C110.1,55.5,116.2,70.3,116.2,85.7z"/>
</g>
<g id="NNE">
<path id="nnePie" class="st4" d="M99.1,44.6L57.9,85.8V27.7h0.2C73.5,27.6,88.3,33.7,99.1,44.6z"/>
</g>
<g id="arrowContainer">
<polygon id="arrow" class="st2 west" points="78.4,105.3 80.2,107.1 79.1,108.3 77.2,106.4 75.5,109.7 74.1,108.6 75.9,105.1 75.1,104.3
73.3,107.7 71.9,106.6 73.8,103 72.9,102.1 71.2,105.6 69.8,104.5 71.7,100.9 63.5,92.7 63.5,92.7 41.5,70.7 41.4,70.8 39,74.3
34.5,62.5 46.3,67.1 42.5,69.5 64.6,91.6 65.2,92.1 72.9,99.8 76.5,98 77.6,99.5 74.1,101.1 74.9,101.9 78.6,100 79.7,101.4
76.2,103.1 75.9,102.9 77.1,104 80.8,102.3 81.9,103.8 "/>
</g>
</svg>
</div>
I'm working on SVG animations with CSS and I've noticed that with my line drawing animations, any SVG rect (#clipboard-border and #clipboard-clip-border) stroke always excludes a bit of the top-left corner, which makes it an incomplete rectangle.
I've tried adjusting the stroke-dasharray and stroke-dashoffset measurements within the CSS, as well as adjusting the sizes and pixel coordinated within the SVG code, but neither are the problem it seems. Help?
html,
body {
width: 100%;
height: 100%;
background-color: #CECECE;
}
div {
text-align: center;
}
svg {
display: inline-block;
width: 120px;
margin: 3% auto;
padding: 0px 100px;
}
/* ---------------------
SVG RULES
--------------------- */
/* All grey strokes */
#clipboard-border,
.clipboard-content,
.clipboard-borders,
.mech-pencil-borders {
fill: none;
stroke: #4D5152;
stroke-width: 6;
stroke-miterlimit: 10;
}
/* All things white */
#clipboard-paper-fill,
#mech-pencil-eraser-fill {
fill: #F3F7F6;
}
/* All things green */
#mech-pencil-point-fill,
#mech-pencil-top-fill {
fill: #25B686;
}
/* All things blue */
#clipboard-fill {
fill: #85D0D3;
}
/* All things yellow */
#clipboard-clip-fill,
#mech-pencil-grip {
fill: #FBFBCE;
}
#clipboard-knob-1,
#clipboard-knob-2,
#clipboard-knob-3,
#mech-pencil-bottom-btn,
#mech-pencil-top-btn {
stroke-dasharray: 8px;
stroke-dashoffset: 8px;
animation: trace .5s ease-out forwards;
}
/* ---------------------
ANIMATION KEYFRAMES
--------------------- */
#keyframes trace {
100% {
stroke-dashoffset: 0px;
}
}
#keyframes fill-it {
100% {
opacity: 1;
}
}
#keyframes grow {
0% {
transform: scale(0);
}
30% {
transform: scale(1.1);
}
60% {
transform: scale(.9);
}
}
/* ---------------------
SVG ANIMATION: INSIGHT & PLANNING ICON
--------------------- */
#clipboard-clip-border {
stroke-dasharray: 180px;
stroke-dashoffset: 180px;
animation: trace .2s ease-out forwards;
}
#clipboard-clip-fill {
opacity: 0;
animation: fill-it .2s .2s ease-in-out forwards;
}
#clipboard-border {
stroke-dasharray: 640px;
stroke-dashoffset: 640px;
animation: trace 1.25s ease-in-out forwards;
}
#clipboard-fill,
#mech-pencil-point-fill,
#mech-pencil-top-fill {
opacity: 0;
animation: fill-it .25s 1.25s ease-in-out forwards;
}
#clipboard-paper-border {
stroke-dasharray: 400px;
stroke-dashoffset: 400px;
animation: trace 1s ease-out forwards;
}
#clipboard-paper-fill,
#mech-pencil-eraser-fill,
#mech-pencil-grip {
opacity: 0;
animation: fill-it .75s 1s ease-in-out forwards;
}
#clipboard-content-line-1 {
stroke-dasharray: 30px;
stroke-dashoffset: 30px;
animation: trace .5s ease-out forwards;
}
#clipboard-content-line-7,
#clipboard-clip-detail {
stroke-dasharray: 52px;
stroke-dashoffset: 52px;
animation: trace .5s ease-out forwards;
}
#clipboard-content-line,
#clipboard-content-line-even,
#mech-pencil-eraser-border {
stroke-dasharray: 80px;
stroke-dashoffset: 80px;
animation: trace .75s ease-out forwards;
}
#mech-pencil-border-left,
#mech-pencil-border-right {
stroke-dasharray: 115px;
stroke-dashoffset: 115px;
animation: trace .75s ease-out forwards;
}
#mech-pencil-point-border {
stroke-dasharray: 60px;
stroke-dashoffset: 60px;
animation: trace .5s ease-out forwards;
}
#mech-pencil-tip,
#mech-pencil-top {
stroke-dasharray: 10px;
stroke-dashoffset: 10px;
animation: trace .4s ease-out forwards;
}
/* ---------------------
ANIMATION DELAYS
--------------------- */
#clipboard-knob-1,
#clipboard-knob-2 {
animation-delay: .25s;
}
#clipboard-clip-detail,
#clipboard-content-line,
#clipboard-content-line-7,
#clipboard-knob-2 {
animation-delay: .5s;
}
#mech-pencil-bottom-btn,
#mech-pencil-top-btn {
animation-delay: 1.25s;
}
<div class="wrapper">
<!-- INSIGHT & PLANNING ICON -->
<svg id="insight-planning" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="200px" height="200px" viewBox="0 0 200 200">
<g class="clipboard">
<rect id="clipboard-fill" x="15.015" y="11.44" width="132" height="182" />
<rect id="clipboard-paper-fill" x="30.753" y="11.44" width="100" height="151" />
<g class="clipboard-content">
<line id="clipboard-content-line-even" x1="46.491" y1="68.096" x2="115.738" y2="68.096" />
<line id="clipboard-content-line" x1="46.491" y1="80.687" x2="115.738" y2="80.687" />
<line id="clipboard-content-line-even" x1="46.491" y1="93.277" x2="115.738" y2="93.277" />
<line id="clipboard-content-line" x1="46.491" y1="105.867" x2="115.738" y2="105.867" />
<line id="clipboard-content-line-even" x1="46.491" y1="118.458" x2="115.738" y2="118.458" />
<line id="clipboard-content-line-7" x1="46.491" y1="131.048" x2="96.852" y2="131.048" />
<line id="clipboard-content-line-1" x1="115.738" y1="49.211" x2="90.557" y2="49.211" />
</g>
<rect id="clipboard-border" x="15.015" y="11.44" width="132" height="182" />
</g>
<g class="mech-pencil-fills">
<rect id="mech-pencil-grip" x="166.099" y="96.425" width="18" height="47" />
<rect id="mech-pencil-top-fill" x="166.099" y="30.325" width="18" height="66" />
<rect id="mech-pencil-eraser-fill" x="166.099" y="11.44" width="18" height="18" />
<polygon id="mech-pencil-point-fill" points="184.985,143.639 184.985,159.376 175.542,168.819 166.099,159.376 166.099,143.639" />
</g>
<g class="mech-pencil-borders">
<line id="mech-pencil-border-left" x1="166.099" y1="143.639" x2="166.099" y2="30.325" />
<line id="mech-pencil-border-right" x1="184.985" y1="30.325" x2="184.985" y2="145" />
<rect id="mech-pencil-eraser-border" x="166.099" y="11.44" width="18" height="18" />
<polygon id="mech-pencil-point-border" points="184.985,143.639 184.985,159.376 175.542,168.819 166.099,159.376 166.099,143.639" />
<line id="mech-pencil-top" x1="175.542" y1="11.44" x2="175.542" y2="1.997" />
<line id="mech-pencil-tip" x1="175.542" y1="168.819" x2="175.542" y2="175.114" />
<line id="mech-pencil-bottom-btn" x1="175.542" y1="127.901" x2="175.542" y2="121.605" />
<line id="mech-pencil-top-btn" x1="175.542" y1="115.31" x2="175.542" y2="109.015" />
</g>
<g class="clipboard-clip">
<rect id="clipboard-clip-fill" x="49.639" y="5.144" width="62" height="25" />
</g>
<g class="clipboard-borders">
<polyline id="clipboard-paper-border" points="131.476,11.44 131.476,162.524 30.753,162.524 30.753,11.44" />
<rect id="clipboard-clip-border" x="49.639" y="5.144" width="62" height="25" />
<line id="clipboard-clip-detail" x1="59.081" y1="17.735" x2="103.148" y2="17.735" />
<line id="clipboard-knob-1" x1="65.376" y1="178.262" x2="71.672" y2="178.262" />
<line id="clipboard-knob-2" x1="77.967" y1="178.262" x2="84.262" y2="178.262" />
<line id="clipboard-knob-3" x1="90.557" y1="178.262" x2="96.852" y2="178.262" />
</g>
</svg>
</div>
Also posted in Codepen.
Just add stroke-linecap: square; to the CSS declarations for the SVG object.
svg {
display: inline-block;
width: 120px;
margin: 3% auto;
padding: 0px 100px;
stroke-linecap: square; /* <-- Add this */
}
Example:
Here's an SVG with two paths (open, not closed). The path drawn with "butt" line endings has a bit missing in the top corner, but the other path (drawn with "square" line endings) doesn't have this issue.
<svg width="250" height="100" viewBox="0 0 250 100">
<path d="M10 10h80v80h-80v-80" style="stroke:#000; stroke-width:10px; fill:none; stroke-linecap: square;"/>
<text x="50" y="70" text-anchor="middle">Square</text>
<path d="M160 10h80v80h-80v-80" style="stroke:#000; stroke-width:10px; fill:none; stroke-linecap: butt;"/>
<text x="200" y="70" text-anchor="middle">Butt</text>
</svg>
P.S. I like your work, but next time please consider making a minimal, complete and verifiable example to illustrate the problem. That way people won't have to wade through reams of code to discover what's going wrong :-)