Show a custom context menu at clicked position
The browser will show the default context menu when user right-clicks on the page. Sometimes, we want to replace the default menu with our own menu that allows user to perform additional actions.
This post illustrates a simple implementation. First of all, let's create an element that we want to show a customized context menu element:
<div id="element">Right-click me</div>
<ul id="menu">...</menu>
Prevent the default context menu from being displayed
const ele = document.getElementById('element');
ele.addEventListener('contextmenu', function (e) {
e.preventDefault();
});
Show the menu at clicked position
We will calculate the position of menu, but it need to be positioned absolutely to its container firstly. So, let's place the element and menu to a container whose position is relative
:
<div class="relative">
<div id="element">Right-click me</div>
<ul id="menu" class="absolute hidden">...</menu>
</div>
The relative
, absolute
and hidden
classes are defined as following:
.relative {
position: relative;
}
.absolute {
position: absolute;
}
.hidden {
display: none;
}
Resource
This post doesn't tell how to build the menu. It's up to you but
CSS Layout is a nice resource to look at
It's the time to set the position for the menu. It can be calculated based on
the mouse position:
ele.addEventListener('contextmenu', function (e) {
const rect = ele.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
menu.style.top = `${y}px`;
menu.style.left = `${x}px`;
menu.classList.remove('hidden');
});
Close the menu when clicking outside
We can handle the
click
event of
document
, and determine if user
clicks outside of the menu:
ele.addEventListener('contextmenu', function(e) {
...
document.addEventListener('click', documentClickHandler);
});
const documentClickHandler = function(e) {
const isClickedOutside = !menu.contains(e.target);
if (isClickedOutside) {
menu.classList.add('hidden');
document.removeEventListener('click', documentClickHandler);
}
};
The menu is hidden by
adding the
hidden
class.
More importantly, the
click
event handler is also removed from
document
as we don't need to handle that when the menu is hidden. This technique is mentioned in the
Create one time event handler post.
Use case
Finally, following is the demo you can play with!
Demo
Show a custom context menu at clicked position
See also