Let’s start with our basic HTML structure.
<div>
<label for="username">Username</label>
<input type="text" name="username" id="username" placeholder="Your Name Here" />
</div>
It’s a basic form field, but it looks quite plain. Let’s transform it into something that belongs in a modern web application.
Adding Structure and Layout
First, let’s establish proper visual hierarchy by styling the label and adding some basic spacing.
<div>
<label for="username" class="block font-medium text-slate-900">Username</label>
<input type="text" name="username" id="username" placeholder="Your Name Here" />
</div>
block
: Makes the label take full width and sit above the inputfont-medium
: Adds medium font weight (500) for better hierarchytext-slate-900
: Near-black color for excellent readability
Creating Visual Separation
Now let’s add some breathing room between the label and input field.
<div class="space-y-2">
<label for="username" class="block font-medium text-slate-900">Username</label>
<input type="text" name="username" id="username" placeholder="Your Name Here" />
</div>
You could add a margin to one or both elements, but you can also use the spacing utilties as well.
Styling the Input Field
Time to make the input field look professional with proper dimensions, colors, and borders.
<div class="space-y-2">
<label for="username" class="block font-medium text-slate-900">Username</label>
<input
type="text"
name="username"
id="username"
class="block w-full rounded-md bg-white px-3 py-1.5 text-slate-900"
placeholder="Your Name Here"
/>
</div>
block
: Makes the input a block element for full controlw-full
: Input takes the full width of its containerrounded-md
: Adds 6px border radius for modern, friendly appearancebg-white
: Explicit white background (important for consistency)px-3
: 12px horizontal padding for comfortable text spacingpy-1.5
: 6px vertical padding for proper touch targetstext-slate-900
: Dark text color for high contrast
Adding Borders and Outlines
Now let’s add a proper border and focus states using Tailwind’s outline utilities.
<div class="space-y-2">
<label for="username" class="block font-medium text-slate-900">Username</label>
<input
type="text"
name="username"
id="username"
class="block w-full rounded-md bg-white px-3 py-1.5 text-slate-900 outline-1 -outline-offset-1 outline-slate-400"
placeholder="Your Name Here"
/>
</div>
outline-1
: 1px outline width (more reliable than borders for form fields)-outline-offset-1
: Negative offset puts the outline inside the elementoutline-slate-400
: Light-ish color for subtle, non-distracting border
Using outline
instead of border
prevents layout shifts and provides better consistency across browsers.
Adding Focus States
Let’s add an interactive focus state that provides clear visual feedback.
<div class="space-y-2">
<label for="username" class="block font-medium text-slate-900">Username</label>
<input
type="text"
name="username"
id="username"
class="block w-full rounded-md bg-white px-3 py-1.5 text-slate-900 outline-1 -outline-offset-1 outline-slate-300 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600"
placeholder="Your Name Here"
/>
</div>
focus:outline-2
: Thicker 2px outline when focusedfocus:-outline-offset-2
: Negative offset creates an inset ring effectfocus:outline-indigo-600
: Brand color (indigo) for focus state
The focus state uses a thicker outline with the same negative offset technique, creating a clear visual indicator without changing the input’s dimensions.
We’ll talk more about focus states in a hot minute.
Typography Refinements
Let’s improve the typography for both the label and input text, including placeholder styling.
<div class="space-y-2">
<label for="username" class="block text-sm font-medium text-slate-900">Username</label>
<input
type="text"
name="username"
id="username"
class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-slate-900 outline-1 -outline-offset-1 outline-slate-300 placeholder:text-slate-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600"
placeholder="Your Name Here"
/>
</div>
text-sm
on label: 14px font size, appropriate for form labelstext-base
on input: 16px font size prevents zoom on mobile devicesplaceholder:text-slate-400
: Lighter slate for placeholder text, creating clear hierarchy