28 CSS Input Fields09 / 28
Password Strength
Sign-up password input with a live strength bar that grades red → amber → green. Driven by `:has(input:valid/:invalid)` — zero scoring JavaScript.
Published
The code
<label class="if-09">
<span class="if-09-label">Password</span>
<input
type="password"
name="password"
autocomplete="new-password"
placeholder="At least 12 characters"
minlength="6"
required
/>
<span class="if-09-meter" aria-hidden="true"><span class="if-09-fill"></span></span>
<span class="if-09-hint">Use 12+ characters with letters, numbers, and a symbol.</span>
</label><label class="if-09">
<span class="if-09-label">Password</span>
<input
type="password"
name="password"
autocomplete="new-password"
placeholder="At least 12 characters"
minlength="6"
required
/>
<span class="if-09-meter" aria-hidden="true"><span class="if-09-fill"></span></span>
<span class="if-09-hint">Use 12+ characters with letters, numbers, and a symbol.</span>
</label>.if-09 {
display: grid;
gap: 6px;
width: 100%;
max-width: 280px;
font-size: 11px;
color: #b8b6d4;
}
.if-09-label {
font-weight: 600;
}
.if-09 input {
width: 100%;
box-sizing: border-box;
padding: 11px 14px;
background: #1a1a22;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
color: #f0eeff;
font-size: 14px;
outline: none;
transition: border-color 0.2s;
}
.if-09 input:focus {
border-color: #c084fc;
}
.if-09-meter {
position: relative;
height: 4px;
border-radius: 99px;
background: rgba(255, 255, 255, 0.08);
overflow: hidden;
}
.if-09-fill {
position: absolute;
inset: 0;
width: 0;
background: linear-gradient(90deg, #ef4444, #f59e0b, #22c55e);
border-radius: inherit;
transition: width 0.3s ease;
}
.if-09:has(input:placeholder-shown) .if-09-fill {
width: 0;
}
.if-09:has(input:not(:placeholder-shown):invalid) .if-09-fill {
width: 30%;
}
.if-09:has(input:not(:placeholder-shown):valid) .if-09-fill {
width: 65%;
}
.if-09:has(input:focus:valid) .if-09-fill {
width: 100%;
}
.if-09-hint {
font-size: 10.5px;
color: #b8b6d4;
}
.if-09 {
display: grid;
gap: 6px;
width: 100%;
max-width: 280px;
}
.if-09-label {
font-family: "JetBrains Mono", monospace;
font-size: 10px;
letter-spacing: 0.12em;
color: #b8b6d4;
text-transform: uppercase;
}
.if-09-wrap {
display: inline-flex;
align-items: center;
padding: 0 6px 0 14px;
background: #1a1a22;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 10px;
transition: border-color 0.2s;
}
.if-09-wrap:focus-within {
border-color: #7c6cff;
}
.if-09 input {
flex: 1;
min-width: 0;
padding: 12px 0;
border: 0;
outline: none;
background: transparent;
color: #f0eeff;
font: 500 14px/1 system-ui, sans-serif;
letter-spacing: 0.08em;
}
.if-09 input::placeholder {
color: #b8b6d4;
}
.if-09-toggle {
width: 32px;
height: 32px;
border: 0;
cursor: pointer;
background: transparent;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.15s;
}
.if-09-toggle:hover {
background: rgba(255, 255, 255, 0.05);
}
.if-09-toggle svg {
width: 16px;
height: 16px;
fill: none;
stroke: #b8b6d4;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
.if-09-eye-off {
display: none;
}
.if-09-toggle[aria-pressed="true"] .if-09-eye {
display: none;
}
.if-09-toggle[aria-pressed="true"] .if-09-eye-off {
display: block;
}
.if-09-toggle[aria-pressed="true"] svg {
stroke: #7c6cff;
}.if-09 {
display: grid;
gap: 6px;
width: 100%;
max-width: 280px;
font-size: 11px;
color: #b8b6d4;
}
.if-09-label {
font-weight: 600;
}
.if-09 input {
width: 100%;
box-sizing: border-box;
padding: 11px 14px;
background: #1a1a22;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
color: #f0eeff;
font-size: 14px;
outline: none;
transition: border-color 0.2s;
}
.if-09 input:focus {
border-color: #c084fc;
}
.if-09-meter {
position: relative;
height: 4px;
border-radius: 99px;
background: rgba(255, 255, 255, 0.08);
overflow: hidden;
}
.if-09-fill {
position: absolute;
inset: 0;
width: 0;
background: linear-gradient(90deg, #ef4444, #f59e0b, #22c55e);
border-radius: inherit;
transition: width 0.3s ease;
}
.if-09:has(input:placeholder-shown) .if-09-fill {
width: 0;
}
.if-09:has(input:not(:placeholder-shown):invalid) .if-09-fill {
width: 30%;
}
.if-09:has(input:not(:placeholder-shown):valid) .if-09-fill {
width: 65%;
}
.if-09:has(input:focus:valid) .if-09-fill {
width: 100%;
}
.if-09-hint {
font-size: 10.5px;
color: #b8b6d4;
}
.if-09 {
display: grid;
gap: 6px;
width: 100%;
max-width: 280px;
}
.if-09-label {
font-family: "JetBrains Mono", monospace;
font-size: 10px;
letter-spacing: 0.12em;
color: #b8b6d4;
text-transform: uppercase;
}
.if-09-wrap {
display: inline-flex;
align-items: center;
padding: 0 6px 0 14px;
background: #1a1a22;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 10px;
transition: border-color 0.2s;
}
.if-09-wrap:focus-within {
border-color: #7c6cff;
}
.if-09 input {
flex: 1;
min-width: 0;
padding: 12px 0;
border: 0;
outline: none;
background: transparent;
color: #f0eeff;
font: 500 14px/1 system-ui, sans-serif;
letter-spacing: 0.08em;
}
.if-09 input::placeholder {
color: #b8b6d4;
}
.if-09-toggle {
width: 32px;
height: 32px;
border: 0;
cursor: pointer;
background: transparent;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.15s;
}
.if-09-toggle:hover {
background: rgba(255, 255, 255, 0.05);
}
.if-09-toggle svg {
width: 16px;
height: 16px;
fill: none;
stroke: #b8b6d4;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
.if-09-eye-off {
display: none;
}
.if-09-toggle[aria-pressed="true"] .if-09-eye {
display: none;
}
.if-09-toggle[aria-pressed="true"] .if-09-eye-off {
display: block;
}
.if-09-toggle[aria-pressed="true"] svg {
stroke: #7c6cff;
}Here's a working CSS Input Field from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Password Strength
Source: https://codefronts.com/components/css-input-fields/password-strength/
Sign-up password input with a live strength bar that grades red → amber → green. Driven by `:has(input:valid/:invalid)` — zero scoring JavaScript.
## HTML
```html
<label class="if-09">
<span class="if-09-label">Password</span>
<input
type="password"
name="password"
autocomplete="new-password"
placeholder="At least 12 characters"
minlength="6"
required
/>
<span class="if-09-meter" aria-hidden="true"><span class="if-09-fill"></span></span>
<span class="if-09-hint">Use 12+ characters with letters, numbers, and a symbol.</span>
</label>
```
## CSS
```css
.if-09 {
display: grid;
gap: 6px;
width: 100%;
max-width: 280px;
font-size: 11px;
color: #b8b6d4;
}
.if-09-label {
font-weight: 600;
}
.if-09 input {
width: 100%;
box-sizing: border-box;
padding: 11px 14px;
background: #1a1a22;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
color: #f0eeff;
font-size: 14px;
outline: none;
transition: border-color 0.2s;
}
.if-09 input:focus {
border-color: #c084fc;
}
.if-09-meter {
position: relative;
height: 4px;
border-radius: 99px;
background: rgba(255, 255, 255, 0.08);
overflow: hidden;
}
.if-09-fill {
position: absolute;
inset: 0;
width: 0;
background: linear-gradient(90deg, #ef4444, #f59e0b, #22c55e);
border-radius: inherit;
transition: width 0.3s ease;
}
.if-09:has(input:placeholder-shown) .if-09-fill {
width: 0;
}
.if-09:has(input:not(:placeholder-shown):invalid) .if-09-fill {
width: 30%;
}
.if-09:has(input:not(:placeholder-shown):valid) .if-09-fill {
width: 65%;
}
.if-09:has(input:focus:valid) .if-09-fill {
width: 100%;
}
.if-09-hint {
font-size: 10.5px;
color: #b8b6d4;
}
.if-09 {
display: grid;
gap: 6px;
width: 100%;
max-width: 280px;
}
.if-09-label {
font-family: "JetBrains Mono", monospace;
font-size: 10px;
letter-spacing: 0.12em;
color: #b8b6d4;
text-transform: uppercase;
}
.if-09-wrap {
display: inline-flex;
align-items: center;
padding: 0 6px 0 14px;
background: #1a1a22;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 10px;
transition: border-color 0.2s;
}
.if-09-wrap:focus-within {
border-color: #7c6cff;
}
.if-09 input {
flex: 1;
min-width: 0;
padding: 12px 0;
border: 0;
outline: none;
background: transparent;
color: #f0eeff;
font: 500 14px/1 system-ui, sans-serif;
letter-spacing: 0.08em;
}
.if-09 input::placeholder {
color: #b8b6d4;
}
.if-09-toggle {
width: 32px;
height: 32px;
border: 0;
cursor: pointer;
background: transparent;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.15s;
}
.if-09-toggle:hover {
background: rgba(255, 255, 255, 0.05);
}
.if-09-toggle svg {
width: 16px;
height: 16px;
fill: none;
stroke: #b8b6d4;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
.if-09-eye-off {
display: none;
}
.if-09-toggle[aria-pressed="true"] .if-09-eye {
display: none;
}
.if-09-toggle[aria-pressed="true"] .if-09-eye-off {
display: block;
}
.if-09-toggle[aria-pressed="true"] svg {
stroke: #7c6cff;
}
```Here's a working CSS Input Field from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Password Strength
Source: https://codefronts.com/components/css-input-fields/password-strength/
Sign-up password input with a live strength bar that grades red → amber → green. Driven by `:has(input:valid/:invalid)` — zero scoring JavaScript.
## HTML
```html
<label class="if-09">
<span class="if-09-label">Password</span>
<input
type="password"
name="password"
autocomplete="new-password"
placeholder="At least 12 characters"
minlength="6"
required
/>
<span class="if-09-meter" aria-hidden="true"><span class="if-09-fill"></span></span>
<span class="if-09-hint">Use 12+ characters with letters, numbers, and a symbol.</span>
</label>
```
## CSS
```css
.if-09 {
display: grid;
gap: 6px;
width: 100%;
max-width: 280px;
font-size: 11px;
color: #b8b6d4;
}
.if-09-label {
font-weight: 600;
}
.if-09 input {
width: 100%;
box-sizing: border-box;
padding: 11px 14px;
background: #1a1a22;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
color: #f0eeff;
font-size: 14px;
outline: none;
transition: border-color 0.2s;
}
.if-09 input:focus {
border-color: #c084fc;
}
.if-09-meter {
position: relative;
height: 4px;
border-radius: 99px;
background: rgba(255, 255, 255, 0.08);
overflow: hidden;
}
.if-09-fill {
position: absolute;
inset: 0;
width: 0;
background: linear-gradient(90deg, #ef4444, #f59e0b, #22c55e);
border-radius: inherit;
transition: width 0.3s ease;
}
.if-09:has(input:placeholder-shown) .if-09-fill {
width: 0;
}
.if-09:has(input:not(:placeholder-shown):invalid) .if-09-fill {
width: 30%;
}
.if-09:has(input:not(:placeholder-shown):valid) .if-09-fill {
width: 65%;
}
.if-09:has(input:focus:valid) .if-09-fill {
width: 100%;
}
.if-09-hint {
font-size: 10.5px;
color: #b8b6d4;
}
.if-09 {
display: grid;
gap: 6px;
width: 100%;
max-width: 280px;
}
.if-09-label {
font-family: "JetBrains Mono", monospace;
font-size: 10px;
letter-spacing: 0.12em;
color: #b8b6d4;
text-transform: uppercase;
}
.if-09-wrap {
display: inline-flex;
align-items: center;
padding: 0 6px 0 14px;
background: #1a1a22;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 10px;
transition: border-color 0.2s;
}
.if-09-wrap:focus-within {
border-color: #7c6cff;
}
.if-09 input {
flex: 1;
min-width: 0;
padding: 12px 0;
border: 0;
outline: none;
background: transparent;
color: #f0eeff;
font: 500 14px/1 system-ui, sans-serif;
letter-spacing: 0.08em;
}
.if-09 input::placeholder {
color: #b8b6d4;
}
.if-09-toggle {
width: 32px;
height: 32px;
border: 0;
cursor: pointer;
background: transparent;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.15s;
}
.if-09-toggle:hover {
background: rgba(255, 255, 255, 0.05);
}
.if-09-toggle svg {
width: 16px;
height: 16px;
fill: none;
stroke: #b8b6d4;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
.if-09-eye-off {
display: none;
}
.if-09-toggle[aria-pressed="true"] .if-09-eye {
display: none;
}
.if-09-toggle[aria-pressed="true"] .if-09-eye-off {
display: block;
}
.if-09-toggle[aria-pressed="true"] svg {
stroke: #7c6cff;
}
```How this works
The strength bar is a single ::before-style span with an animated width. Four :has() rules on the label read the input's validation state: empty gives 0%, typed but :invalid (below minlength) gives 30%, :valid gives 65%, and :focus:valid pushes to 100%.
The gradient underneath spans red to amber to green horizontally, so as the bar widens it naturally reveals warmer then cooler tones — a CSS password strength meter without JS that reads as a live grade rather than a stepped bar. Add more pattern tests or wrap multiple inputs to tier further.
Make it yours
- Tighten grading by adding a stronger
pattern(e.g.(?=.*\d)(?=.*[!@#$])) so:validonly fires when the rule is met. - Recolour the gradient stops via
#ef4444 → #f59e0b → #22c55eon the fill background. - Tune band widths — 30/65/100% — to reflect your own scoring thresholds.
- Speed up or ease the reveal with the
width 0.3s easetransition on the fill.
Gotchas — read before shipping
- This grades on native constraints only — pattern length and character-class rules. It cannot detect dictionary matches or entropy the way zxcvbn does.
- The
placeholderattribute must be non-empty for the empty-state rule to fire via:placeholder-shown. :has()is the browser floor; older engines show a static empty bar, so pair with a semanticaria-describedbyhint for accessibility.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 105+ | 15.4+ | 121+ | 105+ |
Requires :has(); falls back to an unfilled meter with a fully working password field.