21 CSS Tooltips21 / 21
Form Field Help
Compact help circles sit next to form labels and reveal a one-line hint on hover — username rules, email visibility, time-zone purpose. The tooltip pops to the right with a side-arrow tail so the form line stays uninterrupted. For settings panels, sign-up forms, and profile editors.
Published
The code
<div class="tp-21">
<div class="tp-21__form">
<div class="tp-21__field">
<div class="tp-21__label">
Username
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Letters, numbers, and underscores only. 3–20 characters.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="kalani_a" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Email address
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Used for login and account recovery. Never shown publicly.</span>
</span>
</div>
<input class="tp-21__input" type="email" value="kalani@example.com" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Website
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Include https:// — displayed on your public profile page.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="https://kalani.dev" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Bio
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Shown below your name on your profile. Max 160 characters.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="Building things on the web. Based in Honolulu." readonly>
</div>
<div class="tp-21__field tp-21__field-last">
<div class="tp-21__label">
Time zone
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Used to display timestamps and schedule notifications correctly.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="Pacific/Honolulu (UTC −10:00)" readonly>
</div>
</div>
</div><div class="tp-21">
<div class="tp-21__form">
<div class="tp-21__field">
<div class="tp-21__label">
Username
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Letters, numbers, and underscores only. 3–20 characters.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="kalani_a" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Email address
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Used for login and account recovery. Never shown publicly.</span>
</span>
</div>
<input class="tp-21__input" type="email" value="kalani@example.com" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Website
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Include https:// — displayed on your public profile page.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="https://kalani.dev" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Bio
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Shown below your name on your profile. Max 160 characters.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="Building things on the web. Based in Honolulu." readonly>
</div>
<div class="tp-21__field tp-21__field-last">
<div class="tp-21__label">
Time zone
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Used to display timestamps and schedule notifications correctly.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="Pacific/Honolulu (UTC −10:00)" readonly>
</div>
</div>
</div>.tp-21 {
width: 100%;
min-height: 100vh;
background: #fff;
/* Right room — help tooltips pop to the RIGHT of each ? icon,
~280px wide single-line pills. Padding the right side gives them
room to extend without getting clipped by the gallery card. */
padding: 40px 320px 40px 28px;
font-family: system-ui, -apple-system, sans-serif;
}
.tp-21__form {
max-width: 400px;
margin: 0 auto;
}
.tp-21__field {
margin-bottom: 18px;
}
.tp-21__field-last {
margin-bottom: 0;
}
.tp-21__label {
display: flex;
align-items: center;
gap: 5px;
font-size: 12.5px;
font-weight: 500;
color: #111;
margin-bottom: 6px;
}
.tp-21__t {
position: relative;
display: inline-flex;
align-items: center;
}
.tp-21__icon {
width: 15px;
height: 15px;
border-radius: 50%;
background: #e5e7eb;
color: #9ca3af;
font-size: 9px;
font-weight: 700;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: help;
transition: background .12s, color .12s;
flex-shrink: 0;
line-height: 1;
}
.tp-21__t:hover .tp-21__icon {
background: #d1d5db;
color: #374151;
}
.tp-21__tip {
position: absolute;
top: 50%;
left: calc(100% + 8px);
transform: translateY(-50%) translateX(4px);
background: #18181b;
color: #fff;
font-size: 11.5px;
padding: 7px 11px;
border-radius: 5px;
width: 240px;
pointer-events: none;
opacity: 0;
visibility: hidden;
transition: opacity .14s, transform .14s cubic-bezier(0.22, 1, 0.36, 1), visibility 0s linear .14s;
z-index: 100;
line-height: 1.4;
display: block;
}
.tp-21__t:hover .tp-21__tip {
opacity: 1;
visibility: visible;
transform: translateY(-50%) translateX(0);
transition-delay: 0s;
}
.tp-21__tip::after {
content: '';
position: absolute;
top: 50%;
right: 100%;
transform: translateY(-50%);
border: 4px solid transparent;
border-right-color: #18181b;
}
.tp-21__input {
width: 100%;
padding: 8px 11px;
border: 1px solid #e5e7eb;
border-radius: 6px;
font-size: 12.5px;
color: #374151;
background: #fafafa;
outline: none;
font-family: inherit;
}
.tp-21__input:focus {
border-color: #6366f1;
background: #fff;
}.tp-21 {
width: 100%;
min-height: 100vh;
background: #fff;
/* Right room — help tooltips pop to the RIGHT of each ? icon,
~280px wide single-line pills. Padding the right side gives them
room to extend without getting clipped by the gallery card. */
padding: 40px 320px 40px 28px;
font-family: system-ui, -apple-system, sans-serif;
}
.tp-21__form {
max-width: 400px;
margin: 0 auto;
}
.tp-21__field {
margin-bottom: 18px;
}
.tp-21__field-last {
margin-bottom: 0;
}
.tp-21__label {
display: flex;
align-items: center;
gap: 5px;
font-size: 12.5px;
font-weight: 500;
color: #111;
margin-bottom: 6px;
}
.tp-21__t {
position: relative;
display: inline-flex;
align-items: center;
}
.tp-21__icon {
width: 15px;
height: 15px;
border-radius: 50%;
background: #e5e7eb;
color: #9ca3af;
font-size: 9px;
font-weight: 700;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: help;
transition: background .12s, color .12s;
flex-shrink: 0;
line-height: 1;
}
.tp-21__t:hover .tp-21__icon {
background: #d1d5db;
color: #374151;
}
.tp-21__tip {
position: absolute;
top: 50%;
left: calc(100% + 8px);
transform: translateY(-50%) translateX(4px);
background: #18181b;
color: #fff;
font-size: 11.5px;
padding: 7px 11px;
border-radius: 5px;
width: 240px;
pointer-events: none;
opacity: 0;
visibility: hidden;
transition: opacity .14s, transform .14s cubic-bezier(0.22, 1, 0.36, 1), visibility 0s linear .14s;
z-index: 100;
line-height: 1.4;
display: block;
}
.tp-21__t:hover .tp-21__tip {
opacity: 1;
visibility: visible;
transform: translateY(-50%) translateX(0);
transition-delay: 0s;
}
.tp-21__tip::after {
content: '';
position: absolute;
top: 50%;
right: 100%;
transform: translateY(-50%);
border: 4px solid transparent;
border-right-color: #18181b;
}
.tp-21__input {
width: 100%;
padding: 8px 11px;
border: 1px solid #e5e7eb;
border-radius: 6px;
font-size: 12.5px;
color: #374151;
background: #fafafa;
outline: none;
font-family: inherit;
}
.tp-21__input:focus {
border-color: #6366f1;
background: #fff;
}Here's a working CSS Tooltip 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: Form Field Help
Source: https://codefronts.com/snippets/css-tooltips/form-field-help/
Compact help circles sit next to form labels and reveal a one-line hint on hover — username rules, email visibility, time-zone purpose. The tooltip pops to the right with a side-arrow tail so the form line stays uninterrupted. For settings panels, sign-up forms, and profile editors.
## HTML
```html
<div class="tp-21">
<div class="tp-21__form">
<div class="tp-21__field">
<div class="tp-21__label">
Username
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Letters, numbers, and underscores only. 3–20 characters.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="kalani_a" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Email address
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Used for login and account recovery. Never shown publicly.</span>
</span>
</div>
<input class="tp-21__input" type="email" value="kalani@example.com" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Website
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Include https:// — displayed on your public profile page.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="https://kalani.dev" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Bio
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Shown below your name on your profile. Max 160 characters.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="Building things on the web. Based in Honolulu." readonly>
</div>
<div class="tp-21__field tp-21__field-last">
<div class="tp-21__label">
Time zone
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Used to display timestamps and schedule notifications correctly.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="Pacific/Honolulu (UTC −10:00)" readonly>
</div>
</div>
</div>
```
## CSS
```css
.tp-21 {
width: 100%;
min-height: 100vh;
background: #fff;
/* Right room — help tooltips pop to the RIGHT of each ? icon,
~280px wide single-line pills. Padding the right side gives them
room to extend without getting clipped by the gallery card. */
padding: 40px 320px 40px 28px;
font-family: system-ui, -apple-system, sans-serif;
}
.tp-21__form {
max-width: 400px;
margin: 0 auto;
}
.tp-21__field {
margin-bottom: 18px;
}
.tp-21__field-last {
margin-bottom: 0;
}
.tp-21__label {
display: flex;
align-items: center;
gap: 5px;
font-size: 12.5px;
font-weight: 500;
color: #111;
margin-bottom: 6px;
}
.tp-21__t {
position: relative;
display: inline-flex;
align-items: center;
}
.tp-21__icon {
width: 15px;
height: 15px;
border-radius: 50%;
background: #e5e7eb;
color: #9ca3af;
font-size: 9px;
font-weight: 700;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: help;
transition: background .12s, color .12s;
flex-shrink: 0;
line-height: 1;
}
.tp-21__t:hover .tp-21__icon {
background: #d1d5db;
color: #374151;
}
.tp-21__tip {
position: absolute;
top: 50%;
left: calc(100% + 8px);
transform: translateY(-50%) translateX(4px);
background: #18181b;
color: #fff;
font-size: 11.5px;
padding: 7px 11px;
border-radius: 5px;
width: 240px;
pointer-events: none;
opacity: 0;
visibility: hidden;
transition: opacity .14s, transform .14s cubic-bezier(0.22, 1, 0.36, 1), visibility 0s linear .14s;
z-index: 100;
line-height: 1.4;
display: block;
}
.tp-21__t:hover .tp-21__tip {
opacity: 1;
visibility: visible;
transform: translateY(-50%) translateX(0);
transition-delay: 0s;
}
.tp-21__tip::after {
content: '';
position: absolute;
top: 50%;
right: 100%;
transform: translateY(-50%);
border: 4px solid transparent;
border-right-color: #18181b;
}
.tp-21__input {
width: 100%;
padding: 8px 11px;
border: 1px solid #e5e7eb;
border-radius: 6px;
font-size: 12.5px;
color: #374151;
background: #fafafa;
outline: none;
font-family: inherit;
}
.tp-21__input:focus {
border-color: #6366f1;
background: #fff;
}
```Here's a working CSS Tooltip 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: Form Field Help
Source: https://codefronts.com/snippets/css-tooltips/form-field-help/
Compact help circles sit next to form labels and reveal a one-line hint on hover — username rules, email visibility, time-zone purpose. The tooltip pops to the right with a side-arrow tail so the form line stays uninterrupted. For settings panels, sign-up forms, and profile editors.
## HTML
```html
<div class="tp-21">
<div class="tp-21__form">
<div class="tp-21__field">
<div class="tp-21__label">
Username
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Letters, numbers, and underscores only. 3–20 characters.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="kalani_a" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Email address
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Used for login and account recovery. Never shown publicly.</span>
</span>
</div>
<input class="tp-21__input" type="email" value="kalani@example.com" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Website
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Include https:// — displayed on your public profile page.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="https://kalani.dev" readonly>
</div>
<div class="tp-21__field">
<div class="tp-21__label">
Bio
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Shown below your name on your profile. Max 160 characters.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="Building things on the web. Based in Honolulu." readonly>
</div>
<div class="tp-21__field tp-21__field-last">
<div class="tp-21__label">
Time zone
<span class="tp-21__t">
<span class="tp-21__icon">?</span>
<span class="tp-21__tip">Used to display timestamps and schedule notifications correctly.</span>
</span>
</div>
<input class="tp-21__input" type="text" value="Pacific/Honolulu (UTC −10:00)" readonly>
</div>
</div>
</div>
```
## CSS
```css
.tp-21 {
width: 100%;
min-height: 100vh;
background: #fff;
/* Right room — help tooltips pop to the RIGHT of each ? icon,
~280px wide single-line pills. Padding the right side gives them
room to extend without getting clipped by the gallery card. */
padding: 40px 320px 40px 28px;
font-family: system-ui, -apple-system, sans-serif;
}
.tp-21__form {
max-width: 400px;
margin: 0 auto;
}
.tp-21__field {
margin-bottom: 18px;
}
.tp-21__field-last {
margin-bottom: 0;
}
.tp-21__label {
display: flex;
align-items: center;
gap: 5px;
font-size: 12.5px;
font-weight: 500;
color: #111;
margin-bottom: 6px;
}
.tp-21__t {
position: relative;
display: inline-flex;
align-items: center;
}
.tp-21__icon {
width: 15px;
height: 15px;
border-radius: 50%;
background: #e5e7eb;
color: #9ca3af;
font-size: 9px;
font-weight: 700;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: help;
transition: background .12s, color .12s;
flex-shrink: 0;
line-height: 1;
}
.tp-21__t:hover .tp-21__icon {
background: #d1d5db;
color: #374151;
}
.tp-21__tip {
position: absolute;
top: 50%;
left: calc(100% + 8px);
transform: translateY(-50%) translateX(4px);
background: #18181b;
color: #fff;
font-size: 11.5px;
padding: 7px 11px;
border-radius: 5px;
width: 240px;
pointer-events: none;
opacity: 0;
visibility: hidden;
transition: opacity .14s, transform .14s cubic-bezier(0.22, 1, 0.36, 1), visibility 0s linear .14s;
z-index: 100;
line-height: 1.4;
display: block;
}
.tp-21__t:hover .tp-21__tip {
opacity: 1;
visibility: visible;
transform: translateY(-50%) translateX(0);
transition-delay: 0s;
}
.tp-21__tip::after {
content: '';
position: absolute;
top: 50%;
right: 100%;
transform: translateY(-50%);
border: 4px solid transparent;
border-right-color: #18181b;
}
.tp-21__input {
width: 100%;
padding: 8px 11px;
border: 1px solid #e5e7eb;
border-radius: 6px;
font-size: 12.5px;
color: #374151;
background: #fafafa;
outline: none;
font-family: inherit;
}
.tp-21__input:focus {
border-color: #6366f1;
background: #fff;
}
```How this works
The tp-21 component is the Stripe-checkout/Typeform inline help idiom. Structurally, each row is a tp-21__field that stacks a tp-21__label above a tp-21__input. The label is a flex row that keeps text and the question-mark icon on the same baseline via display: flex; align-items: center; gap: 5px, so the icon never disturbs the field spacing when tooltips are hidden. The icon lives inside tp-21__t, a relatively positioned inline-flex wrapper that anchors the sideways-popping tp-21__tip pill.
The trigger is tp-21__icon, a 15x15 grey circle rendered with border-radius: 50%, #e5e7eb background, and a 9px bold question-mark glyph. On hover, the background steps to #d1d5db and the glyph darkens to #374151 — a Tailwind-neutral hover recipe that reads clearly without breaking the form's colour system. Because the icon sits inline with the label text and shares its baseline, the field label stays visually stable whether the user hovers the icon or not.
The tooltip pops to the right instead of above, which is the correct anchor for a form line: an upward-popping tip would collide with the previous field's input. Positioning is top: 50% with left: calc(100% + 8px), plus translateY(-50%) for vertical centring and a 4px translateX slide-in. The pill is a 240px dark #18181b panel with 11.5px white body copy at 1.4 line-height, and a ::after triangle rendered by border-right-color pointing left toward the icon. Enter animation is 140ms and matches the toolbar; delayed visibility keeps the pill alive during exit.
Make it yours
- Recolour the trigger by editing
tp-21__icon's background and text tokens plus the:hoverpair. The Tailwind neutrals slot into any brand system; keep the 15px diameter so the glyph stays legible at 9px. - Anchor the tip above the field for narrow containers by swapping
top: 50%; left: calc(100% + 8px)forbottom: calc(100% + 8px); left: 50%and updating the::afterarrow to point down. - Widen the tip for longer prose by increasing the fixed
width: 240pxontp-21__tip. The pill wraps naturally becausewhite-spaceis not locked to nowrap, unlike the toolbar variant. - Add an error-state variant by introducing
tp-21__icon--error(red bg + white glyph) andtp-21__tip--error(red bg with matching arrow tint). Reuse the existing positioning so the error tip lands in the same spot as the help tip. - Swap the question-mark for an info glyph or an SVG info icon by replacing the icon child. Keep the flex-centring on
tp-21__iconand the 9px font-size baseline so the glyph optical-centres inside the circle.
Gotchas — read before shipping
- The container reserves 320px of right padding for exactly the rightward-popping tips. Removing that padding when embedding the component inside a narrower shell will clip every tip against the frame edge; either preserve the padding or add a
tp-21__tip--abovevariant for narrow contexts. - The tip is triggered on hover of
tp-21__t, not the icon alone. That is intentional so the pill stays open while the pointer traverses the 8px gap. Verify your click-tracking analytics do not treat the wrapper as a separate target — it will double-count icon hovers. - Question-mark triggers with hover-only reveal violate SC 2.1.1 Keyboard for form users. Add
tabindex="0"to eachtp-21__tand mirror the:hoverselectors with:focus-visible. Combine with anaria-describedbythat points from the input to the tip's ID for screen-reader parity. - The pill uses
pointer-events: none, which prevents users from selecting the hint text. That is fine for a short format hint ("Max 160 characters") but wrong if you plan to include links or copyable examples. For those cases, switch to a click-toggled popover and drop thepointer-events: none. - The readonly inputs in the sample markup preserve the demo state. Ship the component with real
type="email"andautocompleteattributes; the CSS is agnostic, but keep thetp-21__input:focusborder swap so users see the active field state Stripe-style. - Fixed 240px pill width does not respond to viewport. On sub-420px screens, the pill can push past the container even with 320px padding. Add an
@media (max-width: 640px)block that flipstp-21__tipto anchor above the field and shrinks the width tocalc(100vw - 40px).
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 90+ | 15+ | 88+ | 90+ |
Inline-flex, calc anchors, and the delayed visibility transition are all baseline. INP stays under 200ms because only two properties animate. iOS Safari surfaces the tip on :hover only when a stylus or Magic Keyboard is attached.