Context Menu Demo
A simple context menu demo made with vanilla JavaScript.
by velo_ninja
HTML
<div class="box"><span id="info">Right-click me</span></div>
<menu class="context-menu">
<a href="javascript:;" class="bold">Change Color</a>
<hr>
<a href="javascript:;" data-color="red">Red</a>
<a href="javascript:;" data-color="green">Green</a>
<a href="javascript:;" data-color="blue">Blue</a>
<hr>
<a href="javascript:;" data-color="transparent">Reset</a>
</menu>
CSS
* { margin:0; padding:0; font-family:"Lucida Grade", "Lucida Sans Unicode", sans-serif; }
body { font-size:10.5pt; background-color:#DDD; }
.box { position:absolute; top:40%; left:50%; width:256px; height:256px; margin:-128px 0 0 -128px; border:1px solid #AAA; border-radius:10px; -webkit-transition:background-color .5s ease; transition:background-color .5s ease; }
.box span { position:absolute; bottom:-1.5em; left:0; right:0; font-size:inherit; text-align:center; color:#666; text-shadow:0 1px 0 #FFF; }
.context-menu {
display: none;
min-width: 150px;
position: fixed;
z-index: 900;
padding:5px 0;
background: #fff;
border: 1px solid #CCC;
border-radius: 5px;
box-shadow: 0 8px 20px rgba(0, 0, 0, .4);
font-weight: normal;
}
.context-menu.shown { display:block; }
.context-menu a {
display: block;
padding: 3px 16px;
overflow: hidden;
text-decoration: none;
text-overflow: ellipsis;
line-height: 16px;
white-space: nowrap;
font-size: 10.5pt;
font-weight: normal;
color: #333;
cursor: default;
}
.context-menu a.bold { font-weight:bold; }
.context-menu a.disabled { color:#B7B7B7; }
.context-menu a:not(.disabled):hover {
color: #FFF;
background-color:#1D5DF3;
background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%,#5f87f8), color-stop(100%,#1d5df3));
background-image:linear-gradient(to bottom, #5f87f8 0%,#1d5df3 100%);
}
.context-menu a > img {
float: left;
margin-right: 5px;
width: 16px;
height: 16px;
overflow: hidden;
}
.context-menu hr {
border: 0;
height: 1px;
margin: 5px 1px;
background: #EEE;
}
JavaScript
document.querySelector(".box").addEventListener("contextmenu", function (e) {
e.preventDefault();
var contextMenu = document.querySelector(".context-menu");
posX = (e.clientX + 150 > document.documentElement.clientWidth) ? e.clientX - 150 : e.clientX,
posY = (e.clientY + 140 + 55 > document.documentElement.clientHeight) ? e.clientY - 140 : e.clientY;
contextMenu.style.top = posY + "px";
contextMenu.style.left = posX + "px";
contextMenu.classList.add("shown");
});
document.querySelector(".context-menu").addEventListener("click", function (e) {
var target = e.target;
if (target.nodeName !== "A") return;
var color = target.getAttribute("data-color");
if (!color) return;
var info = target.textContent;
document.querySelector(".box").style.backgroundColor = color;
document.querySelector("#info").textContent = "You clicked " + info;
this.classList.remove("shown");
});
document.addEventListener("click", function (e) {
var target = e.target;
while (target.nodeType !== Node.DOCUMENT_NODE) {
if (target.classList.contains("shown")) return;
else target = target.parentNode;
}
var elems2hide = document.querySelectorAll(".shown");
for (var i = 0, length = elems2hide.length; i < length; i++) {
elems2hide[i].classList.remove("shown");
}
});