<form onSubmit="event.preventDefault();">
      <div class="form-group">
        <div class="form-group__content">
          <div class="form-group__shaker">
            <label for="first-name">
              <span aria-hidden="true" class="label__letter" style="--index: 0;">F</span>
              <span aria-hidden="true" class="label__letter" style="--index: 1;">i</span>
              <span aria-hidden="true" class="label__letter" style="--index: 2;">r</span>
              <span aria-hidden="true" class="label__letter" style="--index: 3;">s</span>
              <span aria-hidden="true" class="label__letter" style="--index: 4;">t</span>
              <span aria-hidden="true" class="label__letter" style="--index: 5;">&nbsp;</span>
              <span aria-hidden="true" class="label__letter" style="--index: 6;">N</span>
              <span aria-hidden="true" class="label__letter" style="--index: 7;">a</span>
              <span aria-hidden="true" class="label__letter" style="--index: 8;">m</span>
              <span aria-hidden="true" class="label__letter" style="--index: 9;">e</span>
              <span class="sr-only">First Name</span>
            </label>
            <div class="form-group__input">
              <input
                id="first-name"
                type="text"
                placeholder="first name"
                required
                pattern="[A-Za-z]{2,}"
              />
              <div class="form-group__error">Enter at least two characters</div>
            </div>
            <label class="ok button button--icon" for="proceed-first-name">
              OK.
              <svg viewBox="0 0 512 512" title="check-circle">
                <path
                  d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"
                />
              </svg>
            </label>
          </div>
        </div>
        <input
          class="proceed sr-only"
          id="proceed-first-name"
          type="checkbox"
          tabindex="-1"
        />
        <div class="form-group__controls">
          <label class="prev button button--icon">
            <span class="sr-only">Previous question</span>
            <svg viewBox="0 0 320 512" title="angle-up">
              <path
                d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
              />
            </svg>
          </label>
          <label class="next button button--icon" for="proceed-first-name">
            <span class="sr-only">Next question</span>
            <svg viewBox="0 0 320 512" title="angle-up">
              <path
                d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
              />
            </svg>
          </label>
        </div>
      </div>
      <div class="form-group">
        <div class="form-group__content">
          <div class="form-group__shaker">
            <label for="last-name">
              <span aria-hidden="true" class="label__letter" style="--index: 0;">L</span>
              <span aria-hidden="true" class="label__letter" style="--index: 1;">a</span>
              <span aria-hidden="true" class="label__letter" style="--index: 2;">s</span>
              <span aria-hidden="true" class="label__letter" style="--index: 3;">t</span>
              <span aria-hidden="true" class="label__letter" style="--index: 4;">&nbsp;</span>
              <span aria-hidden="true" class="label__letter" style="--index: 5;">N</span>
              <span aria-hidden="true" class="label__letter" style="--index: 6;">a</span>
              <span aria-hidden="true" class="label__letter" style="--index: 7;">m</span>
              <span aria-hidden="true" class="label__letter" style="--index: 8;">e</span>
              <span class="sr-only">Last Name</span>
            </label>
            <div class="form-group__input">
              <input
                id="last-name"
                type="text"
                placeholder="last name"
                required
                pattern="[A-Za-z]{2,}"
              />
              <div class="form-group__error">Enter at least two characters</div>
            </div>
            <label class="ok button button--icon" for="proceed-last-name">
              OK.
              <svg viewBox="0 0 512 512" title="check-circle">
                <path
                  d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"
                />
              </svg>
            </label>
          </div>
        </div>
        <input
          class="proceed sr-only"
          id="proceed-last-name"
          type="checkbox"
          tabindex="-1"
        />
        <div class="form-group__controls">
          <label class="prev button button--icon" for="proceed-first-name">
            <span class="sr-only">Previous question</span>
            <svg viewBox="0 0 320 512" title="angle-up">
              <path
                d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
              />
            </svg>
          </label>
          <label class="next button button--icon" for="proceed-last-name">
            <span class="sr-only">Next question</span>
            <svg viewBox="0 0 320 512" title="angle-up">
              <path
                d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
              />
            </svg>
          </label>
        </div>
      </div>
      <div class="form-group">
        <div class="form-group__content">
          <div class="form-group__shaker">
            <label for="email">
              <span aria-hidden="true" class="label__letter" style="--index: 0;">E</span>
              <span aria-hidden="true" class="label__letter" style="--index: 1;">m</span>
              <span aria-hidden="true" class="label__letter" style="--index: 2;">a</span>
              <span aria-hidden="true" class="label__letter" style="--index: 3;">i</span>
              <span aria-hidden="true" class="label__letter" style="--index: 4;">l</span>
              <span class="sr-only">Email</span>
            </label>
            <div class="form-group__input">
              <input
                type="email"
                required
                placeholder="email"
                pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"
              />
              <div class="form-group__error">Enter a valid email address</div>
            </div>
            <label class="ok button button--icon" for="proceed-email">
              OK.
              <svg viewBox="0 0 512 512" title="check-circle">
                <path
                  d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"
                />
              </svg>
            </label>
          </div>
        </div>
        <input
          class="proceed sr-only"
          id="proceed-email"
          type="checkbox"
          tabindex="-1"
        />
        <div class="form-group__controls">
          <label class="prev button button--icon" for="proceed-last-name">
            <span class="sr-only">Previous question</span>
            <svg viewBox="0 0 320 512" title="angle-up">
              <path
                d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
              />
            </svg>
          </label>
          <label class="next button button--icon" for="proceed-email">
            <span class="sr-only">Next question</span>
            <svg viewBox="0 0 320 512" title="angle-up">
              <path
                d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
              />
            </svg>
          </label>
        </div>
      </div>
      <div class="form-group">
        <div class="form-group__content">
          <button type="submit">Submit</button>
        </div>
        <div class="form-group__controls">
          <label class="prev button button--icon" for="proceed-email"
            ><span class="sr-only">Previous question</span>
            <svg viewBox="0 0 320 512" title="angle-up">
              <path
                d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
              />
            </svg>
          </label>
          <label class="next button button--icon"
            ><span class="sr-only">Next question</span>
            <svg viewBox="0 0 320 512" title="angle-up">
              <path
                d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"
              />
            </svg>
          </label>
        </div>
      </div>
      <button type="reset" class="button button--icon">
        <span class="sr-only">Reset Form</span>
        <svg viewBox="0 0 24 24" title="reset">
          <path
            fill="currentColor"
            d="M12,5V1L7,6L12,11V7A6,6 0 0,1 18,13A6,6 0 0,1 12,19A6,6 0 0,1 6,13H4A8,8 0 0,0 12,21A8,8 0 0,0 20,13A8,8 0 0,0 12,5Z"
          ></path>
        </svg>
      </button>
    </form>
:root {
  --red: hsl(18 100% 50%);
  --green: hsl(130 52% 46%);
  --yellow: hsl(44 83% 53%);
  --blue: hsl(215 100% 53%);
  --grey: hsl(0 0% 45%);
  --text: var(--gray-5);
  --transition: 0.5s;
  --valid: var(--green);
  --invalid: var(--red);
  --focus: var(--blue-4);
  --blur: var(--text-1);
  --disabled: var(--grey);
}

*,
*:after,
*:before {
	box-sizing: border-box;
}

body {
	display: grid;
	place-items: center;
	min-height: 100vh;
	font-family:  'Google Sans', sans-serif, system-ui;
}

form {
  margin: var(--size-2);
	width: var(--size-content-3);
	max-width: 90vmin;
  min-width: 375px;
	aspect-ratio: 1;
	background: var(--surface-2);
	position: relative;
	margin: 0;
	padding: 0;
	border-radius: var(--radius-4);
	overflow: hidden;
}

input {
  border: 4px solid var(--color);
  border-radius: 4px;
  padding: 1rem 2rem;
  font-weight: 400;
  transition-property: border-color, outline-color;
  transition-duration: var(--transition);
  transition-timing-function: var(--ease-elastic-2);
}

input:focus-visible {
  outline-color: var(--color);
}

input::placeholder {
  color: transparent;
}

.form-group {
	padding: var(--size-fluid-2);
  position: absolute;
  display: grid;
  place-items: center;
  inset: 0;
  z-index: var(--show, 0);
}

.form-group__content {
	height: 100%;
	width: 90%;
	display: flex;
  flex-wrap: wrap;
  gap: var(--size-4);
  align-items: center;
  justify-content: center;
  align-content: center;
  opacity: var(--show, 0);
  opacity: 1;
  transition-property: transform, opacity;
  transition-duration: var(--transition);
  transition-timing-function: var(--ease-elastic-2);
  transform: translateY(calc(var(--offset, 1) * 100%)) scale(var(--show, 0));
  /*transform: translateY(calc(var(--offset, 1) * 100%)) scale(1);*/
}

.form-group__shaker {
	height: 100%;
	width: 100%;
	display: flex;
	flex-wrap: wrap;
	gap: var(--size-4);
	align-items: center;
	justify-content: center;
  align-content: center;
}

.form-group__controls {
	display: flex;
	position: absolute;
	gap: var(--size-2);
	bottom: var(--size-fluid-2);
	right: calc(48px + (var(--size-2) + var(--size-fluid-2)));
	opacity: var(--show, 0);
}

[type="reset"] {
	position: absolute;
	right: var(--size-fluid-2);
	bottom: var(--size-fluid-2);
	z-index: 3;
}

.form-group .form-group__input {
	flex: 1;
}

.sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border-width: 0;
}

.button {
	background: hsl(0 0% 5%);
	padding: 0;
}

.button:hover {
	background: hsl(0 0% 10%);
}

.button--icon svg {
	height: 60%;
	aspect-ratio: 1;
	fill: currentColor;
}

.button--icon {
	color: var(--gray-0);
	width: 48px;
	aspect-ratio: 1;
	display: grid;
	place-items: center;
}

.ok {
	height: 48px;
	display: flex;
	padding: var(--size-2);
	width: 80px;
	align-items: center;
	justify-content: center;
}

.ok svg {
	width: calc(48px * 0.6);
}

.next {
	transform: rotate(180deg);
}

label {
  font-family: sans-serif;
  display: flex;
  font-weight: bold;
  transform-style: preserve-3d;
  transition-property: color, opacity;
  transition-duration: var(--transition);
  color: var(--color);
  font-size: 1.25rem;
  white-space: nowrap;
  text-align: center;
}

.form-group__input {
	position: relative;
}

.form-group__input input {
	width: 100%;
}

.form-group__error {
	display: none;
	white-space: nowrap;
	position: absolute;
	top: calc(var(--size-2) + 100%);
	left: 50%;
	color: var(--red);
	transform: translate(-50%, 0) scale(1);
	font-size: var(--font-size-0);
}


.form-group:has(:invalid:not([type="checkbox"])) {
	--color: var(--invalid);
}

.form-group:has(:focus:not([type="checkbox"])) {
  --color: var(--focus);
}

.form-group:has(:placeholder-shown:not([type="checkbox"])) {
  --color: var(--blur);
}

.form-group:has(:valid:not([type="checkbox"])) {
	--color: var(--valid);
}

.form-group:has(:valid:not([type="checkbox"])) :is([for], .ok) {
	pointer-events: all;
	opacity: 1;
}

:is(.form-group:first-of-type) {
  --show: 1;
  --offset: 0;
}

:is(.form-group:has(.proceed:checked), .form-group:first-of-type:has(.proceed:checked)) {
  --show: 0;
  --offset: -1;
}


:is(.form-group:has(:checked):focus-within + .form-group:not(.form-group:has(:checked))) {
  --show: 1;
  --offset: 0;
}

form:not(:focus-within) .form-group:has(:checked) + .form-group:not(.form-group:has(:checked)) {
	--show: 1;
	--offset: 0;
}

.form-group:has( ~ .form-group:focus-within) {
	--show: 0;
	--offset: -1;
}

.form-group:has(:focus-within) {
	--show: 1;
	--offset: 0;
}

.ok, .next, label:not([for]) {
	opacity: 0.25;
	pointer-events: none;
}

[type="submit"] {
	background-color: var(--valid);
	font-family: 'Google Sans', sans-serif, system-ui;
	font-weight: bold;
	font-size: var(--font-size-fluid-1);
	border-radius: var(--radius-2);
	padding: var(--size-2) var(--size-4);
  color: var(--gray-0);
}

[type="submit"]:hover {
	background: var(--green-8);
}

.form-group:has(:invalid:not(:focus):not(:placeholder-shown)) .form-group__error {
  display: block;
}


@media(prefers-reduced-motion: no-preference) {
	
	.form-group__content:has(:valid:not([type="checkbox"])) .label__letter {
	  animation: wave 0.25s calc(var(--index) * 0.05s);
	}
	
	.form-group__shaker:has(:invalid:not(:focus)) {
		animation: shake 0.2s;
	}

	.form-group__shaker:has(:focus),
	.form-group__shaker:has(:placeholder-shown:not(:focus)),
	.form-group__content:has(:placeholder-shown:not(:focus)),
	.form-group__content:has(:placeholder-shown:not(:focus)) .label__letter {
	  animation: none;
	}

	.form-group__error {
		animation: show-error 0.1s 0.2s both;
	}

	@keyframes wave {
	  50% {
	    transform: translateY(-50%);
	  }
	}

	@keyframes show-error {
		0% {
			transform: translate(-50%, -100%) scale(0);
		}
	}

	@keyframes shake {
	  0%, 100% {
	    transform: translateX(0);
	  } 
	  20%, 40%, 60%, 80% {
	    transform: translateX(-2%);
	  }
	  10%, 30%, 50%, 70%, 90% {
	    transform: translateX(2%);
	  }
	}

}

External CSS

  1. https://codepen.io/jh3y/pen/zYRjgjW.css
  2. https://unpkg.com/open-props/colors-hsl.min.css
  3. https://unpkg.com/open-props/open-props.min.css
  4. https://unpkg.com/open-props/normalize.min.css

External JavaScript

  1. https://codepen.io/jh3y/pen/zYRjgjW.js