问题描述
我创建了一个自定义非粘性子菜单,我希望在单击某个菜单项时显示该子菜单。单击时我将其滚动到位置,并且我决定使用 height 属性控制可见性。使用 CSS 执行此操作的正确方法是什么?
结构看起来像这样
#submenu {
height: 0;
overflow: hidden;
}
.submenu-trigger:focus~#submenu {
height: 134px !important;
}
<div id="wrapper">
<header>
<nav>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a class="submenu-trigger" href="#submenu">Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>
</header>
<!-- Placed outside to follow page scroll -->
<section>
<div id="submenu">
<nav>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
</ul>
</nav>
</div>
</section>
<main>
…
</main>
</div>
编辑:CSS 似乎无法做到这一点。当主菜单项不再处于焦点时,如何使用 JS 使子菜单收回?
编辑 2:在 biberman's suggestion 处实现了 @https://ensjotannklinikk.no/forside-wip/ 的变体。以下是现场版的不同之处:
-
“Behandlinger” = 相关菜单项
-
.behandlinger-meny
而不是#submenu
-
.behandlinger-item
而不是.submenu-trigger
-
55px
而不是auto
,以保留 CSS 过渡
document.querySelector('.behandlinger-item').addEventListener('click',function() {
var submenu = document.querySelector('.behandlinger-meny');
submenu.style.height = '55px';
});
非常接近,感谢@biberman。
唯一缺少的是
-
让它在每次点击时都保持打开状态(而不是打开和关闭)。我自己想。 -
点击其他位置时关闭(回到高度 0),但@biberman 再次罢工。.behandlinger-meny
和.behandlinger-item
-
此修复不适用于移动设备。 New question。
非常感谢,Stack Overflow!
解决方法
这可以使用 js 轻松完成(在脚本标记或单独的 js 文件中)。您只需要一个用于“单击”的事件侦听器和一个用于更改高度的小函数:
document.querySelector('.submenu-trigger').addEventListener('click',function() {
var submenu = document.querySelector('#submenu');
submenu.style.height = submenu.style.height == 'auto' ? 0 : 'auto';
});
#submenu {
height: 0;
overflow: hidden;
}
.submenu-trigger:focus ~ #submenu {
height: 134px !important;
}
<div id="wrapper">
<header>
<nav>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a class="submenu-trigger" href="#submenu">Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>
</header>
<section>
<div id="submenu">
<nav>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
</ul>
</nav>
</div>
</section>
<main>
…
</main>
</div>
如果您搜索一个没有额外 javascript 的解决方案,您可能可以将其减少到最低限度并内联进行。 (最好不要混合html结构和程序代码,但它有效):
#submenu {
height: 0;
overflow: hidden;
}
<div id="wrapper">
<header>
<nav>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a class="submenu-trigger" href="#submenu" onclick="document.querySelector('#submenu').style.height = (document.querySelector('#submenu').style.height == 'auto') ? '0' : 'auto';">Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>
</header>
<section>
<div id="submenu">
<nav>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
</ul>
</nav>
</div>
</section>
<main>
…
</main>
</div>
如果要在单击其他位置(不是 .submenu-trigger 和 #submenu)或按“Esc”时关闭菜单,则需要另外两个事件侦听器。但这不是内联的:
var submenu = document.querySelector('#submenu');
var menuTrigger = document.querySelector('.submenu-trigger');
function isChild(item,parentItem) {
while (item != undefined && item != null && item.tagName.toUpperCase() != 'BODY'){
if (item == parentItem){
return true;
}
item = item.parentNode;
}
return false;
}
menuTrigger.addEventListener('click',function() {
submenu.style.height = 'auto';
});
document.querySelector('body').addEventListener('click',function(e) {
if ( !isChild(e.target,menuTrigger) && !isChild(e.target,submenu) ) {
submenu.style.height = 0;
}
});
document.addEventListener('keyup',function(e) {
if ( e.key == 'Escape' ) {
submenu.style.height = 0;
}
});
#submenu {
height: 0;
width: 100px;
background-color: #ddd;
overflow: hidden;
}
<div id="wrapper">
<header>
<nav>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a class="submenu-trigger" href="#submenu">Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>
</header>
<section>
<div id="submenu">
<nav>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
</ul>
</nav>
</div>
</section>
<main>
...
</main>
</div>
jQuery 示例:
var submenu = $('#submenu');
$('.submenu-trigger').on('click',function() {
submenu.css('height','auto');
});
$('body').on('click',function(e) {
if (!$(e.target).is('.submenu-trigger') &&
!$(e.target).parents().is('#submenu')) {
submenu.css('height',0);
}
});
$(document).on('keyup',function(e) {
if (e.key == 'Escape') {
submenu.css('height',0);
}
});
#submenu {
height: 0;
width: 100px;
background-color: #ddd;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="wrapper">
<header>
<nav>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a class="submenu-trigger" href="#submenu">Item 3</a></li>
<li><a>Item 4</a></li>
</ul>
</nav>
</header>
<section>
<div id="submenu">
<nav>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
</ul>
</nav>
</div>
</section>
<main>
...
</main>
</div>