Custom Context Menus for Touch & Desktop – ContextMenu

Category: Javascript , Menu & Navigation | August 8, 2025
Authoribnsultan
Last UpdateAugust 8, 2025
LicenseMIT
Views82 views
Custom Context Menus for Touch & Desktop – ContextMenu

ContextMenu is a lightweight JavaScript library that creates custom, reusable context menus.

It replaces the default browser menu with a clean, styleable menu that works on both desktop and touch devices.

Features:

  • Cross-platform compatibility: Works with right-click events on desktop and double-finger tap gestures on touch devices.
  • Automatic positioning: Dynamically repositions menus to prevent overflow beyond viewport boundaries.
  • Data binding support: Passes contextual data from trigger elements to menu items through JSON attributes.
  • Custom callback functions: Execute specified JavaScript functions when menu items are selected.
  • Lightweight footprint: Minimal CSS and JavaScript files that load quickly without dependencies.

How to use it:

1. Add the stylesheet to your <head> and the script tag before the closing </body> tag.

<link rel="stylesheet" href="/contextmenu.min.css">
<script src="/contextmenu.min.js"></script>

2. Add the cm-toggle class to elements that should trigger your context menu. Note that the data-cm-target attribute should point to the ID of your context menu.

<div class="cm-toggle" data-cm-target="#itemMenu">
  Right-click Here
</div>

3. Create a div with the class .context-menu-dialog and the corresponding ID. Inside, place a <ul> with your menu items.

<div id="itemMenu" class="context-menu-dialog">
  <ul>
    <li><a href="#">Menu item 1</a></li>
    <li><a href="#">Menu item 2</a></li>
    <li><a href="#">Menu item 3</a></li>
    ...
  </ul>
</div>

4. Use the data-cm-bind attribute on your trigger element to hold a JSON string. On the menu items (<li>), use data-cm-callback to name the JavaScript function that should run on click.

<div class="cm-toggle" 
     data-cm-target="#itemMenu" 
     data-cm-bind='{"id": "item-42", "type": "product"}'>
     Right-Click Me
</div>
<div id="itemMenu" class="context-menu-dialog">
  <ul>
    <li data-cm-callback="editItem">Edit</li>
    <li data-cm-callback="deleteItem">Delete</li>
  </ul>
</div>
function editItem(data) {
  console.log('Editing item with ID:', data.id); // Logs: "Editing item with ID: item-42"
  // Add your edit logic here
}
function deleteItem(data) {
  console.log('Deleting item of type:', data.type); // Logs: "Deleting item of type: product"
  // Add your delete logic here
}

5. Override the default styles to match your web design:

.context-menu-dialog {
  position: fixed;
  display: none;
  background-color: #fff;
  border: 1px solid #ccc;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  z-index: 1000;
  width: 220px; /* Standard width for context menu */
  max-width: 100%;
  border-radius: 5px; /* Add some rounding to the corners */
}
.context-menu-dialog ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.context-menu-dialog ul li {
  padding: 10px 20px;
  white-space: nowrap;
}
.context-menu-dialog ul li a {
  text-decoration: none;
  color: #333;
  display: block;
  width: 100%;
}
.context-menu-dialog ul li:hover {
  background-color: #e9e9e9;
}
.submenu {
  display: none;
  position: absolute;
  top: 0;
  left: 100%;
  background-color: #fff;
  border: 1px solid #ccc;
  width: 200px;
}
.context-menu-dialog li:hover .submenu {
  display: block;
}

FAQs:

Q: How do I create nested sub-menus?
A: ContextMenu.js does not support nested menus. It’s designed for simplicity. If you need multi-level menus, you should consider a more feature-rich context menu library.

Q: Why isn’t my callback function working?
A: First, make sure your function is in the global scope (e.g., window.myFunction = ... or just declared globally). Second, double-check that the name in the data-cm-callback attribute is an exact match for your function’s name, with no typos. Finally, open your browser’s developer console to check for any JavaScript errors that might be breaking the script.

Q: Can I generate the menu items dynamically with JavaScript?
A: Yes. The library attaches its listeners when init() runs. You can manipulate the DOM to add or remove <li> elements inside your .context-menu-dialog div at any time. As long as the new list items have the data-cm-callback attribute, they will work when the menu is triggered.

Q: How does the touch support actually work?
A: It listens for a touchstart event where event.touches.length is exactly 2. This means it requires a two-finger tap. This specific trigger avoids conflicts with single-finger actions like scrolling, tapping, or long-pressing for text selection.

Related Resources:

You Might Be Interested In:


Leave a Reply