<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;"> </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;"> </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%);
}
}
}