Mozilla Takes Aim at Chrome's Prompt API: A Battle for User Control
In recent years, browser vendors have been rethinking how websites interact with users—especially when it comes to permissions, popups, and data access. One key battleground? The prompt() API.
While Chrome and other Chromium-based browsers have long supported the classic window.prompt() for simple user input, Mozilla Firefox has taken a more privacy-conscious stance—limiting and discouraging its use in modern web development. This isn’t just about preference; it’s a philosophical shift toward user control and security.
In this tutorial, we’ll explore:
- What the
prompt()API does - Why Mozilla is pushing back
- How to build modern, accessible alternatives
- A step-by-step replacement using HTML, CSS, and JavaScript
Let’s dive in.
What Is window.prompt()?
The prompt() method is a built-in browser function that displays a modal dialog asking the user for input:
const name = prompt("What's your name?");
console.log(name); // Logs user input or null if canceled
It’s simple, synchronous, and requires zero setup. But simplicity comes at a cost.
Why Mozilla Is Saying “No” to prompt()
Mozilla has been vocal about deprecating disruptive, non-standard UI patterns like alert(), confirm(), and prompt(). Here’s why:
- ❌ Poor user experience – Blocks the entire page
- ❌ Not customizable – Can’t style or enhance
- ❌ Accessibility issues – Hard to navigate with screen readers
- ❌ Security risks – Phishing-prone (fake prompts)
- ❌ Not mobile-friendly – Awkward on touch devices
Instead, Mozilla encourages developers to build custom, accessible, and user-friendly modals.
🔥 Pro Tip: Modern browsers may block
prompt()in cross-origin iframes or during automated flows.
Step-by-Step: Replace prompt() with a Custom Modal
Let’s build a clean, accessible alternative that works across all browsers—including Firefox.
Step 1: HTML Structure
Create a modal with an input field and buttons:
<!-- Custom Prompt Modal -->
<div id="custom-prompt" class="modal hidden">
<div class="modal-content">
<p id="prompt-message">Enter your name:</p>
<input type="text" id="prompt-input" autofocus />
<div class="modal-buttons">
<button id="prompt-cancel">Cancel</button>
<button id="prompt-submit">OK</button>
</div>
</div>
</div>
<!-- Trigger Button -->
<button id="open-prompt">Ask Name</button>
Step 2: Add CSS Styling
Make it look clean and responsive:
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 8px;
width: 90%;
max-width: 400px;
text-align: center;
}
#prompt-input {
width: 100%;
padding: 10px;
margin: 10px 0;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
}
.modal-buttons {
margin-top: 15px;
}
.modal-buttons button {
padding: 8px 16px;
margin: 0 5px;
border: none;
border-radius: 4px;
cursor: pointer;
}
#prompt-cancel {
background: #f44336;
color: white;
}
#prompt-submit {
background: #4CAF50;
color: white;
}
.hidden {
display: none;
}
Step 3: JavaScript Logic
Now, replace prompt() with a promise-based custom function:
javascript
class CustomPrompt {
constructor() {
this.modal = document.getElementById('custom-prompt');
this.messageEl = document.getElementById('prompt-message');
this.inputEl = document.getElementById('prompt-input');
this.cancelBtn = document.getElementById('prompt-cancel');
this.submitBtn = document.getElementById('prompt-submit');
this.resolvePromise = null;
// Close on cancel
this.cancelBtn.addEventListener('click', () => {
this.close(null);
});
// Close on submit
this.submitBtn.addEventListener('click', () => {
this.close(this.inputEl.value.trim() || null);
});
// Close on ESC key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
this.close(null);
}
});
// Close when clicking outside
this.modal.addEventListener('click', (e) => {
if (e.target === this.modal) {
this.close(null);
}
});
}
// Show prompt and return a promise
show(message = 'Enter value:', defaultValue = '') {
this.messageEl.textContent = message;
this.inputEl.value = defaultValue;
this.modal.classList.remove('hidden');
// Focus input after render
setTimeout(() => this.inputEl.focus(), 100);
// Return a promise that resolves when user submits
---
☕ **Appreciative**
Top comments (0)