【发布时间】:2012-07-16 20:30:02
【问题描述】:
我有你典型的下拉导航,我正在努力确保下拉菜单链接始终可访问和可见:
<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 将其保留在屏幕上?
我可能使用的一个线索是,如果菜单确实离开屏幕,它总是会在窗口底部产生一个垂直滚动条,但我不确定如何使用这些知识.我尝试了this question关于检测垂直滚动条的公认答案,但由于某种原因,它总是返回true,并且总是添加“边缘”类(也许时间有问题?):
$(".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/
说真的,我不想看到垂直滚动条,哪怕是一瞬间,所以我不确定这是要走的路,而且可能会出现误报(滚动条出于其他原因)。
我也尝试了this answer 中的解决方案,我承认,我不太明白,无法让它工作: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,但我不知道如何解决该问题。有什么想法吗?
【问题讨论】:
-
stackoverflow.com/questions/1725508/… 这可能会有所帮助。
-
我会看看并更新我的结果,谢谢。再想一想,“滚动条检测”方法不是很好,如果有效,可能会导致误报(滚动条是另一个原因)。
-
是的,非常类似,除了顶级下拉菜单和可堆叠的导航项目(如果视口很小)。我会看看我是否可以挑选出该代码并找到有用的东西,感谢您理解我的问题。
-
@WesleyMurch - 有点老了。前段时间写的,最后没用。我确信有足够的空间进行更新和改进。希望对您有所帮助。
标签: javascript jquery html css