首页 > 解决方案 > 单击菜单项时如何影响其他元素

问题描述

我创建了一个自定义非粘性子菜单,我希望在单击某个菜单项时显示该子菜单。单击时我将其滚动到位置,并且我决定要使用 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:在https://ensjotannklinikk.no/forside-wip/实施了@biberman 建议的变体。以下是现场版的不同之处:

    document.querySelector('.behandlinger-item').addEventListener('click', function() {
            var submenu = document.querySelector('.behandlinger-meny');
            submenu.style.height = '55px';
    });

真的很接近,感谢@biberman。

唯一缺少的是

非常感谢,堆栈溢出!

标签: htmlcsscss-selectorspseudo-classsiblings

解决方案


这可以通过 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>


推荐阅读