Q:

Как конвертировать SVG SMIL анимацию в CSS3 анимацию

Мой  SVG анимирован с использованием SMIL - анимации.  
SVG SMIL анимация не поддерживается в IE.
Поэтому я хотел бы заменить анимационную часть на CSS-анимацию, чтобы сделать анимацию более широко поддерживаемой.    

<svg width="25%" height="25%" viewBox="0 0 64 64">
  <g>
   <circle r="5" cx="24" cy="0" transform="translate(32,32)" stroke-width="0">
     <animate attributeName="fill-opacity" dur="750ms" values="1;.9;.85;.7;.4;.3;.3;.3;1" repeatCount="indefinite"></animate>
  </circle>
  <circle r="5" cx="16.970562748477143" cy="16.97056274847714" transform="translate(32,32)" stroke-width="0">
     <animate attributeName="fill-opacity" dur="750ms" values=".3;1;.9;.85;.7;.4;.3;.3;.3" repeatCount="indefinite"></animate>
  </circle>
  <circle r="5" cx="1.4695761589768238e-15" cy="24" transform="translate(32,32)" stroke-width="0">
     <animate attributeName="fill-opacity" dur="750ms" values=".3;.3;1;.9;.85;.7;.4;.3;.3" repeatCount="indefinite"></animate>
  </circle>
  <circle r="5" cx="-16.97056274847714" cy="16.970562748477143" transform="translate(32,32)" stroke-width="0">
     <animate attributeName="fill-opacity" dur="750ms" values=".3;.3;.3;1;.9;.85;.7;.4;.3" repeatCount="indefinite"></animate>
  </circle>
  <circle r="5" cx="-24" cy="2.9391523179536475e-15" transform="translate(32,32)" stroke-width="0">
    <animate attributeName="fill-opacity" dur="750ms" values=".4;.3;.3;.3;1;.9;.85;.7;.4" repeatCount="indefinite"></animate>
  </circle>
  <circle r="5" cx="-16.970562748477143" cy="-16.97056274847714" transform="translate(32,32)" stroke-width="0">
    <animate attributeName="fill-opacity" dur="750ms" values=".7;.4;.3;.3;.3;1;.9;.85;.7" repeatCount="indefinite"></animate>
  </circle>
  <circle r="5" cx="-4.408728476930472e-15" cy="-24" transform="translate(32,32)" stroke-width="0">
    <animate attributeName="fill-opacity" dur="750ms" values=".85;.7;.4;.3;.3;.3;1;.9;.85" repeatCount="indefinite"></animate>
  </circle>
  <circle r="5" cx="16.970562748477136" cy="-16.970562748477143" transform="translate(32,32)" stroke-width="0">
    <animate attributeName="fill-opacity" dur="750ms" values=".9;.85;.7;.4;.3;.3;.3;1;.9" repeatCount="indefinite"></animate>
  </circle>
</g>

Как заменить вышеприведенную анимацию SVG SMIL на CSS-анимациию? 

A:

circle {
    animation: fade 800ms infinite;
}
circle:nth-child(1) { animation-delay: -700ms; }
circle:nth-child(2) { animation-delay: -600ms; }
circle:nth-child(3) { animation-delay: -500ms; }
circle:nth-child(4) { animation-delay: -400ms; }
circle:nth-child(5) { animation-delay: -300ms; }
circle:nth-child(6) { animation-delay: -200ms; }
circle:nth-child(7) { animation-delay: -100ms; }

@keyframes fade {
     0% { fill-opacity: 1; }
    12% { fill-opacity: .9; }
    25% { fill-opacity: .85; }
    37% { fill-opacity: .7; }
    50% { fill-opacity: .4; }
    62%, 87% { fill-opacity: .3; }
   100% { fill-opacity: 1; }
}
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 64 64">
 <g transform="translate(32,32)" stroke-width="0">
  <circle r="5" cx= "24" cy=  "0" />
  <circle r="5" cx= "17" cy= "17" />
  <circle r="5" cx=  "0" cy= "24" />
  <circle r="5" cx="-17" cy= "17" />
  <circle r="5" cx="-24" cy=  "0" />
  <circle r="5" cx="-17" cy="-17" />
  <circle r="5" cx=  "0" cy="-24" />
  <circle r="5" cx= "17" cy="-17" />
 </g>
</svg>

A:

Странно... Метки CSS и CSS3 есть, а ответа такого нет. Непорядок... 
Исправлю, дополню "pure CSS":

body { margin: 0; display: grid; place-items: center; height: 100vh; background: url('https://i.stack.imgur.com/m9NKc.png') no-repeat, #fcfcff; }

.loader {
  /* Размер и позиции кругов */
  --radius: -0.344em; --size90: 0.689em; --size65: 0.496em; --size62: 0.472em;
  /* Нет смысла менять (смотри 'font-size' ниже) */
  height: 1em; width: 1em;
  /* Если изменить радиус скругления углов (например, на '40%' 
     или '10% 50%'), то могут получиться интересные формы. */
  border-radius: 50%;
  /* Базовый размер (от него всё пляшет) */
  font-size: 45vh;
  /* Далее сама анимация */
  animation: loader 1s infinite;
}

@keyframes loader {
  0%, 100% { box-shadow: 0px calc(var(--size90) * -1) 0 var(--radius) black, var(--size65) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.1), var(--size90) 0px 0 var(--radius) rgba(0, 0, 0, 0.1), var(--size65) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.25), 0px var(--size90) 0 var(--radius) rgba(0, 0, 0, 0.4), calc(var(--size65) * -1) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.55), calc(var(--size90) * -1) 0px 0 var(--radius) rgba(0, 0, 0, 0.7), calc(var(--size65) * -1) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.85); }
  12.5% { box-shadow: 0px calc(var(--size90) * -1) 0 var(--radius) rgba(0, 0, 0, 0.85), var(--size65) calc(var(--size62) * -1) 0 var(--radius) black, var(--size90) 0px 0 var(--radius) rgba(0, 0, 0, 0.1), var(--size65) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.1), 0px var(--size90) 0 var(--radius) rgba(0, 0, 0, 0.25), calc(var(--size65) * -1) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.4), calc(var(--size90) * -1) 0px 0 var(--radius) rgba(0, 0, 0, 0.55), calc(var(--size65) * -1) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.7); }
  25% { box-shadow: 0px calc(var(--size90) * -1) 0 var(--radius) rgba(0, 0, 0, 0.7), var(--size65) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.85), var(--size90) 0px 0 var(--radius) black, var(--size65) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.1), 0px var(--size90) 0 var(--radius) rgba(0, 0, 0, 0.1), calc(var(--size65) * -1) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.25), calc(var(--size90) * -1) 0px 0 var(--radius) rgba(0, 0, 0, 0.4), calc(var(--size65) * -1) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.55); }
  37.5% { box-shadow: 0px calc(var(--size90) * -1) 0 var(--radius) rgba(0, 0, 0, 0.55), var(--size65) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.7), var(--size90) 0px 0 var(--radius) rgba(0, 0, 0, 0.85), var(--size65) var(--size62) 0 var(--radius) black, 0px var(--size90) 0 var(--radius) rgba(0, 0, 0, 0.1), calc(var(--size65) * -1) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.1), calc(var(--size90) * -1) 0px 0 var(--radius) rgba(0, 0, 0, 0.25), calc(var(--size65) * -1) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.4); }
  50% { box-shadow: 0px calc(var(--size90) * -1) 0 var(--radius) rgba(0, 0, 0, 0.4), var(--size65) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.55), var(--size90) 0px 0 var(--radius) rgba(0, 0, 0, 0.7), var(--size65) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.85), 0px var(--size90) 0 var(--radius) black, calc(var(--size65) * -1) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.1), calc(var(--size90) * -1) 0px 0 var(--radius) rgba(0, 0, 0, 0.1), calc(var(--size65) * -1) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.25); }
  62.5% { box-shadow: 0px calc(var(--size90) * -1) 0 var(--radius) rgba(0, 0, 0, 0.25), var(--size65) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.4), var(--size90) 0px 0 var(--radius) rgba(0, 0, 0, 0.55), var(--size65) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.7), 0px var(--size90) 0 var(--radius) rgba(0, 0, 0, 0.85), calc(var(--size65) * -1) var(--size62) 0 var(--radius) black, calc(var(--size90) * -1) 0px 0 var(--radius) rgba(0, 0, 0, 0.1), calc(var(--size65) * -1) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.1); }
  75% { box-shadow: 0px calc(var(--size90) * -1) 0 var(--radius) rgba(0, 0, 0, 0.1), var(--size65) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.25), var(--size90) 0px 0 var(--radius) rgba(0, 0, 0, 0.4), var(--size65) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.55), 0px var(--size90) 0 var(--radius) rgba(0, 0, 0, 0.7), calc(var(--size65) * -1) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.85), calc(var(--size90) * -1) 0px 0 var(--radius) black, calc(var(--size65) * -1) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.1); }
  87.5% { box-shadow: 0px calc(var(--size90) * -1) 0 var(--radius) rgba(0, 0, 0, 0.1), var(--size65) calc(var(--size62) * -1) 0 var(--radius) rgba(0, 0, 0, 0.1), var(--size90) 0px 0 var(--radius) rgba(0, 0, 0, 0.25), var(--size65) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.4), 0px var(--size90) 0 var(--radius) rgba(0, 0, 0, 0.55), calc(var(--size65) * -1) var(--size62) 0 var(--radius) rgba(0, 0, 0, 0.7), calc(var(--size90) * -1) 0px 0 var(--radius) rgba(0, 0, 0, 0.85), calc(var(--size65) * -1) calc(var(--size62) * -1) 0 var(--radius) black; }
}
<div class="loader"></div>

Код может показаться громоздким из-за синтаксиса CSS-переменных и rgba(r, g, b, a).
  Использовал переменные при подгонке адаптивности, да так и оставил - может, кто 
  поиграться захочет. А если понадобится сократить, то можно заменить переменные на 
  коэффициенты в em-ах, которые указаны в переменных.

