Как реализовать Navbar Dropdown Hover в Bootstrap v4?
Я немного запутался в новой версии bootstrap, так как они изменили выпадающие меню на divs:
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">Navbar</a>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" onclick="location.href='http://example.com'; return false;" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown link
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
</ul>
</div>
</nav>
Вы, ребята, имеете какую-либо идею, чтобы выпустить выпадающее меню в раскрывающемся списке в этом фрагменте без добавления дополнительного кода сценария (только css и скрипт из начальной загрузки)? Я уже видел классы bootstrap css, и я не могу относиться к тем, которые есть в bootstrap V3 (я выполняю это без добавления jquery в V3).
Ответы
Ответ 1
Простое решение только для CSS:
.dropdown:hover>.dropdown-menu {
display: block;
}
При нажатии на него все равно будет переключено show
класса (и оно останется открытым, когда оно больше не будет зависать).
Чтобы обойти это правильно, используйте события и свойства, зарезервированные для устройств на основе указателей: jQuery mouseenter
, mouseleave
и :hover
. Должно работать гладко, интуитивно, не мешая вообще с тем, как раскрывающийся работает на устройствах на базе сенсорных. Попробуйте, дайте мне знать, если это работает для вас:
Полное решение jQuery (не тронутое касание):
Решение до версии 4.1.2 (устарело):
$('body').on('mouseenter mouseleave','.dropdown',function(e){
var _d=$(e.target).closest('.dropdown');
if (e.type === 'mouseenter')_d.addClass('show');
setTimeout(function(){
_d.toggleClass('show', _d.is(':hover'));
$('[data-toggle="dropdown"]', _d).attr('aria-expanded',_d.is(':hover'));
},300);
});
$('body').on('mouseenter mouseleave','.dropdown',function(e){
var _d=$(e.target).closest('.dropdown');
if (e.type === 'mouseenter')_d.addClass('show');
setTimeout(function(){
_d.toggleClass('show', _d.is(':hover'));
$('[data-toggle="dropdown"]', _d).attr('aria-expanded',_d.is(':hover'));
},300);
});
/* this is not needed, just prevents page reload when a dd link is clicked */
$('.dropdown a').on('click tap', e => e.preventDefault())
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href>Navbar</a>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href>Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href>Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href>Pricing</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown link
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href>Action</a>
<a class="dropdown-item" href>Another action</a>
<a class="dropdown-item" href>Something else here</a>
</div>
</li>
</ul>
</div>
</nav>
Ответ 2
Просто добавьте этот простой код css в свой стиль и вы готовы к работе.
.dropdown:hover > .dropdown-menu {
display: block;
}
.dropdown > .dropdown-toggle:active {
/*Without this, clicking will make it sticky*/
pointer-events: none;
}
Ответ 3
У Андрея "полное" решение jQuery + CSS имеет правильное намерение, но оно многословно и еще не завершено. Неполный, потому что, хотя он, вероятно, покрывает все необходимые изменения DOM, в нем отсутствует запуск пользовательских событий. Подробно, потому что это заново изобретает колесо, когда Bootstrap уже предоставляет метод dropdown(), который делает все.
Таким образом, правильное, СУХОЕ решение, которое не зависит от хака CSS, часто повторяемого среди других ответов, это просто jQuery:
$('body').on('mouseover mouseout', '.dropdown', function(e) {
$(e.target).dropdown('toggle');
});
Ответ 4
Функциональность Bootstrap, похоже, немного изменилась с момента выпуска версии v4. Появится .dropdown-menu
который также получит класс .show
в дополнение к .dropdown
. Я адаптировал Андрея к ответу, чтобы переключить класс в .dropdown-menu
. Обратите внимание, что CSS больше не нужен, и HTML тот же, за исключением того, что я обновил ссылки на текущие версии, а класс nav изменился на navbar-expand-md
.
$('body').on('mouseenter mouseleave', '.dropdown', function (e) {
var dropdown = $(e.target).closest('.dropdown');
var menu = $('.dropdown-menu', dropdown);
dropdown.addClass('show');
menu.addClass('show');
setTimeout(function () {
dropdown[dropdown.is(':hover') ? 'addClass' : 'removeClass']('show');
menu[dropdown.is(':hover') ? 'addClass' : 'removeClass']('show');
}, 300);
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<nav class="navbar navbar-expand-md navbar-light bg-faded">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">Navbar</a>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="http://example.com" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown link
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
</ul>
</div>
</nav>
Ответ 5
Я уже использовал и создал навигационную панель, когда мне было предложено изменить ее на взаимодействие с наведением, поэтому в итоге это было исправлено с помощью jQuery.
function bootstrapHoverMenu (bp = 768) {
// close all dropdowns that are open
$('body').click( function (e) {
$('.dropdown-menu.show').removeClass('show');
});
// show dropdown for the link clicked
$('.nav-item').hover(function (e) {
$('.dropdown-menu.show').removeClass('show');
if(( $(window).width() >= bp )) {
$dd = $(this).find('.dropdown-menu');
$dd.addClass('show');
}
});
// get href for top level link if clicked and open
$('.dropdown').click(function (e) {
if( $(window).width() < bp ) {
$('.dropdown-menu').css({'display': 'none'});
}
$href = $(this).find('.nav-link').attr('href');
window.open($href, '_self');
});
}
$(document).ready( function() {
// when page ready run the fix
bootstrapHoverMenu();
});
Downside - это мобильная связь только с верхними уровнями.
Ответ 6
Bootstrap v4 Solution - основанный на jQuery, но лучше, чем чистое решение css
Это гарантирует, что вы все еще можете следить за кликами на уровне верхнего уровня и совместимы с мобильными устройствами.
Это было сделано с учетом настольных компьютеров и мобильных устройств. Не упаковал jQuery с условием, который проверяет, превышает ли ширина окна 768 пикселей.
JQuery
/** Dropdown on hover */
$(".nav-link.dropdown-toggle").hover( function () {
// Open up the dropdown
$(this).removeAttr('data-toggle'); // remove the data-toggle attribute so we can click and follow link
$(this).parent().addClass('show'); // add the class show to the li parent
$(this).next().addClass('show'); // add the class show to the dropdown div sibling
}, function () {
// on mouseout check to see if hovering over the dropdown or the link still
var isDropdownHovered = $(this).next().filter(":hover").length; // check the dropdown for hover - returns true of false
var isThisHovered = $(this).filter(":hover").length; // check the top level item for hover
if(isDropdownHovered || isThisHovered) {
// still hovering over the link or the dropdown
} else {
// no longer hovering over either - lets remove the 'show' classes
$(this).attr('data-toggle', 'dropdown'); // put back the data-toggle attr
$(this).parent().removeClass('show');
$(this).next().removeClass('show');
}
});
// Check the dropdown on hover
$(".dropdown-menu").hover( function () {
}, function() {
var isDropdownHovered = $(this).prev().filter(":hover").length; // check the dropdown for hover - returns true of false
var isThisHovered= $(this).filter(":hover").length; // check the top level item for hover
if(isDropdownHovered || isThisHovered) {
// do nothing - hovering over the dropdown of the top level link
} else {
// get rid of the classes showing it
$(this).parent().removeClass('show');
$(this).removeClass('show');
}
});
CSS
@media(min-width: 768px) {
.dropdown-menu {
margin-top: 0; // fixes closing on slow mouse transition
}
}
Ответ 7
Bootstrap 4 CSS-only
Ни один из ответов CSS не работает полностью. Либо выпадающее меню остается открытым после клика, либо есть пробел, из-за которого выпадающее меню скрывается, прежде чем вы сможете добраться до ссылок меню, чтобы щелкнуть.
Здесь простое решение CSS:
.navbar-nav li:hover .dropdown-menu {
display: block;
}
Удалите data-toggle=dropdown
из HTML-разметки, чтобы предотвратить раскрытие списка нажатием кнопки. Используйте mt-0
(margin-top: 0), чтобы устранить пробел над меню и сделать возможным наведение элементов меню.
Демо https://www.codeply.com/go/awyU7VTIJf
Полный код:
.navbar-nav li:hover .dropdown-menu {
display: block;
}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
..
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown">
Dropdown
</a>
<div class="dropdown-menu mt-0" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
</ul>
</div>
</nav>
Ответ 8
Я думаю, что это просто работает с bootstrap 4, я добавляю inline, но вы всегда можете связать событие с скриптом.
<a
onmouseover="$('#navbarDropdownMenuLink').dropdown('toggle')"
class="nav-link dropdown-toggle"
href="http://example.com"
id="navbarDropdownMenuLink"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
Dropdown link
</a>
Ответ 9
CSS-решения не работают должным образом на сенсорном устройстве
Я обнаружил, что любые CSS-решения заставляют меню оставаться открытым на сенсорных устройствах, они больше не рушатся.
Итак, я прочитал статью: https://www.brianshim.com/webtricks/drop-down-menus-on-ios-and-android/ (Брайан Шим)
Очень полезно! В нем говорится, что сенсорное устройство всегда сначала проверяет существование класса наведения на элементе.
Но: с помощью jQuery.show() вы вводите атрибут стиля (display: block;), который открывает меню с первого прикосновения. Теперь меню открылось без загрузочного класса show. Если пользователь выбирает ссылку из выпадающего меню, она работает отлично. Но если пользователь решает закрыть меню, не используя его, он должен нажать два раза, чтобы закрыть меню: при первом нажатии исходный класс начальной загрузки "show" присоединяется, поэтому меню открывается снова, при втором нажатии меню закрывается из-за к нормальному поведению начальной загрузки (удаление класса 'show').
Чтобы предотвратить это, я использовал статью: https://codeburst.io/the-only-way-to-detect-touch-with-javascript-7791a3346685 (Дэвид Гилбертсон)
У него есть несколько очень удобных способов обнаружения сенсорных или парящих устройств.
Итак, объединил двух авторов с моим собственным jQuery:
$(window).one('mouseover', function(){
window.USER_CAN_HOVER = true;
if(USER_CAN_HOVER){
jQuery('#navbarNavDropdown ul li.dropdown').on("mouseover", function() {
var $parent = jQuery(this);
var $dropdown = $parent.children('ul');
$dropdown.show(200,function() {
$parent.mouseleave(function() {
var $this = jQuery(this);
$this.children('ul').fadeOut(200);
});
});
});
};
}); Проверьте один раз, если устройство позволяет событие зависания. Если это так, представьте возможность зависания, используя .show(). Если устройство не допускает события наведения мыши, функция .show() никогда не вводится, поэтому вы получаете естественное поведение при начальной загрузке на сенсорном устройстве.
Обязательно удалите все CSS, касающиеся классов при наведении меню.
У меня ушло три дня :), поэтому я надеюсь, что это поможет некоторым из вас.
Ответ 10
Hoverable выпадающий без потери функциональности popper.js только для начальной загрузки 4
Javascript
$('.dropdown-hoverable').hover(function(){
$(this).children('[data-toggle="dropdown"]').click();
}, function(){
$(this).children('[data-toggle="dropdown"]').click();
});
HTML
<nav class="nav">
<li class="nav-item dropdown dropdown-hoverable">
<a class="nav-link dropdown-toggle" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" href="#">Menu link</a>
<ul class="dropdown-menu">
</ul>
</li>
</nav>
Ответ 11
Это решение включается и выключается
<script>
$(document).ready(function() {
// close all dropdowns that are open
$('body').click(function(e) {
$('.nav-item.show').removeClass('show');
//$('.nav-item.clicked').removeClass('clicked');
$('.dropdown-menu.show').removeClass('show');
});
$('.nav-item').click( function(e) {
$(this).addClass('clicked')
});
// show dropdown for the link clicked
$('.nav-item').hover(function(e) {
if ($('.nav-item.show').length < 1) {
$('.nav-item.clicked').removeClass('clicked');
}
if ($('.nav-item.clicked').length < 1) {
$('.nav-item.show').removeClass('show');
$('.dropdown-menu.show').removeClass('show');
$dd = $(this).find('.dropdown-menu');
$dd.parent().addClass('show');
$dd.addClass('show');
}
});
});</script>
Чтобы отключить зависание для меню уменьшения размера lg, добавьте
if(( $(window).width() >= 992 )) {
Ответ 12
Я использую bootstrap 4.0.0, так как мы хотим смоделировать .show
для hover, это просто. просто добавьте все стили в .dropdown.show.dropdown-menu
к :hover
. как это:
.dropdown:hover>.dropdown-menu {
opacity: 1;
visibility: visible;
transform: translate3d(0px, 0px, 0px);
}
Ответ 13
1. Удалите атрибут data-toggle = "dropdown" (чтобы при нажатии не открылось выпадающее меню)
2. Добавьте псевдо-класс hover, чтобы отобразить раскрывающееся меню
.
.dropdown:hover .dropdown-menu {display: block;}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">Navbar</a>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="http://example.com" id="navbarDropdownMenuLink" aria-haspopup="true" aria-expanded="false">
Dropdown link
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
</ul>
</div>
</nav>
Ответ 14
$('body').on('mouseenter mouseleave','.dropdown',function(e){
var _d=$(e.target).closest('.dropdown');
if (e.type === 'mouseenter')_d.addClass('show');
setTimeout(function(){
_d.toggleClass('show', _d.is(':hover'));
$('[data-toggle="dropdown"]', _d).attr('aria-expanded',_d.is(':hover'));
},300);
});
/* this is not needed, just prevents page reload when a dd link is clicked */
$('.dropdown a').on('click tap', e => e.preventDefault())
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href>Navbar</a>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href>Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href>Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href>Pricing</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown link
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href>Action</a>
<a class="dropdown-item" href>Another action</a>
<a class="dropdown-item" href>Something else here</a>
</div>
</li>
</ul>
</div>
</nav>
Ответ 15
<div style="width: 100%; overflow: scroll;"><table class="table table-striped table-bordered" style="font-size:12px">