У меня есть типичная выпадающая навигация, и я стараюсь, чтобы ссылки меню перетаскивания всегда были доступны и видимы:
<li><a href="#">Link 1</a>
<ul>
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
<li><a href="#">Link 3</a></li>
</ul>
</li>
<li><a href="#">Link 2</a>
<ul>
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a></li>
<li><a href="#">Link 3</a></li>
</ul>
</li>
<!-- etc. -->
</ul>
CSS действительно не является чем-то особенным (цвета и фоны удалены):
.dropdown,
.dropdown li,
.dropdown ul {
list-style:none;
margin:0;
padding:0;
}
.dropdown {
position:relative;
z-index:10000;
float:left;
width:100%;
}
.dropdown ul {
position:absolute;
top:100%;
visibility:hidden;
display:none;
width:16em;
}
.dropdown ul ul {
top:0;
left:100%;
}
.dropdown li {
position:relative;
float:left;
}
.dropdown li:hover{
z-index:910;
}
.dropdown ul:hover,
.dropdown li:hover > ul,
.dropdown a:hover + ul,
.dropdown a:focus + ul {
visibility:visible;
display:block;
}
.dropdown a {
display:block;
padding:1em 2em;
}
.dropdown ul li {
width:100%;
}
Существует неизвестное количество ссылок верхнего уровня (они созданы пользователем). Проблема, с которой я сталкиваюсь, заключается в том, что иногда меню переходов (которые идут вправо) выходят из экрана, если ссылка верхнего уровня находится слишком далеко вправо. Я добавил этот бит CSS для компенсации:
.dropdown > li:last-child ul { /* ...or use a class on the last link for IE */
right:0;
}
Теперь последний идет влево вместо экрана, что приятно, но есть несколько проблем:
- Мне не нужны эти стили для последней ссылки, так как она не всегда находится на краю экрана (например, если есть только 3 ссылки).
- Когда окно браузера изменяется, ссылки стекаются друг над другом (по дизайну). Иногда ссылки в середине последовательности заканчиваются на правом краю, а их выпадающие окна обрезаются.
- Иногда меню ссылок "рядом с последним" также выходит за пределы границы.
Измените размер панели в этой демонстрации, чтобы увидеть, что я имею в виду (красная область считается "вне экрана" ) http://jsfiddle.net/G7qfq/
Я боролся с этой досадной проблемой в течение многих лет и никогда не нашел удовлетворительного решения. Есть ли способ проверить, не исчезнет ли меню выпадающего меню, и если да, добавьте/удалите имя class
или что-то еще, чтобы я мог сохранить его на экране с помощью CSS?
Один ключ, который я могу использовать, состоит в том, что если меню выходит из экрана, оно всегда создает вертикальную полосу прокрутки в нижней части окна, но я не уверен, как использовать эти знания. Я пробовал принятый ответ на этот вопрос об обнаружении вертикальных полос прокрутки, но по какой-то причине он всегда возвращает true
и всегда добавляет класс "edge" (возможно, там проблема со временем?):
$(".dropdown li").on('mouseenter mouseleave', function (e) {
// Get the computed style of the body element
var cStyle = document.body.currentStyle||window.getComputedStyle(document.body, "");
// Check the overflow and overflowY properties for "auto" and "visible" values
hasVScroll = cStyle.overflow == "visible"
|| cStyle.overflowY == "visible"
|| (hasVScroll && cStyle.overflow == "auto")
|| (hasVScroll && cStyle.overflowY == "auto");
if (hasVScroll) {
$(this).addClass('edge');
} else {
$(this).removeClass('edge');
}
});
Демо с javascript: http://jsfiddle.net/G7qfq/2/
На самом деле, я не хочу видеть вертикальную полосу прокрутки даже в течение секунды секунды, поэтому я не уверен, что путь, плюс могут быть ложные срабатывания (полоса прокрутки по какой-то другой причине).
Я также попробовал решение в этом ответе, которое, как я признаю, я не совсем понимаю и не мог заставить его работать: http://jsfiddle.net/G7qfq/3/
$(".dropdown li").on('mouseenter mouseleave', function (e) {
var elm = $('ul:first', this);
var off = elm .offset();
var t = off.top;
var l = off.left;
var h = elm.height();
var w = elm.width();
var docH = $(window).height();
var docW = $(window).width();
var isEntirelyVisible = (t > 0 && l > 0 && t + h < docH && l+ w < docW);
if ( ! isEntirelyVisible ) {
$(this).addClass('edge');
} else {
$(this).removeClass('edge');
}
});
Я предполагаю, что для решения требуется javascript, и я использую jQuery, но у меня нет подсказки, как подойти к проблеме. Любые идеи?