JSFiddle - React, Tailwind, and code Playground
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="menu">
<ul class="dropdown-menu">
<li class="dropdown-menu-item">item 1
<ul class="dropdown-menu_s">
<li class="dropdown-submenu">
<span>LoremLorem</span>
<ul class="dropdown-menu_delay">
<li>Lorem ipsum dolor ipisicing</li>
<li>sit amet, consectetur ad</li>
<li>ovident, vitae, ex eaque,</li>
<li>voluptate qui omnis quis velit</li>
<li>sint ipsa cumque deleniti quo</li>
<li>quod ratione magni eum consequuntur</li>
</ul>
</li>
<li class="dropdown-submenu">
<span>ipsumipsum</span>
<ul class="dropdown-menu_delay">
<li>quodquod</li>
<li>rationeratione</li>
<li>magnimagni</li>
<li>eumeum</li>
<li>consequunturconsequuntur</li>
<li>quoquo</li>
</ul>
</li>
<li class="dropdown-submenu">
<span>dolordolor</span>
<ul class="dropdown-menu_delay">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</li>
<li class="dropdown-submenu">
<span>ipisicingipisicing</span>
<ul class="dropdown-menu_delay">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</li>
<li class="dropdown-submenu">
<span>omnisomnis</span>
<ul class="dropdown-menu_delay">
<li></li>
<li></li>
<li></li>
...
CSS
.menu {
background: gray;
}
li {
cursor: pointer;
}
.dropdown-menu {
display: flex;
list-style-type: none;
}
.dropdown-submenu, .dropdown-menu-item {
background: white;
margin-left: 10px;
}
.dropdown-menu_s, .dropdown-menu_delay {
list-style-type: none;
padding: 0;
}
.dropdown-menu-item {
position: relative;
}
.dropdown-submenu {
padding: 10px;
}
.dropdown-menu_delay {
position: absolute;
top: 0;
left: 100%;
display: none;
background: red;
}
.dropdown-menu_delay li {
padding: 10px;
background: white;
}
.dropdown-submenu.active {
color: blue;
border: 1px solid blue;
}
JavaScript
$(document).ready(function(){
var nCurPosX; // текущее положение курсора
$('html').mousemove(function(e){
if(!e) e = window.event;
nCurPosX = e.clientX;
});
$('.dropdown-submenu').hover(function(){
var $curItem = $(this),
$submenu = $curItem.find('ul').eq(0);
$curItem.addClass('hover');
/* задержка чтобы при случайном наведении на пункт, под меню не показывалось */
setTimeout(function() {
/* если по истечению задержки мы все еще на том же пункт меню, значит показываем подменю */
if($curItem.hasClass('hover')) {
$submenu.css('display', 'block');
}
}, 300);
},
function(){
var nPosXStart = nCurPosX,
$submenu = $(this).find('ul').eq(0),
$curItem = $(this);
$curItem.removeClass('hover');
/* делаем небольшую задержку чтобы определить направление движение курсора */
setTimeout(function() {
var nPosXEnd = nCurPosX;
// если в сторону подменю, значит делаем большую задержку для возможности движения по диагонали
if(nPosXEnd - nPosXStart > 0)
setTimeout(function() {
/* если по истечению задержки курсор находится на подменю или текущем пункте меню тогда не прячем подменю */
if(!$submenu.hasClass('hover') && !$curItem.hasClass('hover')){
$submenu.css('display', 'none').removeClass('hover');
}}, 800);
// если нет и мы ушли с текущего пункта меню, моментально скрываем подменю
else if(!$submenu.hasClass('hover') && !$curItem.hasClass('hover')){
$submenu.css('display', 'none').removeClass('hover');
}
}, 10);
});
$('.submenu').hover(function(){
$(this).addClass('hover');
},
function(){
...