AI CSS Animations

Solar Farm Day Cycle

An accent sun rises behind a field of tilted hairline solar panels, arcs across the sky on two eased axes and sets, while a glint slides over every panel as the light moves.

Also known as: solar panel animation, isometric solar farm, sun arc animation, hairline animation.

HTML

<div class="hln-solar-day" role="img" aria-label="The sun arcs over a field of solar panels"><svg viewBox="-65 -25.91 150 81.82" aria-hidden="true"><g transform="translate(12 8)"><g class="hln-solar-day-sx"><g class="hln-solar-day-sy"><g class="hln-solar-day-rays"><line x1="7.5" y1="0" x2="10" y2="0"/><line x1="5.3" y1="5.3" x2="7.07" y2="7.07"/><line x1="0" y1="7.5" x2="0" y2="10"/><line x1="-5.3" y1="5.3" x2="-7.07" y2="7.07"/><line x1="-7.5" y1="0" x2="-10" y2="0"/><line x1="-5.3" y1="-5.3" x2="-7.07" y2="-7.07"/><line x1="0" y1="-7.5" x2="0" y2="-10"/><line x1="5.3" y1="-5.3" x2="7.07" y2="-7.07"/></g><circle r="5.5" class="hln-solar-day-a"/></g></g></g><g><polygon points="-36,18 20,46 20,44 -36,16"/><polygon points="56,28 20,46 20,44 56,26"/><polygon points="0,-2 56,26 20,44 -36,16"/></g><polyline points="15,37.5 20,40 30,35" fill="none" class="hln-solar-day-l"/><line x1="-6.5" y1="5.75" x2="-6.5" y2="2.65"/><line x1="5.5" y1="11.75" x2="5.5" y2="8.65"/><polygon points="-9,3 6,10.5 6,11.3 -9,3.8"/><polygon points="15,0.5 6,10.5 6,11.3 15,1.3"/><polygon points="0,-7 15,0.5 6,10.5 -9,3"/><line x1="-3" y1="-3.67" x2="12" y2="3.83" class="hln-solar-day-l"/><line x1="-6" y1="-0.33" x2="9" y2="7.17" class="hln-solar-day-l"/><line x1="3" y1="-5.5" x2="-6" y2="4.5" class="hln-solar-day-l"/><line x1="6" y1="-4" x2="-3" y2="6" class="hln-solar-day-l"/><line x1="9" y1="-2.5" x2="0" y2="7.5" class="hln-solar-day-l"/><line x1="12" y1="-1" x2="3" y2="9" class="hln-solar-day-l"/><g class="hln-solar-day-glint"><line x1="-0.27" y1="-5.97" x2="-7.83" y2="2.43"/><line x1="0.63" y1="-5.52" x2="-6.93" y2="2.88"/></g><line x1="10.5" y1="14.25" x2="10.5" y2="11.15"/><line x1="22.5" y1="20.25" x2="22.5" y2="17.15"/><polygon points="8,11.5 23,19 23,19.8 8,12.3"/><polygon points="32,9 23,19 23,19.8 32,9.8"/><polygon points="17,1.5 32,9 23,19 8,11.5"/><line x1="14" y1="4.83" x2="29" y2="12.33" class="hln-solar-day-l"/><line x1="11" y1="8.17" x2="26" y2="15.67" class="hln-solar-day-l"/><line x1="20" y1="3" x2="11" y2="13" class="hln-solar-day-l"/><line x1="23" y1="4.5" x2="14" y2="14.5" class="hln-solar-day-l"/><line x1="26" y1="6" x2="17" y2="16" class="hln-solar-day-l"/><line x1="29" y1="7.5" x2="20" y2="17.5" class="hln-solar-day-l"/><g class="hln-solar-day-glint"><line x1="16.73" y1="2.52" x2="9.17" y2="10.93"/><line x1="17.63" y1="2.97" x2="10.07" y2="11.38"/></g><line x1="27.5" y1="22.75" x2="27.5" y2="19.65"/><line x1="39.5" y1="28.75" x2="39.5" y2="25.65"/><polygon points="25,20 40,27.5 40,28.3 25,20.8"/><polygon points="49,17.5 40,27.5 40,28.3 49,18.3"/><polygon points="34,10 49,17.5 40,27.5 25,20"/><line x1="31" y1="13.33" x2="46" y2="20.83" class="hln-solar-day-l"/><line x1="28" y1="16.67" x2="43" y2="24.17" class="hln-solar-day-l"/><line x1="37" y1="11.5" x2="28" y2="21.5" class="hln-solar-day-l"/><line x1="40" y1="13" x2="31" y2="23" class="hln-solar-day-l"/><line x1="43" y1="14.5" x2="34" y2="24.5" class="hln-solar-day-l"/><line x1="46" y1="16" x2="37" y2="26" class="hln-solar-day-l"/><g class="hln-solar-day-glint"><line x1="33.73" y1="11.03" x2="26.17" y2="19.43"/><line x1="34.63" y1="11.48" x2="27.07" y2="19.88"/></g><line x1="-21.5" y1="13.25" x2="-21.5" y2="10.15"/><line x1="-9.5" y1="19.25" x2="-9.5" y2="16.15"/><polygon points="-24,10.5 -9,18 -9,18.8 -24,11.3"/><polygon points="0,8 -9,18 -9,18.8 0,8.8"/><polygon points="-15,0.5 0,8 -9,18 -24,10.5"/><line x1="-18" y1="3.83" x2="-3" y2="11.33" class="hln-solar-day-l"/><line x1="-21" y1="7.17" x2="-6" y2="14.67" class="hln-solar-day-l"/><line x1="-12" y1="2" x2="-21" y2="12" class="hln-solar-day-l"/><line x1="-9" y1="3.5" x2="-18" y2="13.5" class="hln-solar-day-l"/><line x1="-6" y1="5" x2="-15" y2="15" class="hln-solar-day-l"/><line x1="-3" y1="6.5" x2="-12" y2="16.5" class="hln-solar-day-l"/><g class="hln-solar-day-glint"><line x1="-15.27" y1="1.52" x2="-22.83" y2="9.93"/><line x1="-14.37" y1="1.97" x2="-21.93" y2="10.38"/></g><line x1="-4.5" y1="21.75" x2="-4.5" y2="18.65"/><line x1="7.5" y1="27.75" x2="7.5" y2="24.65"/><polygon points="-7,19 8,26.5 8,27.3 -7,19.8"/><polygon points="17,16.5 8,26.5 8,27.3 17,17.3"/><polygon points="2,9 17,16.5 8,26.5 -7,19"/><line x1="-1" y1="12.33" x2="14" y2="19.83" class="hln-solar-day-l"/><line x1="-4" y1="15.67" x2="11" y2="23.17" class="hln-solar-day-l"/><line x1="5" y1="10.5" x2="-4" y2="20.5" class="hln-solar-day-l"/><line x1="8" y1="12" x2="-1" y2="22" class="hln-solar-day-l"/><line x1="11" y1="13.5" x2="2" y2="23.5" class="hln-solar-day-l"/><line x1="14" y1="15" x2="5" y2="25" class="hln-solar-day-l"/><g class="hln-solar-day-glint"><line x1="1.73" y1="10.03" x2="-5.83" y2="18.43"/><line x1="2.63" y1="10.48" x2="-4.93" y2="18.88"/></g><line x1="12.5" y1="30.25" x2="12.5" y2="27.15"/><line x1="24.5" y1="36.25" x2="24.5" y2="33.15"/><polygon points="10,27.5 25,35 25,35.8 10,28.3"/><polygon points="34,25 25,35 25,35.8 34,25.8"/><polygon points="19,17.5 34,25 25,35 10,27.5"/><line x1="16" y1="20.83" x2="31" y2="28.33" class="hln-solar-day-l"/><line x1="13" y1="24.17" x2="28" y2="31.67" class="hln-solar-day-l"/><line x1="22" y1="19" x2="13" y2="29" class="hln-solar-day-l"/><line x1="25" y1="20.5" x2="16" y2="30.5" class="hln-solar-day-l"/><line x1="28" y1="22" x2="19" y2="32" class="hln-solar-day-l"/><line x1="31" y1="23.5" x2="22" y2="33.5" class="hln-solar-day-l"/><g class="hln-solar-day-glint"><line x1="18.73" y1="18.52" x2="11.17" y2="26.93"/><line x1="19.63" y1="18.98" x2="12.07" y2="27.38"/></g><g><polygon points="12,38 16,40 16,33 12,31"/><polygon points="22,37 16,40 16,33 22,30"/><polygon points="18,28 22,30 16,33 12,31"/></g><polygon points="20.5,34.75 17.5,36.25 17.5,33.75 20.5,32.25" class="hln-solar-day-l"/></svg></div>

CSS

.hln-solar-day {
  --c: var(--hln-color, #ff4f2e);
  font-size: var(--hln-size, 16px);
  position: relative;
  display: grid;
  place-items: center;
  width: 22em;
  height: 12em;
  border-radius: 0.75em;
  background: #f6f5f1;
  overflow: hidden;
  --u: 1px;
}
.hln-solar-day svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: #ffffff;
  stroke: #1c1d21;
  stroke-width: 1.25;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.hln-solar-day svg * {
  vector-effect: non-scaling-stroke;
}
.hln-solar-day-l {
  stroke: #9a9ca3;
}
.hln-solar-day-a {
  fill: var(--c);
}
.hln-solar-day-a {
  stroke: var(--c);
}
.hln-solar-day-rays {
  fill: none;
  stroke: var(--c);
  animation: hln-solar-day-rays 8s linear infinite;
}
.hln-solar-day-sx {
  animation: hln-solar-day-sx 8s linear infinite;
}
.hln-solar-day-sy {
  animation: hln-solar-day-sy 8s linear infinite;
}
.hln-solar-day-glint {
  animation: hln-solar-day-glint 8s linear infinite;
}
@keyframes hln-solar-day-sx {
  0% { transform: translate(calc(var(--u) * -66), 0); opacity: 0; animation-timing-function: cubic-bezier(.37, 0, .63, 1); }
  8% { transform: translate(calc(var(--u) * -56), 0); opacity: 1; animation-timing-function: cubic-bezier(.37, 0, .63, 1); }
  72% { transform: translate(calc(var(--u) * 56), 0); opacity: 1; animation-timing-function: cubic-bezier(.37, 0, .63, 1); }
  80%, 100% { transform: translate(calc(var(--u) * 66), 0); opacity: 0; }
}
@keyframes hln-solar-day-sy {
  0% { transform: translate(0, calc(var(--u) * 6)); animation-timing-function: cubic-bezier(.33, 1, .68, 1); }
  40% { transform: translate(0, calc(var(--u) * -16)); animation-timing-function: cubic-bezier(.32, 0, .67, 0); }
  80%, 100% { transform: translate(0, calc(var(--u) * 6)); }
}
@keyframes hln-solar-day-rays {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(90deg); }
}
@keyframes hln-solar-day-glint {
  0%, 12% { opacity: 0; transform: translate(calc(var(--u) * 0), calc(var(--u) * 0)); animation-timing-function: ease-out; }
  18% { opacity: 1; transform: translate(calc(var(--u) * 1.5), calc(var(--u) * 0.75)); }
  62% { opacity: 1; transform: translate(calc(var(--u) * 12), calc(var(--u) * 6)); animation-timing-function: ease-in; }
  68%, 100% { opacity: 0; transform: translate(calc(var(--u) * 13.5), calc(var(--u) * 6.75)); }
}
@media (prefers-reduced-motion: reduce) {
  .hln-solar-day * {
    animation-play-state: paused !important;
    animation-delay: calc(var(--delay, 0s) - 3.2s) !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hln-solar-day, .hln-solar-day *, .hln-solar-day::before, .hln-solar-day::after, .hln-solar-day *::before, .hln-solar-day *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Customizing this snippet

  • Color: set --hln-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --hln-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 16px.
  • Speed: change the duration on the transition or animation shorthand. Staggered delays are relative, so they keep their rhythm.
  • Reduced motion: the rule at the end of the CSS turns the motion off for people who asked their OS for less of it. Keep it.

Similar hairline animations