App UI

Sign-In Card

A sign-in card that assembles downward, with fields that answer to focus.

5
Elements
2
Groups
3
Hover states
1160ms
Duration

Why it is timed this way

The reasoning

The focus states are the useful part. They compile to a transition on a :focus rule, so keyboard users get the same ring as mouse users — which is the whole point, and the thing most hand-written form CSS forgets.

5 elements move, the first at 0ms and the last starting at 260ms — the whole scene settles by 1160ms. Every bar below is one element's animation window.

Form Title
Form Sub
Email Field
Password Field
Sign In
0ms580ms1160ms

The code

Everything the scene needs, in whichever format you ship. Entrances compile to@keyframesand hover states totransition, with a reduced-motion guard on both.

201 lines
.sign-in {
  transform: translate3d(0px, 0px, 0);
  width: 960px;
  height: 480px;
  transform-origin: 480px 185px;
}

.form-card {
  transform: translate3d(0px, 0px, 0);
  box-shadow: 0px 16px 44px 0px #00000066;
  width: 288px;
  height: 250px;
  background: #171a24;
  border-radius: 18px;
  transform-origin: 180px 161px;
}

.form-title {
  transform: translate3d(0px, 0px, 0);
  width: 288px;
  height: 32px;
  background: #00000000;
  color: #eceef4;
  font-size: 24px;
  font-weight: 700;
  animation: form-title-anim 1160ms linear 0ms infinite both;
  will-change: transform, opacity;
}

@keyframes form-title-anim {
  0% {
    transform: translate3d(0px, 48px, 0);
    opacity: 0;
    animation-timing-function: ease-out;
  }
  60.34% {
    transform: translate3d(0px, 0px, 0);
    opacity: 1;
  }
  100% {
    transform: translate3d(0px, 0px, 0);
    opacity: 1;
  }
}

.form-sub {
  transform: translate3d(0px, 0px, 0);
  width: 288px;
  height: 20px;
  background: #00000000;
  color: #98a1b5;
  font-size: 14px;
  font-weight: 500;
  animation: form-sub-anim 1160ms linear 0ms infinite both;
  will-change: transform, opacity;
}

@keyframes form-sub-anim {
  0% {
    transform: translate3d(0px, 48px, 0);
    opacity: 0;
  }
  5.6% {
    transform: translate3d(0px, 48px, 0);
    opacity: 0;
    animation-timing-function: ease-out;
  }
  65.95% {
    transform: translate3d(0px, 0px, 0);
    opacity: 1;
  }
  100% {
    transform: translate3d(0px, 0px, 0);
    opacity: 1;
  }
}

.email-field {
  transform: translate3d(0px, 0px, 0);
  width: 288px;
  height: 46px;
  background: #1f2331;
  border-radius: 10px;
  transition: box-shadow 200ms ease-out, background 200ms ease-out;
  animation: email-field-anim 1160ms linear 0ms infinite both;
  will-change: transform, opacity;
}

.email-field:focus-visible {
  box-shadow: 0px 0px 0px 3px #6366f166;
  background: #272c3a;
  transition: box-shadow 150ms ease-out, background 150ms ease-out;
}

@keyframes email-field-anim {
  0% {
    transform: translate3d(0px, 48px, 0);
    opacity: 0;
  }
  11.21% {
    transform: translate3d(0px, 48px, 0);
    opacity: 0;
    animation-timing-function: ease-out;
  }
  71.55% {
    transform: translate3d(0px, 0px, 0);
    opacity: 1;
  }
  100% {
    transform: translate3d(0px, 0px, 0);
    opacity: 1;
  }
}

.password-field {
  transform: translate3d(0px, 0px, 0);
  width: 288px;
  height: 46px;
  background: #1f2331;
  border-radius: 10px;
  transition: box-shadow 200ms ease-out, background 200ms ease-out;
  animation: password-field-anim 1160ms linear 0ms infinite both;
  will-change: transform, opacity;
}

.password-field:focus-visible {
  box-shadow: 0px 0px 0px 3px #6366f166;
  background: #272c3a;
  transition: box-shadow 150ms ease-out, background 150ms ease-out;
}

@keyframes password-field-anim {
  0% {
    transform: translate3d(0px, 48px, 0);
    opacity: 0;
  }
  16.81% {
    transform: translate3d(0px, 48px, 0);
    opacity: 0;
    animation-timing-function: ease-out;
  }
  77.16% {
    transform: translate3d(0px, 0px, 0);
    opacity: 1;
  }
  100% {
    transform: translate3d(0px, 0px, 0);
    opacity: 1;
  }
}

.sign-in-2 {
  transform: translate3d(0px, 0px, 0);
  width: 288px;
  height: 42px;
  background: #6366f1;
  border-radius: 10px;
  color: #ffffff;
  font-size: 14px;
  font-weight: 600;
  transition: transform 200ms ease-out, background 200ms ease-out;
  animation: sign-in-2-anim 1160ms linear 0ms infinite both;
  will-change: transform, opacity;
}

.sign-in-2:hover {
  transform: translate3d(36px, 242px, 0);
  background: #8b7bff;
  transition: transform 180ms ease-out, background 180ms ease-out;
}

@keyframes sign-in-2-anim {
  0% {
    transform: translate3d(0px, 48px, 0);
    opacity: 0;
  }
  22.41% {
    transform: translate3d(0px, 48px, 0);
    opacity: 0;
    animation-timing-function: ease-out;
  }
  82.76% {
    transform: translate3d(0px, 0px, 0);
    opacity: 1;
  }
  100% {
    transform: translate3d(0px, 0px, 0);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .form-title,
  .form-sub,
  .email-field,
  .password-field,
  .sign-in-2 {
    animation: none;
    transition: none;
  }
}

More scenes

Your day

Onboarding Screen

A phone frame that pops in, then fills with list rows.

Now in beta
Ship motion
that feels right.
Design it, tune it, export the CSS.

Launch Hero

A product hero whose copy, buttons and panel arrive in sequence.

Starter
$0
Pro
$12
Team
$40

Three-Plan Pricing

Three plans that pop in, with the featured column raised and hover lifts on every card.