← Back to Writing
3 min read

Marching Ants Borders in Pure CSS


The "marching ants" effect — a dashed border whose dashes animate along the perimeter — looks like it requires SVG or canvas. It doesn't. Four CSS background-image gradients and one @keyframes rule are all you need.

How it works

CSS background-image accepts multiple values. Each gradient paints one side of the border:

Each gradient alternates between the border color and transparent at a fixed interval, creating a dashed pattern:

background-image:
  linear-gradient(90deg, #000 50%, transparent 0),  /* top */
  linear-gradient(90deg, #000 50%, transparent 0),  /* bottom */
  linear-gradient(180deg, #000 50%, transparent 0), /* left */
  linear-gradient(180deg, #000 50%, transparent 0); /* right */
background-size: 30px 1px, 30px 1px, 1px 30px, 1px 30px;
background-position: 0 0, 0 100%, 0 0, 100% 0;
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;

Animating the march

Shift the background-position by exactly one dash interval and the dashes appear to march:

@keyframes marchingAnts {
  to {
    background-position: 30px 0, -30px 100%, 0 -30px, 100% 30px;
  }
}

Note the directions: top moves right (+30px), bottom moves left (-30px), left moves up, right moves down. This makes the ants appear to travel clockwise around the perimeter.

Pause on idle, run on hover

animation: marchingAnts 0.4s linear infinite;
animation-play-state: paused;

&:hover {
  animation-play-state: running;
}

Dark mode

Because the gradient color is hardcoded in the CSS, it won't respond to a data-theme attribute. The fix is to use a CSS custom property instead of a literal color:

linear-gradient(90deg, var(--color-border) 50%, transparent 0)

Now the border color is controlled by the same token system as the rest of the design.