7

I am trying to animate an SVG in image/object tag but it is not working

svg {
  width: 100%;
  height: 200px;
}

.rotate-45 {
  transform-origin: center;
  transform: rotate(45deg);
}

.rotate {
  transform-origin: center;
  animation: rotate 1s ease-in-out infinite;
}

.rotate-back {
  transform-origin: center;
  animation: rotate 1s ease-in-out infinite;
  animation-direction: alternate;
}

.left {
  animation: move 1s ease-in-out infinite;
}

.right {
  animation: move 1s ease-in-out infinite;
}

@keyframes rotate {
  100% {
    transform: rotate(calc(90deg + 45deg));
  }
}

@keyframes move {
  50% {
    transform: translate(-30px, -30px);
  }
}
 <svg width="100%" height="100%" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g transform="translate(500,500)">
      <rect class="rotate-45 rotate-back" x="-5" y="-5" width="10" height="10" stroke="#00a99d" stroke-width="20" fill="none" />
      <rect class="rotate-45 rotate" x="-50" y="-50" width="100" height="100" stroke="#00a99d" stroke-width="20" stroke-linejoin="bevel" fill="none" />
      <g transform="translate(-50,0) rotate(-45)">
        <polyline class="left" points="40,-40 50,-50 -40,-50 -50,-40 -50,50 -40,40" stroke="#00a99d" stroke-width="20" fill="none" />
      </g>
      <g transform="translate(50,0) rotate(135)">
        <polyline class="right" points="40,-40 50,-50 -40,-50 -50,-40 -50,50 -40,40" stroke="#00a99d" stroke-width="20" fill="none" />
      </g>
      <text y="-140" text-anchor="middle" font-weight="bold" font-size="3em" font-family="sans-serif">loading data...</text>
    </g>
  </svg>

How to animate the SVG inside the image tag along side with CSS

Here is a plunker for that code https://plnkr.co/edit/TdfR7cpVaQArtcUs0Hro?p=preview

Kaiido
  • 123,334
  • 13
  • 219
  • 285
Sibiraj
  • 4,486
  • 7
  • 33
  • 57
  • 1
    you titles says nothing about the problem. please specifically explain in the title your issue in short – vsync Sep 05 '17 at 09:03
  • you seem to want help in doing CSS animation, this has nothing to do with SVG. – vsync Sep 05 '17 at 09:04
  • 1
    Include your CSS in your svg directly, html's document's CSS can't target img's content : https://plnkr.co/edit/dtjUhZpzbm3NjdzsBKch?p=preview – Kaiido Sep 05 '17 at 09:05
  • 1
    You can also use `` if you dont want to have to embed it for `img` tags to work. The above code will work in an `object` tag – Deckerz Sep 05 '17 at 09:07
  • Possible duplicate of [img src SVG changing the fill color](https://stackoverflow.com/questions/24933430/img-src-svg-changing-the-fill-color) – Kaiido Sep 05 '17 at 09:07
  • @Deckerz, `` tags are not allowed to load external resources though. – Kaiido Sep 05 '17 at 09:08
  • 1
    @Kaiido did you not read my entire message? I said if you dont want to have to embed it for `img` tags to work. This works in an `object` tag – Deckerz Sep 05 '17 at 09:09
  • @Deckerz I wasn't sure what *"if you dont want to have to embed it for `img` tag"* really meant. – Kaiido Sep 05 '17 at 09:12
  • Thanks, everyone. got the solution. Can someone post an answer to close this question? Another doubt is that can the style used inside this svg have its effect on other elements – Sibiraj Sep 05 '17 at 09:13
  • @Kaiido fair enough my bad with wording then – Deckerz Sep 05 '17 at 09:13
  • @Kaiido. I am using your answer. – Sibiraj Sep 05 '17 at 09:14

3 Answers3

13

You can't animate the internals of an <img> from the outside. Even if it is an SVG. There are two reasons for this:

  1. CSS doesn't apply across document boundaries, and
  2. Images referenced via an <img> must be self contained.

Animations should work if you put the CSS inside the external SVG (in a <style> element as normal).

Note also that you will need to change the way you do transform-origin. The way it works in Chrome is convenient, but it is wrong according to the current spec. It won't work on other browsers like Firefox.

<svg width="100%" height="100%" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
  <style>
.rotate-45 {
  transform-origin: 0px 0px;
  transform: rotate(45deg);
}

.rotate {
  transform-origin: 0px 0px;
  animation: rotate 1s ease-in-out infinite;
}

.rotate-back {
  transform-origin: 0px 0px;
  animation: rotate 1s ease-in-out infinite;
  animation-direction: alternate;
}

.left {
  animation: move 1s ease-in-out infinite;
}

.right {
  animation: move 1s ease-in-out infinite;
}

@keyframes rotate {
  100% {
    transform: rotate(135deg);
  }
}

@keyframes move {
  50% {
    transform: translate(-30px, -30px);
  }
}
  </style>
  <g transform="translate(500,500)">
    <rect class="rotate-45 rotate-back" x="-5" y="-5" width="10" height="10" stroke="#00a99d" stroke-width="20" fill="none"/>
    <rect class="rotate-45 rotate" x="-50" y="-50" width="100" height="100" stroke="#00a99d" stroke-width="20" stroke-linejoin="bevel" fill="none"/>
    <g transform="translate(-50,0) rotate(-45)"><polyline class="left" points="40,-40 50,-50 -40,-50 -50,-40 -50,50 -40,40" stroke="#00a99d" stroke-width="20" fill="none"/></g>
    <g transform="translate(50,0) rotate(135)"><polyline class="right" points="40,-40 50,-50 -40,-50 -50,-40 -50,50 -40,40" stroke="#00a99d" stroke-width="20" fill="none"/></g>
    <text y="-140" text-anchor="middle" font-weight="bold" font-size="3em" font-family="sans-serif">loading data...</text>
  </g>
</svg>
Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • A doubt is that can the style used inside this svg have its effect on other elements – Sibiraj Sep 05 '17 at 09:17
  • 3
    No. As I said. CSS doesn't work across document boundaries. This is true whether it is an SVG or anything else. – Paul LeBeau Sep 05 '17 at 09:19
  • If you save the snippet's code to let's say "example.com/icon.svg" and then try to add it to some HTML document by doing this: then the animations work as expected in Chrome and Firefox, but not in Safari or iOS! Why does this happen? – Giorgos Iordanidis Apr 29 '22 at 19:05
0

You can use <?xml-stylesheet href="style.css" type="text/css"?> if you dont want to have to embed it for img tags to work. The above code will work in an object tag

If you want img tags to work do what Kaiido suggested and embed it.

Deckerz
  • 2,606
  • 14
  • 33
0

If you're working with pure JavaScript or some other environment that doesn't automatically include SVG's inline in your HTML output (eg like create-react-app does), here's a solution that might come in handy for you:

<img id="logo" src="logo.svg" />
<script>
// load logo inline for animation on hover
const loadLogo = async () => {
  // get logo, parse source text, and insert text into doc
  document.write(await (await fetch("logo.svg")).text());
  // remove fallback img logo
  document.querySelector("img#logo").remove();
};
loadLogo();
</script>

All this does is attempt to load an image at a given url/path, then insert its text contents right into the document, in place. Then you can style it from other style sheets, manipulate sub-elements with javascript, have user interaction animations, and etc. If it fails to load for any reason, there is an <img> there as a backup.

This could be written to be more general too, but this was just a quick solution I used once.


Another solution is to just embed the SVG using <object> as explained here, though that could have some limitations depending on what you want to do.

V. Rubinetti
  • 1,324
  • 13
  • 21