Modern browsers are much more than document viewers. They include built-in features, called web APIs, that let pages show pop-ups, move things around with the mouse, find the user's location, edit text in place, store data and much more. Some of these work with plain HTML attributes; others need a few lines of JavaScript.
This lesson covers four that are especially useful. The Popover API turns any element into a pop-up menu, tooltip or toast with just the popover attribute, no JavaScript needed. Drag and Drop lets users drag elements and files into place. Geolocation asks permission to find the user's position for maps and "near me" features. And contenteditable makes any element editable, the basis of rich text editors.
Each of these respects the user: features like location always ask for permission, and good pages explain why they need it and work without it. You'll learn the HTML for each, the JavaScript that powers the interactive parts, and the accessibility points to remember.
The Popover API
<button popovertarget="menu">Open menu</button>
<div id="menu" popover>
<a href="/account">Account</a>
<a href="/orders">Orders</a>
</div>popoveron an element hides it until it's opened;popovertargeton a button opens and closes it.- Popovers appear on top of everything (in the "top layer"), close automatically when you click outside or press Escape, and only one auto popover is open at a time.
popovertargetaction="show","hide"or"toggle"controls what the button does.popover="manual"creates one that stays open until closed explicitly, useful for notifications.- For a modal that blocks the rest of the page, use
<dialog>instead, covered in the details and dialog lesson.
Drag and drop and contenteditable
- Images and links are draggable by default; other elements need
draggable="true". - JavaScript handles the events:
dragstart(store data withe.dataTransfer.setData),dragover(calle.preventDefault()to allow dropping) anddrop(read the data and move the element). - Users can also drop files from their computer onto a page; read them from
e.dataTransfer.files. - Drag and drop doesn't work with keyboards or on every touch device, so always offer another way, such as buttons to move items up and down.
contenteditable="true"lets users edit an element's text directly. Its content isn't sent with forms automatically; JavaScript must readinnerText.
Geolocation
navigator.geolocation.getCurrentPosition(
(pos) => console.log(pos.coords.latitude, pos.coords.longitude),
(err) => console.log('Location unavailable:', err.message)
);- The browser asks the user for permission first; they can say no.
- It only works on secure (
https://) pages. - Always handle the error case and offer an alternative, such as typing a postcode.
- Ask for location only when the user does something that needs it, like pressing "Find stores near me", not as soon as the page loads.
HTML5 APIs Syntax
API syntax
<button popovertarget="tip">?</button>
<div id="tip" popover>Helpful tip text</div>
<div draggable="true" id="card">Drag me</div>
<div id="zone">Drop here</div>
<p contenteditable="true">Click to edit this text.</p>
<button id="locate">Find my location</button>
<script>
locate.onclick = () => navigator.geolocation.getCurrentPosition(p => console.log(p.coords));
</script>HTML5 APIs Summary
- The
popoverattribute pluspopovertargetcreates pop-ups with no JavaScript. - Popovers close on outside click or Escape and appear above all other content.
draggable="true"plus dragstart, dragover and drop events implement drag and drop.- Geolocation needs HTTPS and the user's permission; always handle refusal.
contenteditablemakes elements editable; provide keyboard-friendly alternatives for drag and drop.
HTML5 APIs Examples
Each example runs in the page. Edit the code and press Run to see what changes.
A menu and a tip with popover
<style>
[popover] { border: 1px solid #d1d5db; border-radius: 10px; padding: 12px; box-shadow: 0 10px 30px rgb(0 0 0 / 15%); }
#account a { display: block; padding: 6px 4px; }
</style>
<button popovertarget="account">My account</button>
<div id="account" popover>
<a href="#">Orders</a>
<a href="#">Addresses</a>
<a href="#">Sign out</a>
</div>
<p>Delivery takes 2 days <button popovertarget="info" aria-label="About delivery">?</button></p>
<div id="info" popover>Orders before 3pm are sent the same day.</div>Line-by-line explanation
- Line 2CSS styles every popover like a floating card.
- Line 5The button opens and closes the popover whose id matches.
- Lines 6 to 10The popover is hidden until opened, then shown above the page.
- Lines 11 to 12A second popover; opening it closes the first automatically.
Drag items into a basket
<style>
.item { display: inline-block; padding: 8px 12px; margin: 4px; background: #e0f2fe; border-radius: 8px; cursor: grab; }
#basket { min-height: 60px; margin-top: 10px; padding: 10px; border: 2px dashed #94a3b8; border-radius: 10px; }
#basket.over { background: #f0fdf4; border-color: #16a34a; }
</style>
<div class="item" draggable="true" id="apple">Apple</div>
<div class="item" draggable="true" id="bread">Bread</div>
<div id="basket">Drop items here</div>
<script>
document.querySelectorAll('.item').forEach((el) =>
el.addEventListener('dragstart', (e) => e.dataTransfer.setData('text/plain', el.id)));
const basket = document.getElementById('basket');
basket.addEventListener('dragover', (e) => { e.preventDefault(); basket.classList.add('over'); });
basket.addEventListener('dragleave', () => basket.classList.remove('over'));
basket.addEventListener('drop', (e) => {
e.preventDefault();
basket.classList.remove('over');
basket.append(document.getElementById(e.dataTransfer.getData('text/plain')));
});
</script>Line-by-line explanation
- Lines 6 to 7
draggable="true"lets users pick these items up. - Lines 10 to 11When dragging starts, the item's id is stored in the drag data.
- Line 13
preventDefaultin dragover is what allows dropping. - Lines 15 to 19On drop, read the id and move that element into the basket.
Location with a fallback, and editable text
<button id="near" type="button">Find shops near me</button>
<p id="where">Or type your postcode: <input aria-label="Postcode" size="8"></p>
<p><strong>Your note</strong> (click to edit):</p>
<p id="note" contenteditable="true" style="border: 1px solid #ccc; padding: 8px; border-radius: 6px;">Remember to buy milk.</p>
<script>
document.getElementById('near').addEventListener('click', () => {
if (!('geolocation' in navigator)) return;
navigator.geolocation.getCurrentPosition(
(pos) => { document.getElementById('where').textContent = `Searching near ${pos.coords.latitude.toFixed(2)}, ${pos.coords.longitude.toFixed(2)}`; },
() => { document.getElementById('where').prepend('Location not shared. '); }
);
});
</script>Line-by-line explanation
- Line 1Location is requested only after the user presses the button.
- Line 2A postcode box is always available as an alternative.
- Line 4
contenteditablemakes the note editable in place. - Line 7Check the API exists before using it.
- Lines 9 to 10Handle both success and refusal.
Common HTML5 APIs Mistakes
Asking for location on page load
<script>navigator.geolocation.getCurrentPosition(show);</script><button id="near">Use my location</button>
<script>near.onclick = () => navigator.geolocation.getCurrentPosition(show, showPostcodeBox);</script>Prompts without context are usually refused.
Forgetting preventDefault on dragover
<script>zone.addEventListener('drop', handleDrop);</script><script>
zone.addEventListener('dragover', (e) => e.preventDefault());
zone.addEventListener('drop', handleDrop);
</script>Without it, the browser never allows the drop.
A popover button pointing to the wrong id
<button popovertarget="#menu">Menu</button>
<div id="menu" popover>...</div><button popovertarget="menu">Menu</button>
<div id="menu" popover>...</div>popovertarget takes the id itself, without a hash.
HTML5 APIs in Real Projects
APIs in real apps
Store finders and delivery apps use Geolocation, project boards such as Trello use drag and drop, website builders and note apps rely on contenteditable, and the Popover API now powers account menus, tooltips and notifications on many sites without any JavaScript library.
HTML5 APIs Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Make the button open the popover with id "help".
<button ="help">Help</button>
<div id="help" popover>Contact us any time.</div>
popovertarget connects the button to the popover.Which attribute makes an element draggable?
What must happen before Geolocation returns a position?
What happens when you click outside an open auto popover?
The popover never opens: the button points to the wrong id and the popover element is missing its attribute. Fix both.
<button popovertarget="#share">Share</button>
<div id="share">Copy link | Email | Message</div>- The button targets "share"
- The div is a popover
- The popover is hidden until opened
HTML5 APIs Quiz
5 questions to check what you learned.
Does the popover attribute need JavaScript to work?
- Yes, always
- Only for menus
- No, a button with popovertarget can open it
- Only in Chrome
Which event must call preventDefault to allow dropping?
- dragover
- dragstart
- drop
- dragend
What does contenteditable="true" do?
- Makes text bold
- Lets users edit the element's content directly
- Saves text to the server
- Turns the element into a textarea that submits with forms
What's a good practice when a feature needs location?
- Request it on page load
- Hide the prompt
- Ask when the user clicks a clearly labelled button, and offer an alternative
- Require it for the whole site
Why offer buttons as well as drag and drop for reordering?
- Buttons are faster
- Drag and drop is deprecated
- Browsers require it
- Drag and drop isn't usable by keyboard users and doesn't work everywhere on touch screens
HTML5 APIs Challenge
A help popover
Create:
- A button with
popovertarget="faq" - An element with
id="faq"and thepopoverattribute, containing a heading and a paragraph - A paragraph with
contenteditable="true"
- Button targets faq
- faq is a popover with a heading and paragraph
- An editable paragraph