Onscreen Keyboard
Full onscreen keyboard for touch interfaces, kiosks, and terminals with QWERTY layout, special keys, and sheet mode.
Basic QWERTY Layout
Preview
<div class="osk" style="max-width: 480px;">
<div class="osk-row">
<button class="osk-key">Q</button>
<button class="osk-key">W</button>
<button class="osk-key">E</button>
<button class="osk-key">R</button>
<button class="osk-key">T</button>
<button class="osk-key">Y</button>
<button class="osk-key">U</button>
<button class="osk-key">I</button>
<button class="osk-key">O</button>
<button class="osk-key">P</button>
</div>
<div class="osk-row">
<button class="osk-key">A</button>
<button class="osk-key">S</button>
<button class="osk-key">D</button>
<button class="osk-key">F</button>
<button class="osk-key">G</button>
<button class="osk-key">H</button>
<button class="osk-key">J</button>
<button class="osk-key">K</button>
<button class="osk-key">L</button>
</div>
<div class="osk-row">
<button class="osk-key osk-key-special osk-key-shift">
<svg class="osk-key-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19V5M5 12l7-7 7 7"/></svg>
</button>
<button class="osk-key">Z</button>
<button class="osk-key">X</button>
<button class="osk-key">C</button>
<button class="osk-key">V</button>
<button class="osk-key">B</button>
<button class="osk-key">N</button>
<button class="osk-key">M</button>
<button class="osk-key osk-key-special osk-key-backspace">
<svg class="osk-key-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 4H8l-7 8 7 8h13a2 2 0 002-2V6a2 2 0 00-2-2z"/><line x1="18" y1="9" x2="12" y2="15"/><line x1="12" y1="9" x2="18" y2="15"/></svg>
</button>
</div>
<div class="osk-row">
<button class="osk-key osk-key-special osk-key-numbers">123</button>
<button class="osk-key osk-key-space">ERPlora</button>
<button class="osk-key osk-key-special osk-key-enter">Enter</button>
</div>
</div> Requires: ux.min.css
<div class="w-full max-w-[480px] select-none p-2 bg-base-200 rounded-box" style="touch-action: manipulation;">
<div class="flex justify-center gap-1.5 mb-1.5">
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92 active:bg-primary active:text-primary-content">Q</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92 active:bg-primary active:text-primary-content">W</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92 active:bg-primary active:text-primary-content">E</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92 active:bg-primary active:text-primary-content">R</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92 active:bg-primary active:text-primary-content">T</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92 active:bg-primary active:text-primary-content">Y</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92 active:bg-primary active:text-primary-content">U</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92 active:bg-primary active:text-primary-content">I</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92 active:bg-primary active:text-primary-content">O</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92 active:bg-primary active:text-primary-content">P</button>
</div>
<div class="flex justify-center gap-1.5 mb-1.5">
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">A</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">S</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">D</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">F</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">G</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">H</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">J</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">K</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">L</button>
</div>
<div class="flex justify-center gap-1.5 mb-1.5">
<button class="flex-[1.5] flex items-center justify-center h-12 bg-base-300 rounded-field text-sm font-semibold shadow-sm hover:bg-base-300/80 active:scale-92">Shift</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">Z</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">X</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">C</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">V</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">B</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">N</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">M</button>
<button class="flex-[1.5] flex items-center justify-center h-12 bg-base-300 rounded-field text-sm font-semibold shadow-sm hover:bg-base-300/80 active:scale-92">Del</button>
</div>
<div class="flex justify-center gap-1.5">
<button class="flex-[1.25] flex items-center justify-center h-12 bg-base-300 rounded-field text-sm font-semibold shadow-sm hover:bg-base-300/80 active:scale-92">123</button>
<button class="flex-[5] flex items-center justify-center h-12 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">ERPlora</button>
<button class="flex-[2] flex items-center justify-center h-12 bg-primary rounded-field text-sm font-semibold text-primary-content shadow-sm hover:brightness-90 active:scale-92">Enter</button>
</div>
</div> Requires: tw.min.css
// Handle key presses on the onscreen keyboard
const osk = document.querySelector('.osk');
let isShift = false;
osk.querySelectorAll('.osk-key').forEach(key => {
key.addEventListener('click', () => {
const text = key.textContent.trim();
const input = document.querySelector('input:focus');
if (!input) return;
if (key.classList.contains('osk-key-shift')) {
isShift = !isShift;
key.classList.toggle('active', isShift);
} else if (key.classList.contains('osk-key-backspace')) {
input.value = input.value.slice(0, -1);
} else if (key.classList.contains('osk-key-enter')) {
input.form?.requestSubmit();
} else if (key.classList.contains('osk-key-space')) {
input.value += ' ';
} else {
input.value += isShift ? text.toUpperCase() : text.toLowerCase();
if (isShift) { isShift = false; }
}
input.dispatchEvent(new Event('input'));
});
}); Compact Variant
Preview
ERPlora Terminal
<div class="osk osk-compact" style="max-width: 420px;">
<div class="osk-header">
<span class="osk-title">ERPlora Terminal</span>
<button class="osk-lang-btn">
<span>EN</span>
<svg class="osk-key-icon" style="width:14px;height:14px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg>
</button>
</div>
<div class="osk-row">
<button class="osk-key">Q</button>
<button class="osk-key">W</button>
<button class="osk-key">E</button>
<button class="osk-key">R</button>
<button class="osk-key">T</button>
<button class="osk-key">Y</button>
<button class="osk-key">U</button>
<button class="osk-key">I</button>
<button class="osk-key">O</button>
<button class="osk-key">P</button>
</div>
<div class="osk-row">
<button class="osk-key">A</button>
<button class="osk-key">S</button>
<button class="osk-key">D</button>
<button class="osk-key">F</button>
<button class="osk-key">G</button>
<button class="osk-key">H</button>
<button class="osk-key">J</button>
<button class="osk-key">K</button>
<button class="osk-key">L</button>
</div>
<div class="osk-row">
<button class="osk-key osk-key-special osk-key-shift">
<svg class="osk-key-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19V5M5 12l7-7 7 7"/></svg>
</button>
<button class="osk-key">Z</button>
<button class="osk-key">X</button>
<button class="osk-key">C</button>
<button class="osk-key">V</button>
<button class="osk-key">B</button>
<button class="osk-key">N</button>
<button class="osk-key">M</button>
<button class="osk-key osk-key-special osk-key-backspace">
<svg class="osk-key-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 4H8l-7 8 7 8h13a2 2 0 002-2V6a2 2 0 00-2-2z"/><line x1="18" y1="9" x2="12" y2="15"/><line x1="12" y1="9" x2="18" y2="15"/></svg>
</button>
</div>
<div class="osk-row">
<button class="osk-key osk-key-special osk-key-numbers">123</button>
<button class="osk-key osk-key-space"></button>
<button class="osk-key osk-key-special osk-key-enter">Done</button>
</div>
</div> Requires: ux.min.css
<div class="w-full max-w-[420px] select-none p-1.5 bg-base-200 rounded-box" style="--osk-key-height: 40px; --osk-gap: 4px; touch-action: manipulation;">
<div class="flex items-center justify-between pb-2 mb-1 px-1 border-b border-base-300">
<span class="text-xs font-semibold uppercase tracking-wide text-base-content/50">ERPlora Terminal</span>
<button class="flex items-center gap-1 text-sm font-medium px-2 py-1 rounded-md bg-base-100 border border-base-300 hover:bg-base-200 active:scale-97">EN <svg class="size-3.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg></button>
</div>
<!-- Row 1 -->
<div class="flex justify-center gap-1 mb-1">
<button class="flex-1 max-w-[60px] flex items-center justify-center h-10 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">Q</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-10 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">W</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-10 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">E</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-10 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">R</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-10 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">T</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-10 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">Y</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-10 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">U</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-10 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">I</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-10 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">O</button>
<button class="flex-1 max-w-[60px] flex items-center justify-center h-10 bg-base-100 rounded-field text-lg font-medium shadow-sm hover:bg-base-200 active:scale-92">P</button>
</div>
<!-- Row 2: A-L, Row 3: Shift/Z-M/Backspace, Row 4: 123/Space/Done -->
<!-- (same pattern as basic, with h-10 instead of h-12 and gap-1 instead of gap-1.5) -->
</div> Requires: tw.min.css
// Compact keyboard with language switcher
const langBtn = document.querySelector('.osk-lang-btn');
const langs = ['EN', 'ES', 'FR', 'DE'];
let langIndex = 0;
langBtn.addEventListener('click', () => {
langIndex = (langIndex + 1) % langs.length;
langBtn.querySelector('span').textContent = langs[langIndex];
// Swap key labels for the selected layout
}); Glass Variant
Preview
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 2rem; border-radius: 1rem;">
<div class="osk glass" style="max-width: 480px;">
<div class="osk-row">
<button class="osk-key">Q</button>
<button class="osk-key">W</button>
<button class="osk-key">E</button>
<button class="osk-key">R</button>
<button class="osk-key">T</button>
<button class="osk-key">Y</button>
<button class="osk-key">U</button>
<button class="osk-key">I</button>
<button class="osk-key">O</button>
<button class="osk-key">P</button>
</div>
<div class="osk-row">
<button class="osk-key">A</button>
<button class="osk-key">S</button>
<button class="osk-key">D</button>
<button class="osk-key">F</button>
<button class="osk-key">G</button>
<button class="osk-key">H</button>
<button class="osk-key">J</button>
<button class="osk-key">K</button>
<button class="osk-key">L</button>
</div>
<div class="osk-row">
<button class="osk-key osk-key-special osk-key-shift">
<svg class="osk-key-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19V5M5 12l7-7 7 7"/></svg>
</button>
<button class="osk-key">Z</button>
<button class="osk-key">X</button>
<button class="osk-key">C</button>
<button class="osk-key">V</button>
<button class="osk-key">B</button>
<button class="osk-key">N</button>
<button class="osk-key">M</button>
<button class="osk-key osk-key-special osk-key-backspace">
<svg class="osk-key-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 4H8l-7 8 7 8h13a2 2 0 002-2V6a2 2 0 00-2-2z"/><line x1="18" y1="9" x2="12" y2="15"/><line x1="12" y1="9" x2="18" y2="15"/></svg>
</button>
</div>
<div class="osk-row">
<button class="osk-key osk-key-special osk-key-numbers">123</button>
<button class="osk-key osk-key-space">ERPlora</button>
<button class="osk-key osk-key-special osk-key-enter">Go</button>
</div>
</div>
</div> Requires: ux.min.css
<div style="background: linear-gradient(135deg, #667eea, #764ba2); padding: 1.5rem; border-radius: 0.75rem;">
<div class="glass rounded-box p-3 flex flex-col gap-1.5" style="max-width: 480px; margin: 0 auto;">
<div class="flex gap-1.5 justify-center">
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">Q</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">W</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">E</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">R</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">T</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">Y</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">U</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">I</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">O</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">P</button>
</div>
<div class="flex gap-1.5 justify-center px-4">
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">A</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">S</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">D</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">F</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">G</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">H</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">J</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">K</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">L</button>
</div>
<div class="flex gap-1.5 justify-center">
<button class="w-12 h-11 rounded-lg text-sm font-medium text-white/70" style="background: rgba(255,255,255,0.12);">⇧</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">Z</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">X</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">C</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">V</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">B</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">N</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">M</button>
<button class="w-12 h-11 rounded-lg text-sm font-medium text-white/70" style="background: rgba(255,255,255,0.12);">⌫</button>
</div>
<div class="flex gap-1.5 justify-center">
<button class="w-16 h-11 rounded-lg text-sm font-medium text-white/70" style="background: rgba(255,255,255,0.12);">123</button>
<button class="flex-1 h-11 rounded-lg text-sm font-medium text-white" style="background: rgba(255,255,255,0.18);">ERPlora</button>
<button class="w-16 h-11 rounded-lg text-sm font-medium text-white bg-primary">Go</button>
</div>
</div>
</div> Requires: tw.min.css
// No JS needed -- glass is a CSS-only variant Sheet Mode
Preview
ERPlora Search
<!-- The sheet slides up from the bottom of the screen -->
<div class="osk-sheet osk-sheet-open" style="position: relative; transform: none;">
<div class="osk-sheet-container">
<div class="osk-sheet-header">
<span class="osk-sheet-title">ERPlora Search</span>
<div class="osk-sheet-actions">
<button class="osk-sheet-btn">Paste</button>
<button class="osk-sheet-btn-close">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
</div>
</div>
<div class="osk-sheet-content">
<div class="osk" style="max-width: 480px; margin: 0 auto;">
<div class="osk-row">
<button class="osk-key">Q</button>
<button class="osk-key">W</button>
<button class="osk-key">E</button>
<button class="osk-key">R</button>
<button class="osk-key">T</button>
<button class="osk-key">Y</button>
<button class="osk-key">U</button>
<button class="osk-key">I</button>
<button class="osk-key">O</button>
<button class="osk-key">P</button>
</div>
<div class="osk-row">
<button class="osk-key">A</button>
<button class="osk-key">S</button>
<button class="osk-key">D</button>
<button class="osk-key">F</button>
<button class="osk-key">G</button>
<button class="osk-key">H</button>
<button class="osk-key">J</button>
<button class="osk-key">K</button>
<button class="osk-key">L</button>
</div>
<div class="osk-row">
<button class="osk-key osk-key-special osk-key-shift">
<svg class="osk-key-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19V5M5 12l7-7 7 7"/></svg>
</button>
<button class="osk-key">Z</button>
<button class="osk-key">X</button>
<button class="osk-key">C</button>
<button class="osk-key">V</button>
<button class="osk-key">B</button>
<button class="osk-key">N</button>
<button class="osk-key">M</button>
<button class="osk-key osk-key-special osk-key-backspace">
<svg class="osk-key-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 4H8l-7 8 7 8h13a2 2 0 002-2V6a2 2 0 00-2-2z"/><line x1="18" y1="9" x2="12" y2="15"/><line x1="12" y1="9" x2="18" y2="15"/></svg>
</button>
</div>
<div class="osk-row">
<button class="osk-key osk-key-special osk-key-numbers">123</button>
<button class="osk-key osk-key-space"></button>
<button class="osk-key osk-key-special osk-key-enter">Search</button>
</div>
</div>
</div>
</div>
</div> Requires: ux.min.css
<!-- The osk-sheet wrapper provides fixed bottom positioning with slide-up transition.
Add osk-sheet-open to show the keyboard. The osk-sheet-container uses glass morphism. --> Requires: tw.min.css
// Toggle sheet keyboard
function openKeyboard() {
document.querySelector('.osk-sheet').classList.add('osk-sheet-open');
}
function closeKeyboard() {
document.querySelector('.osk-sheet').classList.remove('osk-sheet-open');
}
// Close button
document.querySelector('.osk-sheet-btn-close')
.addEventListener('click', closeKeyboard);
// Open when input is focused (for kiosk mode)
document.querySelectorAll('input[type="text"]').forEach(input => {
input.addEventListener('focus', openKeyboard);
}); Classes Reference
| Class | Description |
|---|---|
.osk | Base keyboard container with padding and background |
.osk-compact | Smaller keys (40px height) and reduced gaps |
.osk-lg | Larger keys (56px height) and increased gaps |
.osk-inline | No border-radius or background (for embedding) |
.osk.glass | Glass morphism variant with translucent keys |
.osk-header | Header bar with title and language selector |
.osk-title | Keyboard header label text |
.osk-lang-btn | Language switcher button |
.osk-row | Horizontal row of keys |
.osk-key | Standard character key |
.osk-key-special | Special function key (wider, darker background) |
.osk-key-shift | Shift key (supports .active and .caps-lock) |
.osk-key-backspace | Backspace key (flex: 1.5) |
.osk-key-enter | Enter key (primary color, flex: 2) |
.osk-key-space | Spacebar (flex: 5) |
.osk-key-numbers | Number/symbol toggle key (flex: 1.25) |
.osk-key-icon | Icon size utility for SVGs inside keys |
.osk-sheet | Fixed bottom sheet container for keyboard |
.osk-sheet-open | Slides the sheet into view |
.osk-sheet-container | Glass-styled inner container |
.osk-sheet-header | Sheet header with title and action buttons |
.osk-sheet-btn | Action button inside the sheet header |
.osk-sheet-btn-close | Round close button for the sheet |
.osk-preview | Floating key preview popup on press |