About this snippet

A sign-up form with a name, an email address and a password. Each field turns red with a message when you leave it in a bad state, turns green with a check once it is right, and the submit button only lights up when the whole form is valid.

The rules are HTML attributes such as required, minlength, type email and a pattern on the password. The styling hangs off :user-invalid and :user-valid rather than :invalid. :invalid is true the moment the page loads, so every empty required field would start red. The user variants only match after the visitor has interacted with the field, so the form stays quiet until there is something to say. :has on the form lets the button react to the inputs above it.

Everything used here is Baseline. Submitting still runs the browser's own validation, so a field the visitor skipped entirely gets the native message on submit.

Size
3.0 KB
Uses
HTML, CSS
Loads
Nothing external
Views
33
<form class="signup">
  <h1>Create your account</h1>
  <div class="field">
    <label for="name">Full name</label>
    <input type="text" id="name" name="name" required minlength="2" autocomplete="name">
    <span class="hint">Enter at least two characters.</span>
  </div>
  <div class="field">
    <label for="email">Email</label>
    <input type="email" id="email" name="email" required autocomplete="email">
    <span class="hint">That does not look like an email address.</span>
  </div>
  <div class="field">
    <label for="password">Password</label>
    <input type="password" id="password" name="password" required minlength="8" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" autocomplete="new-password">
    <span class="hint">Use 8 or more characters with uppercase, lowercase and a number.</span>
  </div>
  <button type="submit">Create account</button>
</form>
*, *::before, *::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  margin: 0;
  background: #f1f5f9;
  color: #0f172a;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  padding: 20px;
}

.signup {
  width: 100%;
  max-width: 400px;
  background: #ffffff;
  padding: 36px;
  border-radius: 20px;
  box-shadow: 0 20px 40px -20px rgba(15, 23, 42, 0.25);
}

.signup h1 {
  font-size: 1.375rem;
  margin: 0 0 24px;
}

.field {
  position: relative;
  margin-bottom: 18px;
}

.field label {
  display: block;
  font-size: 0.875rem;
  font-weight: 600;
  margin-bottom: 6px;
}

.field input {
  width: 100%;
  font: inherit;
  padding: 11px 40px 11px 14px;
  border: 1.5px solid #cbd5e1;
  border-radius: 10px;
  outline: 0;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.field input:focus {
  border-color: #2563eb;
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.15);
}

.field::after {
  content: "";
  position: absolute;
  right: 14px;
  top: 37px;
  width: 8px;
  height: 14px;
  border-right: 2px solid #16a34a;
  border-bottom: 2px solid #16a34a;
  transform: rotate(45deg) scale(0);
  transition: transform 0.2s ease;
}

.field:has(input:user-valid)::after {
  transform: rotate(45deg) scale(1);
}

.field input:user-valid {
  border-color: #16a34a;
}

.field input:user-invalid {
  border-color: #dc2626;
}

.field input:user-invalid:focus {
  box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.15);
}

.hint {
  display: block;
  font-size: 0.8125rem;
  color: #dc2626;
  margin-top: 6px;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height 0.2s ease, opacity 0.2s ease;
}

.field input:user-invalid + .hint {
  max-height: 3em;
  opacity: 1;
}

.signup button {
  width: 100%;
  font: inherit;
  font-weight: 600;
  padding: 13px;
  border: 0;
  border-radius: 10px;
  background: #2563eb;
  color: #ffffff;
  cursor: pointer;
  margin-top: 6px;
  transition: background 0.15s ease, opacity 0.15s ease;
}

.signup button:hover {
  background: #1d4ed8;
}

.signup:has(input:invalid) button {
  opacity: 0.55;
}
Esc
↑↓ moveEnter select

Start from a template

Open an .html file, or HTML, CSS, JS, Markdown, Less or TypeScript files. You can also drop them here. Styles and scripts go into their panes.

Share

Source

Keyboard shortcuts

Save