AI CSS Animations

Animated Dashed Border Card Hover

A file drop zone whose dashed outline starts marching and turns accent on hover while the upload arrow bobs. The dashes live on an SVG rect with pathLength 100, so the loop has no seam.

Also known as: marching ants border css, animated dashed border, file upload drop zone hover.

Drop files here or browse, up to 10 MB

HTML

<div class="hfx-card-dashed-upload">
  <svg class="hfx-card-dashed-upload-frame" aria-hidden="true"><rect width="100%" height="100%" rx="12" pathLength="100"/></svg>
  <span class="hfx-card-dashed-upload-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3"/><path class="hfx-card-dashed-upload-arrow" d="M12 15V4m-4.5 4.5L12 4l4.5 4.5"/></svg></span>
  <strong>Drop files here</strong>
  <span class="hfx-card-dashed-upload-hint">or <u>browse</u>, up to 10 MB</span>
</div>

CSS

.hfx-card-dashed-upload {
  --c: var(--hfx-color, #3b82f6);
  font-size: var(--hfx-size, 16px);
  position: relative;
  display: grid;
  justify-items: center;
  gap: 0.3em;
  box-sizing: border-box;
  width: 15em;
  padding: 1.3em 1em 1.4em;
  border-radius: 0.8em;
  background: color-mix(in srgb, var(--c) 3%, transparent);
  font-family: system-ui, sans-serif;
  text-align: center;
  cursor: pointer;
  transition: background-color 0.3s ease;
}
.hfx-card-dashed-upload:hover { background: color-mix(in srgb, var(--c) 10%, transparent); }
.hfx-card-dashed-upload-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.hfx-card-dashed-upload-frame rect {
  rx: 0.8em;
  fill: none;
  stroke: color-mix(in srgb, var(--c) 50%, transparent);
  stroke-width: 1.5;
  stroke-dasharray: 1.5 1;
  transition: stroke 0.3s ease;
}
.hfx-card-dashed-upload:hover .hfx-card-dashed-upload-frame rect {
  stroke: var(--c);
  animation: hfx-card-dashed-upload-march 1s linear infinite;
}
.hfx-card-dashed-upload-icon {
  display: grid;
  place-items: center;
  width: 2.5em;
  height: 2.5em;
  margin-bottom: 0.35em;
  border-radius: 50%;
  background: color-mix(in srgb, var(--c) 14%, transparent);
  color: var(--c);
  transition: background-color 0.3s ease, color 0.3s ease;
}
.hfx-card-dashed-upload:hover .hfx-card-dashed-upload-icon {
  background: var(--c);
  color: #fff;
}
.hfx-card-dashed-upload-icon svg {
  width: 1.25em;
  height: 1.25em;
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.hfx-card-dashed-upload:hover .hfx-card-dashed-upload-arrow {
  animation: hfx-card-dashed-upload-bob 0.6s cubic-bezier(0.45, 0, 0.55, 1) infinite alternate;
}
.hfx-card-dashed-upload strong {
  font-size: 0.9em;
  font-weight: 600;
}
.hfx-card-dashed-upload-hint {
  font-size: 0.75em;
  opacity: 0.65;
}
.hfx-card-dashed-upload u {
  color: var(--c);
  font-weight: 600;
  text-underline-offset: 0.2em;
}
@keyframes hfx-card-dashed-upload-march {
  to { stroke-dashoffset: -2.5; }
}
@keyframes hfx-card-dashed-upload-bob {
  from { transform: translateY(0.1em); }
  to { transform: translateY(-0.2em); }
}

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

Customizing this snippet

  • Color: set --hfx-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --hfx-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 hover effects