★ THE THIRD PUNK · BIGGEST AUDIENCE OF THE STORE

Stop using 100dvh for inputs
when the iOS keyboard lies to you.

POSITION: FIXED · BOTTOM: 0 · USER TYPES BLIND

Your chat app's textarea is pinned to bottom: 0. On desktop it looks perfect. On iPhone, the software keyboard slides up and your input ends up underneath the keyboard. The user's thumbs hover over nothing. Safari fires CSS layout recalculation before visualViewport finishes resizing — and that's the whole bug, exactly as the Vercel AI SDK community hit it in production this week. Every chat product, every AI textbox, every mobile checkout flow with a sticky bottom CTA is shipping this.

Audit my inputs · Free How it works
★ THE BUG · ONE PARAGRAPH

When the iOS keyboard slides up, your position: fixed; bottom: 0 input slides under it. Every mobile chat app is shipping this. Apple still hasn't fixed it.

The iOS software keyboard occupies the bottom \~45% of the viewport when open. Mobile Safari does not resize the layout viewport when the keyboard appears — it overlays the keyboard on top of your existing layout. Anything pinned to bottom: 0 ends up behind the keyboard. The visualViewport API does know the keyboard is there, but CSS layout has already settled before visualViewport.resize fires. Result: your textarea is invisible to your user. Their thumbs hover over the keyboard, expecting to type into something they can't see. They close your app. This is the single biggest mobile-web UX bug shipping in 2026.

70%
of web traffic in 2026 is mobile-first · Statcounter June 2026
0
major web framework starter templates handle this out of the box (Next.js, Vite, Astro, Nuxt — none of them) · informal survey June 2026
1
listener of visualViewport.resize + one CSS swap fixes every occurrence in your codebase · git-reversible
15→26.5
iOS versions affected and counting. Apple has not fixed this in 11 major releases over 4 years. · WebKit bugtracker, open since 2022

PLAIN ENGLISH You wrote position: fixed; bottom: 0 on your chat input because that's what the docs show. Now your user opens your app on their iPhone, taps the textarea, the keyboard pops up, and the textarea vanishes behind it. They can't see what they're typing. They close your app. This isn't your fault — it's the way Safari is built. But it IS your problem, because your users don't blame Safari, they blame your app. KeyboardPunk finds every place in your code where this can happen and gives you the deterministic fix.

★ FREE AUDIT · NOTHING UPLOADS · YOUR HTML NEVER LEAVES YOUR BROWSER

Paste your HTML. Find the keyboard traps.

Paste the part of your page that pins inputs to viewport bottom — chat composer, comment box, sticky CTA, mobile checkout, anything with position: fixed; bottom: 0 and a focus-able child. We render it in a 390×844 sandboxed iframe (iPhone 16 viewport) inside your browser, walk every fixed-position element looking for input / textarea / [contenteditable] descendants, and emit two snippets: a bootstrap JS that listens to visualViewport.resize and exposes the keyboard height as a CSS custom property, plus a one-line CSS swap that uses it. Zero upload, zero storage, zero AI.

PASTE HTML BELOW · INCLUDE <style> BLOCKS, INLINE STYLES, OR WHOLE PAGES
⌘ + Enter to audit
Paste some HTML above (with any inline <style> blocks) and hit Audit my inputs.
★ HOW IT WORKS · ALL IN YOUR BROWSER

Three steps. No upload. No AI. Just DOM detection plus the visualViewport patch.

STEP 1

Render in a 390×844 sandboxed iframe

Your pasted HTML loads into a hidden, script-disabled iframe sized to iPhone 16 viewport dimensions inside your own browser tab. Nothing leaves the page. The iframe is destroyed the moment the audit completes.

STEP 2

Find every bottom-fixed input container

For every element where getComputedStyle(el).position === 'fixed' AND bottom !== 'auto' AND the element contains an input, textarea, select, or [contenteditable] descendant — we flag it as a keyboard trap. We also check whether any ancestor uses vh / dvh / svh / lvh height units, which makes the bug worse.

STEP 3

Emit the two-snippet patch

For each trap you get the selector, plus two copy-buttons: a bootstrap JS snippet that wires visualViewport.resize to a --keyboard-inset CSS custom property, and a one-line CSS change replacing bottom: 0 with bottom: var(--keyboard-inset, 0px). Two paste-and-go snippets per occurrence. Works on every iOS device shipped in the last 8 years.

★ ALL THE PUNKS · ONE PASS · LIFETIME
The Punk Pass

KeyboardPunk is the third product in the Punk Store. PalettePunk audits color (Display P3 / OKLab gradients, sRGB color literals, modern color functions). StickyPunk finds position: sticky failures caused by ancestor overflow: hidden strangling the scroll context. Three more in the queue this quarter. The Punk Pass gets you all of them — current and future — for the price of buying three separately.

$299
LIFETIME · ALL CURRENT + FUTURE PUNKS
Get the Punk Pass
★ TWO WAYS TO BUY

$99 for KeyboardPunk alone. $299 for the whole Punk Store.

No subscription. No login wall. No "contact sales." Buy once, own forever, use on every project you ever ship.

$99
KEYBOARDPUNK · LIFETIME · ONE PRODUCT
Buy KeyboardPunk · $99 Or get the Punk Pass · $299 · everything · lifetime
Payment processor going live this week · email me for early access

Questions

Why is the fix a JS snippet instead of pure CSS?

The CSS-spec answer is env(keyboard-inset-height, 0px) — but it only ships in Safari 16.4+ and is behind a flag in Chrome. The JS fix using visualViewport.addEventListener('resize', ...) works on every iOS device shipped in the last 8 years, and adds up to about 15 lines of code total. The Punk Store sells deterministic browser-side patches; the patch language is CSS by default, JS where the bug demands it.

Does this run entirely in my browser?

Yes. Nothing uploads. The pasted HTML loads into a sandboxed iframe sized to iPhone 16 viewport (390×844) inside your tab. No fetch, no XHR, no telemetry. View source on this page if you want to verify — the whole scanner is in /scan.js, vanilla JS with zero dependencies.

Will the patch break Android?

No. Android Chrome's visualViewport behavior is already keyboard-aware — Math.max(0, window.innerHeight - vv.height) evaluates to 0 there, so --keyboard-inset stays at 0px and your layout is unchanged. The patch is a no-op everywhere except iOS Safari where it's needed.

Will Apple eventually fix this?

Hopefully. The bug has been in WebKit's tracker since 2022 across iOS 15 → 26.5 (current beta). The Vercel AI SDK community filed fresh issues in June 2026 — still broken. Tactical reason to ship our patch now: if Apple fixes it tomorrow, our patch becomes a no-op (good). If they don't, your users stop closing your app.

What about iOS PWAs in standalone mode?

Same bug, same fix. Standalone PWA Safari has the same keyboard overlay behavior as in-browser Safari. The visualViewport patch works identically.

Same shop as PalettePunk and StickyPunk?

Yes. Same Radio Art LLC, same engineering, same lifetime-license model, same "we publish the methodology" doctrine. Punk Pass upgrade always pays for itself by your second Punk.