用于响应式(移动优先方法)下拉菜单/水平菜单的JavaScript

时间:2017-06-17 00:31:56

标签: javascript drop-down-menu navigation

我正在构建一个具有单一页面布局和移动优先方法的响应式网站。好吧,至少我在尝试,但菜单从一开始就很艰难。

我搜索了与我想要的结果相似的菜单片段并对其进行了调整,但到目前为止我只是失败了。我尝试了很多不同的代码,但这是我目前所拥有的。我可以理解为什么这不起作用,但我没有更多的想法。我真的需要一些帮助。



  $(function () {
        var handleMatchMedia = function(md) {
            if (md.matches) {
            // window width is at least 840px
                $(".nav-toggle").click(function () {
                $(this).next("div").slideToggle(250);
                });
            } else {
            // window width is less than 840px
                $(".nav-toggle").click(function () {
                $(this).parent().siblings().children().next().slideUp(250);
                $(this).next("div").delay(360).slideToggle(250);
                });
            }
        };
        var mq = window.matchMedia("(min-width: 840px)");

        handleMatchMedia(mq);
        mq.addListener(handleMatchMedia);
      });

header {
  background-color: #171717;
  top: 0;
  position: fixed;
  width: 100%;
  color: #ffffff;
  text-transform: uppercase;
  list-style-type: none;
  letter-spacing: 1px;
  z-index: 2; }
  header a {
    text-decoration: none;
    color: #9e9ea1; }
  header a:hover {
    border-bottom: 2px solid #ffffff;
    color: #ffffff;
    padding-bottom: calc(1.5rem/6);
    padding-bottom: 0.25rem; }
  header ::-moz-selection {
    background-color: #ffffff;
    color: #171717; }
  header ::selection {
    background-color: #ffffff;
    color: #171717; }

#nav-container {
  margin: 0 auto;
  max-width: calc((1.5rem*2*12) + (1.5rem*11));
  padding: calc(1.5rem/2) 1.5rem;
  height: calc(1.5rem*2); }

.navigation .nav-toggle span {
  cursor: pointer; }

.navigation .nav-list {
  display: none; }
  .navigation .nav-list ul {
    text-align: center;
    padding: calc(1.5rem/2) 0 1.5rem;
    top: calc(1.5rem*2);
    left: 0;
    right: 0;
    margin: 0 auto;
    position: absolute;
    background-color: #171717; }
    .navigation .nav-list ul li {
      padding: calc(1.5rem/2) 0;
      display: block; }

.navigation .nav-main {
  width: 66.66667%;
  float: left; }

@media all and (min-width: 940px) {
  .nav-main .nav-toggle {
    display: none; }
  .nav-main .nav-list {
    display: block; }
    .nav-main .nav-list ul {
      position: static;
      padding: 0; }
      .nav-main .nav-list ul li {
        display: inline-block;
        padding: 0 calc(1.5rem/2); }
        .nav-main .nav-list ul li:first-child {
          padding-left: 0; }
        .nav-main .nav-list ul li:last-child {
          padding-right: 0; }
  .nav-main .active {
    border-bottom: 2px solid #ffffff;
    color: #ffffff;
    padding-bottom: calc(1.5rem/6);
    padding-bottom: 0.25rem; } }

<header>
  <div id="nav-container">
    <div class="brand">
      <a href="#"><span><span>B</span>rand</span> Name</a>
    </div>
    <div class="navigation">
      <nav class="nav-main left">
        <div class="nav-toggle text-center">
          <span>Menu</span>
        </div>
        <div class="nav-list">
          <ul>
            <li>
              <a class="active" href="#home">Home</a>
            </li>
            <li>
              <a href="#bio">Bio</a>
            </li>
            <li>
              <a href="#portfolio">Portfolio</a>
            </li>
            <li>
              <a href="#contact">Contact</a>
            </li>
          </ul>
        </div>
      </nav>
    </div>
  </div>
</header>
&#13;
&#13;
&#13;

现在做什么(有时):

  • 下拉菜单&#34;闪烁&#34; /点击后直接向上滑动。
  • 菜单项不会始终显示在更大的屏幕上。

我希望它能做什么:

  • 作为标准的(关闭)下拉菜单,但更改为水平菜单 更大的屏幕。
  • 当用户点击&#39; a&#39;外面的跳跃链接 菜单,或在&#34;菜单按钮&#34;。

我是javascript的新手,所以请详细说明如何以及在哪里(最好也是为什么,我想学习:))

提前致谢!

编辑1
更改&lt; a href =&#34;#bio&#34;目标=&#34;空白&#34;&GT;生物&LT; / a&gt; &lt; a href =&#34;#bio&#34;&gt; Bio&lt; / A&GT;

1 个答案:

答案 0 :(得分:0)

正如其他用户所提到的,您可以使用像Bootstrap这样的UI组件库来为您处理这样的事情。但如果你不这样做(这很好),我们走了:

CodePen

我没有更改HTML和CSS中的任何内容,因此我们将保留这些内容。让我们关注JavaScript

$(function () {
  var breakPoint = 940;
  var $window = $(window)
  var collapseMenu = function() {
    if($window.width() < breakPoint) {
      $(".nav-list").slideToggle(250);  
    }  
  };

  $(".nav-toggle").click(collapseMenu)

  $(".nav-list a").click(collapseMenu)

  $(document).click(function (event) {
    console.log(!$(event.target).closest('.navigation').length);
    if(!$(event.target).closest('.navigation').length) {
      collapseMenu();
    }
  });

  var handleMatchMedia = function(md) {
    if(md.matches) {
       $(".nav-list").show();
    }
    else {
      $(".nav-list").hide();
    }
  };

  var mq = window.matchMedia("(min-width: " + breakPoint + "px)");
  handleMatchMedia(mq);
  mq.addListener(handleMatchMedia);
});

关闭手机中的菜单

为了在移动设备中关闭菜单,有几种情况需要解决。但首先,请注意,如果我知道自己处于移动布局中,我只会尝试切换。我确信有一种更高效的方式,但它可以实现这一概念。

  var collapseMenu = function() {
    if($window.width() < breakPoint) {
      $(".nav-list").slideToggle(250);  
    }  
  };

  $(".nav-toggle").click(collapseMenu)

  $(".nav-list a").click(collapseMenu)

  $(document).click(function (event) {
    console.log(!$(event.target).closest('.navigation').length);
    if(!$(event.target).closest('.navigation').length) {
      collapseMenu();
    }
  });

首先我们创建执行切换的函数,然后我们将该函数分配给我们希望菜单关闭的每个场景。前两个是非常自我解释的。但是让我们详细介绍第三种情况

$(document).click(function (event) {
  if(!$(event.target).closest('.navigation').length) {
      collapseMenu();
  }
});

由于我们想要点击菜单,如果他们点击菜单外的任何地方,这意味着我们需要将事件附加到整个文档。这将导致该功能触发页面上的每次点击。但是如果用户在菜单本身中单击,我们不希望折叠菜单,因此我们必须检查事件的目标以确保它不在菜单容器中。只有当它在导航容器之外时,它才会折叠菜单。

处理调整大小

您遇到的问题是,每次用户调整大小时都会添加一个点击事件。这就是为什么当您测试越来越多时,您会看到菜单显示和隐藏的次数越来越多。

var handleMatchMedia = function(md) {
  if(md.matches) {
    $(".nav-list").show();
  }
  else {
    $(".nav-list").hide();
  }
};

var mq = window.matchMedia("(min-width: " + breakPoint + "px)");
handleMatchMedia(mq);
mq.addListener(handleMatchMedia);

所以我所做的就是根据屏幕的宽度将其更改为显示或隐藏。这样,它只是在用户调整大小超过断点时将菜单设置为预期的初始状态。