【问题标题】:How to affect other elements when menu item is clicked单击菜单项时如何影响其他元素
【发布时间】:2021-06-30 03:20:18
【问题描述】:

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

  • “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。

唯一缺少的是

  • 让它在每次点击时保持打开状态(而不是打开和关闭)。我自己想通了。

  • 当单击除.behandlinger-meny.behandlinger-item 之外的任何其他位置时关闭(返回到高度0) @biberman 再次触发。

  • 此修复不适用于移动设备。 New question.

非常感谢,堆栈溢出!

【问题讨论】:

  • 你可以用JS来实现。
  • 感谢您提出更好问题的提示。edit在您的问题中添加stack snippet。所以你的问题包括minimal reproducible example
  • @Developer 谢谢。如果可能的话,我很想学习用 CSS 来做这件事
  • 您的主菜单在&lt;header&gt; 中,而您的子菜单在页面上的其他位置&lt;section&gt;。由于子菜单不在 html 流中,因此仅在您发布的 html 结构中使用 css 似乎是不可能的。 Javascript 是解决方案。

标签: html css css-selectors pseudo-class siblings


【解决方案1】:

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

【讨论】:

  • 谢谢!我现在已经关闭了它们。这很好,但我想当菜单项不再处于焦点时它不会自动收回?
  • 您的问题中没有关于焦点的内容,只是点击。所以请更准确(见stackoverflow.com/help/how-to-ask)...
  • 我希望用 CSS 来实现这一点,那么它就不用说了。但我很欣赏你的观点,我会努力更清楚我真正想要什么,而不仅仅是我想象的解决方案是什么样的
  • 感谢您的回复。如果有帮助:您可以将功能减少到最低限度并将其与onclick=""(在您的触发标签中)一起使用。它有点脏,但它可以工作......
  • 效果很好!太感谢了!您知道如何让它在移动设备上运行吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-17
  • 2019-09-19
  • 2021-04-14
  • 2013-05-07
  • 1970-01-01
  • 2011-05-29
  • 2019-01-27
相关资源
最近更新 更多