cssgridgen

CSS Input Generator

Text, textarea, number, OTP and search — with the browser quirks handled.

We will never share it.

text 17.72:1 · placeholder 2.56:1 — placeholder is too faint to read.

.field label {
  display: block;
  margin-bottom: 6px;
  font-size: 12px;
  font-weight: 500;
  color: #18181b;
}

.field input {
  width: 100%;
  padding: 9px 12px;
  font-size: 14px;
  font-family: inherit;
  line-height: 1.4;
  color: #18181b;
  background: #ffffff;
  border: 1px solid #d4d4d8;
  border-radius: 8px;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.field input::placeholder {
  color: #a1a1aa;
}

.field input:focus {
  outline: none;
  border-color: #2563eb;
  box-shadow: 0 0 0 3px rgb(37 99 235 / 0.25);
}

.field input[aria-invalid="true"] {
  border-color: #dc2626;
}

.field input:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.field .helper {
  margin-top: 6px;
  font-size: 11px;
  color: #a1a1aa;
}

.field .helper[data-error="true"] {
  color: #dc2626;
}
Free tool

Every field type has its own trap

Inputs look like the simplest thing to style and are not. Number fields draw spinner arrows that take three rules to remove, textareas default to monospace, Safari repaints search boxes, and OTP fields need specific attributes or the SMS autofill never appears. Each field type here brings its own fixes.

How to use it

  1. Pick a field type

    Text, textarea, number, OTP or search. Each one adds the browser quirks it actually needs — the number spinner reset, the Safari search reset, the OTP autocomplete attributes.

  2. Shape it

    Padding, font size, radius, border and focus ring width, with the preview updating to the exact values the CSS will contain.

  3. Check every state

    Default, focus, error and disabled. All four are written into the output whether you look at them or not.

  4. Watch the contrast

    Text and placeholder contrast are both checked live. Placeholder grey is the one that usually fails.

  5. Copy the code

    CSS with all the states, semantic HTML with the right input attributes, or the Tailwind class string.

Removing number spinners takes three rules

Two WebKit pseudo-elements handle Chrome, Safari and Edge: ::-webkit-outer-spin-button and ::-webkit-inner-spin-button, both needing -webkit-appearance: none and margin: 0. Firefox ignores those entirely and needs appearance: textfield on the input. Snippets that only include the WebKit half are why the arrows keep coming back.

Textareas inherit almost nothing

Browsers default a textarea to a monospace font at a smaller size than your body text, so font-family: inherit and an explicit font-size are not optional. Add field-sizing: content and the textarea grows as you type, which replaces the old scrollHeight JavaScript entirely.

Focus rings on inputs are not like buttons

A button should use :focus-visible so the ring only appears for keyboard users. A text field should not — remove the focus state on click and the field looks inert, with no indication of where typing will land. Use plain :focus here.

Placeholders are not labels

Placeholder text vanishes the moment someone types, taking the only description of the field with it, and the default grey usually fails contrast. Keep a real <label> and treat the placeholder as an example, not a name. The contrast reading above the preview checks it as you change colours.

Laying out the form

Field styling is one half; arranging them is the other. A two-column form with full-width fields for long values is a grid problem — build it in the grid generator and paste these field styles in.

Frequently asked questions

How do I remove the spinner arrows from a number input?
It takes three rules, not one: ::-webkit-outer-spin-button and ::-webkit-inner-spin-button with -webkit-appearance: none; margin: 0 for Chrome, Safari and Edge, plus appearance: textfield on the input itself for Firefox. Missing the Firefox line is why the arrows usually survive.
How do I style a textarea in CSS?
A textarea takes the same padding, border, radius and font properties as a text input, plus two of its own: resize to control the drag handle and min-height so it does not start as a single line. Set font-family: inherit — textareas default to monospace in most browsers, which is almost never what you want.
How do I make a textarea grow with its content?
Use field-sizing: content with a min-height. It replaces the old JavaScript trick of syncing scrollHeight on every keystroke. Support is good in Chromium and shipping elsewhere, and it degrades to a normal fixed-height textarea.
How do I build an OTP input with CSS?
A row of single-character inputs with maxlength="1", inputmode="numeric" and text-align: center. Put autocomplete="one-time-code" on the first one only, which is what lets iOS and Android offer the code from SMS. Each input needs its own aria-label since there is no visible label per box.
Should input focus use :focus or :focus-visible?
For text fields, :focus. :focus-visible is right for buttons — it hides the ring on mouse clicks — but a text input that shows no focus state when clicked looks broken and loses the one signal that tells you where typing will go.
What contrast does placeholder text need?
At least 3:1 against the field background, and it should never be the only label — placeholder text disappears the moment someone types. The default grey in most CSS resets fails this. The reading above the preview checks both the text and the placeholder as you change colours.
Why does my search input look wrong in Safari?
Safari applies its own appearance to type="search", including an inner shadow and a cancel button. Reset it with -webkit-appearance: none on the input and on ::-webkit-search-cancel-button.