Build a sign-up form users can actually complete

A sign-up form is often the first real interaction a user has with your product—and the last one if it’s frustrating. This codelab walks through building a secure, accessible, and usable sign-up form using nothing more than thoughtful HTML, a bit of CSS, and a small amount of JavaScript. You’ll end up with a form that leverages the capabilities browsers already ship with. A complete working example is available on CodePen.

Start with correct form semantics

Open a new CodePen and drop the following into the HTML editor:

<form action="#" method="post">
  <h1>Sign up</h1>

  <section>
    <label>Full name</label>
    <input>
  </section>

  <section>
    <label>Email</label>
    <input>
  </section>

  <section>
    <label>Password</label>
    <input>
  </section>

  <button id="sign-up">Sign up</button>
</form>

This creates a basic form with fields for the user’s full name, email, and a password. Every field lives inside its own section with an associated <label>. Because the submit action uses a <button> rather than an <input type="submit">, it can contain arbitrary HTML—an important trick you’ll rely on later.

Before changing anything, ask yourself three questions about the default styles:

  • Do the defaults look usable across viewport sizes and devices?
  • Do the defaults hold up for people using screen readers or other assistive technology?
  • Who are your actual users, and what browsers and hardware are they on?

You can answer those questions without setting up a full device lab. Chrome’s Device Mode simulates mobile viewports. You can also send a URL directly from desktop to your phone, or use a testing service like BrowserStack to cover a broader range of hardware. For accessibility, install the ChromeVox extension and attempt to complete the form using only the keyboard and screen reader output.

Layer in layout and focus CSS

The raw HTML is structurally sound, but visually it won’t hold up for a real user base. Paste the provided stylesheet into the CodePen CSS editor.

The stylesheet takes a mobile-first approach, using media queries to adjust layout at 400px and 500px. Pay attention to whether those breakpoints genuinely serve your design, or whether you need to tune the padding, margin, and font-size for the devices you intend to target. There is no sacred rule about which breakpoints to use—breakpoints should be driven by where the layout begins to strain.

Give the browser the data it needs

With styling in place, update the form HTML to the following:

<form action="#" method="post">

  <h1>Sign up</h1>

  <section>
    <label for="name">Full name</label>
    <input id="name" name="name" autocomplete="name"
    pattern="[\p{L}\.\- ]+" required>
  </section>

  <section>
    <label for="email">Email</label>
    <input id="email" name="email" autocomplete="username"
    type="email" required>
  </section>

  <section>
    <label for="password">Password</label>
    <input id="password" name="password" autocomplete="new-password"
    type="password" minlength="8" required>
  </section>

  <button id="sign-up">Sign up</button>
</form>

The payoff of proper type values and attributes is immediate and substantial:

  • type="password" obscures input and signals to the browser’s password manager that it should offer a strong, generated password.
  • type="email" triggers built-in format validation and surfaces the correct keyboard on mobile devices.

Additionally, each label uses a for attribute tied to the corresponding input’s id. This means clicking the label text moves focus to its field, and screen readers announce the label when either the label or the input receives focus. Try submitting the form leaving a field empty or using an under-eight-character password: the required and minlength="8" attributes prompt the browser to block submission, warn the user, and place focus on the offending field. The same applies to the pattern constraint on the name field and every browser-supported validation rule—zero custom JavaScript needed.

The autocomplete values fill in the last gaps. Use autocomplete="username" on the “Email” field: the password manager will associate that value with the user’s username for the site. On the password field, autocomplete="new-password" tells the manager this credential is for sign-up rather than returning a stored one. (In a sign-in form, that value becomes current-password.)

Adding helpful constraints

The password input has a hidden usability flaw: users must guess what constraints apply and have no way to verify what they typed. The following HTML adds a visibility toggle button (text-only for now), but more importantly adds attributes that make those constraints understandable for assistive tech:

<section>
  <label for="password">Password</label>
  <button id="toggle-password" type="button"
  aria-label="Show password as plain text. Warning: this displays your password on the screen.">
  Show password</button>
  <input id="password" name="password" type="password" minlength="8"
  autocomplete="new-password" aria-describedby="password-constraints" required>
  <div id="password-constraints">Eight or more characters.</div>
</section>

The supporting JavaScript—which wires up the toggle button—is available in a separate Pen and belongs in the JavaScript editor. Beyond that, note the aria-describedby attribute on the password input: screen readers announce the label, then the description text that explains the constraint, so the requirement isn’t opaque.

When adding such enhancements, test your assumptions with real users. The trade-off between an icon and text for the password toggle, for example, is not something punditry settles—run a discount usability test with friends or colleagues.

What this form doesn’t cover

This exercise leaves four production-critical areas unaddressed, all of which you should handle before shipping:

  • Checking submitted passwords against known breach logs via a password-checking service. Never silently accept a compromised credential.
  • Presenting links to your Terms of Service and privacy policy near the form and making clear how you use and protect user data.
  • Matching the form’s styling to the larger site so users recognize they’re still in the right place, especially during payment steps.
  • Instrumenting the form with analytics and Real User Monitoring to continuously gauge where users drop off or get stuck.