Solution 1 :

For the :hover and base rect animation duplication, they can each be refactored into their own block.

#svg rect {
  --animation-delay: 0.1s;
  animation: ani 1.8s linear infinite var(--animation-delay);
}

#svg rect:hover {
  animation-play-state: paused;
}

I would store the animation delay in a custom property and add it to the lone animation call.

#svg rect {
  --animation-delay: 0.1s;
  animation: ani 1.8s linear infinite var(--animation-delay);
}

Now you can override the delay later when necessary, such as:

#svg rect:nth-child(3) { --animation-delay: 0.2s; }

The delay will automatically update for that child’s animation.

Here’s the complete code:

#svg rect {
  --animation-delay: 0.1s;
  animation: ani 1.8s linear infinite var(--animation-delay);
}

#svg rect:hover {
  animation-play-state: paused;
}

<!-- No way to shorten this in pure CSS   -->

#svg rect:nth-child(2) { --animation-delay: 0.2s; }
#svg rect:nth-child(3) { --animation-delay: 0.3s; }
#svg rect:nth-child(4) { --animation-delay: 0.4s; }
#svg rect:nth-child(5) { --animation-delay: 0.5s; }

@keyframes ani {
  0% {
    fill: #0057B8;
  }

  20% {
    fill: #F11E4A;
  }

  40% {
    fill: #F8A527;
  }

  60% {
    fill: #266D7F;
  }

  80% {
    fill: #82A;
  }

  100% {
    fill: #0057B8;
  }
}
<svg id="svg" width="401" height="275" viewBox="0 0 401 275" fill="none" >
  <rect width="401" height="275" fill="white" />
  <rect x="50" y="91" width="57" height="57" fill="#C4C4C4" />
  <rect x="118" y="91" width="57" height="57" fill="#C4C4C4" />
  <rect x="186" y="91" width="57" height="57" fill="#C4C4C4" />
  <rect x="254" y="91" width="57" height="57" fill="#C4C4C4" />
</svg>

jsFiddle

Solution 2 :

All your :hover effects are the same, and so are your animation properties so you can simplify those to one rule each:

#svg rect {
    animation: ani 1.8s linear infinite;
}

#svg rect:hover {
    animation-play-state: paused;
}

that would already reduce the lines a lot, for the animation delays themselves your method is ok.

Solution 3 :

If you are intrested in a CSS solution you can do something like below. It’s a bit different animation but you can easily scale it by keeping the same code.

The trick is to animate the same gradient for all the boxes to simulate the color changes. Note how I made the pseudo element relative to the .box not the child elements to have the same layer

.box {
   display:inline-flex;
   margin:5px;
   padding:50px 20px;
   position:relative;
   background:right/800% 100%;
   background-image:linear-gradient(to left,#0057B8,#F11E4A,#F8A527,#266D7F,#82A,#0057B8);
   animation: ani 1.8s linear infinite;
}
.box > div {
  margin:5px;
  height:55px;
  width:55px;
  background-image:inherit;
  -webkit-mask: linear-gradient(#fff,#fff);
          mask: linear-gradient(#fff,#fff);
}
.box > div:before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  background: right/1000% 100%;
  background-image:inherit;
  animation: ani 2s linear infinite;
}

.box > div:hover:before {
  animation-play-state:paused;
}

@keyframes ani {
  100% {
    background-position:left;
  }
}
<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>
<br>
<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

Problem :

I’m working on this to have the rect to change colors. Each rect will change on a 0.1s delay.

Let’s say I want to have more rectangles or path, how can I simplify the code? I think it could be simplified using scss but what about using CSS? is there a smarter way to do so rather than the way I have done?

#svg rect:nth-child(1) {
  animation: ani 1.8s linear infinite;
  animation-delay: 0.1s;
}

#svg rect:nth-child(1):hover {
  animation-play-state: paused;
}

#svg rect:nth-child(2) {
  animation: ani 1.8s linear infinite;
  animation-delay: 0.2s;
}

#svg rect:nth-child(2):hover {
  animation-play-state: paused;
}

#svg rect:nth-child(3) {
  animation: ani 1.8s linear infinite;
  animation-delay: 0.3s;
}

#svg rect:nth-child(3):hover {
  animation-play-state: paused;
}

#svg rect:nth-child(4) {
  animation: ani 1.8s linear infinite;
  animation-delay: 0.4s;
}

#svg rect:nth-child(4):hover {
  animation-play-state: paused;
}

#svg rect:nth-child(5) {
  animation: ani 1.8s linear infinite;
  animation-delay: 0.5s;
}

#svg rect:nth-child(5):hover {
  animation-play-state: paused;
}

@keyframes ani {
  0% {
    fill: #0057B8;
  }
  20% {
    fill: #F11E4A;
  }
  40% {
    fill: #F8A527;
  }
  60% {
    fill: #266D7F;
  }
  80% {
    fill: #82A;
  }
  100% {
    fill: #0057B8;
  }
}
<svg id="svg" width="401" height="275" viewBox="0 0 401 275" fill="none" >
<rect width="401" height="275" fill="white"/>
<rect x="50" y="91" width="57" height="57" fill="#C4C4C4"/>
<rect x="118" y="91" width="57" height="57" fill="#C4C4C4"/>
<rect x="186" y="91" width="57" height="57" fill="#C4C4C4"/>
<rect x="254" y="91" width="57" height="57" fill="#C4C4C4"/>
</svg>

Comments

Comment posted by Code Review Stack Exchange

What you are asking for is a code review and you should be asking such questions on the

Comment posted by Organic Heart

Thanks!! I didn’t know about the

Comment posted by developer.mozilla.org/en-US/docs/Web/CSS/–

@Jalene By the way, you can name it anything:

Comment posted by Organic Heart

Thanks! is there a better way to handle the

Comment posted by Stephane Vanraes

If you can use css variables you can use those and set

By