【问题标题】:Bootstrap mobile menu icon change to x closeBootstrap 移动菜单图标更改为 x 关闭
【发布时间】:2015-03-30 14:28:09
【问题描述】:

编辑

@zim answer 使用 2020 CSS 轻松解决问题,更好地适用于 Bootstrap 4。

原始问题和选择的答案仍然有效且信息量很大。

原始问题

我希望,在移动视图中,菜单图标(在引导基本导航栏示例中使用类图标栏定义)更改为 X 形状(类似于此处发生的情况:https://www.mint.com 但不那么花哨(我只想用 X 替换 3 条条纹)。

目前我正在使用自定义 ID:#ChangeToggle

<button id="ChangeToggle" type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
</button>

以及以下 javascript 函数(我知道这是基本的,但我是新手):

<script>    
$('#ChangeToggle').click(function () {
    if($('#ChangeToggle span').hasClass('ToggleButton')) {
        $('#ChangeToggle').html('<span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>'); 
    }
    else {      
        $('#ChangeToggle').html('<span class="ToggleButton glyphicon glyphicon-remove"></span>'); 
    }
});
</script>

一切正常,唯一的问题是当我点击 X 图标时,菜单没有关闭。它仅在我单击它外部(按钮中的任何其他位置)时才会关闭。单击 X 图标时它所做的唯一一件事就是回到原来的 3 条条纹。

有人知道我做错了什么吗?

【问题讨论】:

    标签: javascript twitter-bootstrap navbar


    【解决方案1】:

    下面的代码可以帮助你解决这个问题。

    HTML:

    <div class="content">
    <h1>Mobile Navigation menu using css and jquery</h1>
    <div class="icons">
    <button class="icon">
    <span></span>
    <span></span>
    <span></span>
    </button>
    </div>
    </div>
    

    css:

    .btn {
    background-color: #ffd200;
    color: #00174f;
    display: inline-block;
    text-decoration: none;
    padding: 13px 30px;
    margin: 30px 0 0 0;
    border-radius: 3px;
    font-weight: bold;
    }
    .btn:hover {
    background-color: #fff;
    }
    .btn--transition {
    -webkit-transition: -webkit-transform 0.2s;
    -webkit-transition: all 200ms ease-in-out;
    transition: all 200ms ease-in-out;
    }
    :focus {
    outline: none;
    }
    .icons {
    margin: 50px 0;
    }
    .icon {
    margin: 0 30px 0 0;
    }
    
    .icon {
    background-color: #ff3000;
    border: 0;
    height: 79px;
    width: 79px;
    border-radius: 50%;
    cursor: pointer;
    position: relative;
    }
    .icon span {
    display: block;
    height: 5px;
    width: 33px;
    background-color: #ffffff;
    border-radius: 2px;
    position: absolute;
    left: 23px;
    -webkit-transition: -webkit-transform 0.3s;
    -webkit-transition: all 300ms ease-in-out;
    transition: all 300ms ease-in-out;
    }
    .icon span:first-child {
    top: 28px;
    }
    .icon span:nth-child(2) {
    top: 37px;
    }
    .icon span:last-child {
    top: 46px;
    }
    .icon--active span:first-child {
    -webkit-transform: rotate(45deg);
    -ms-transform: rotate(45deg);
    transform: rotate(45deg);
    position: absolute;
    top: 37px;
    }
    .icon--active span:last-child {
    -webkit-transform: rotate(-45deg);
    -ms-transform: rotate(-45deg);
    transform: rotate(-45deg);
    position: absolute;
    top: 37px;
    }
    .icon--active span:nth-child(2) {
    opacity: 0;
    }
    .icon--button {
    border-radius: 10px;
    }
    .icon-transition {
    -webkit-transition: -webkit-transform 0.3s;
    -webkit-transition: all 300ms ease-in-out;
    transition: all 300ms ease-in-out;
    }
    

    javascript

    <script>
    var animation = 'rubberBand';
    $('.icon').on('click', function () {
    $(this).toggleClass('icon--active');
    });
    $('.icon').on('click', function () {
    $(this).addClass('animated ' + animation).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () {
    $(this).removeClass('animated ' + animation);
    });
    });
    </script>
    

    这个sn-ps用于将移动图标更改为单击按钮时的关闭图标。

    【讨论】:

      【解决方案2】:

      这对我有用

      理论

      CSS 提供了所有必要的动画工具。基本上发生的事情是这样的:

      • 顶线和底线必须旋转以形成 X
      • 中间线必须消失

      X 将比汉堡线更高更窄,所以:

      • 顶线和中间线必须垂直向右移出以保持其中心

      应用

      /* Define the shape and color of the hamburger lines */
      .navbar-toggler span {
          display: block;
          background-color: #4f4f4f;
          height: 3px;
          width: 25px;
          margin-top: 5px;
          margin-bottom: 5px;
          position: relative;
          left: 0;
          opacity: 1;
          transition: all 0.35s ease-out;
          transform-origin: center left;
      }
      
      
      /* top line needs a little padding */
      .navbar-toggler span:nth-child(1) {
          margin-top: 0.3em;
      }
      
      /**
       * Animate collapse into X.
       */
      
      /* top line rotates 45 degrees clockwise and moves up and in a bit to close the center of the X in the center of the button */
      .navbar-toggler:not(.collapsed) span:nth-child(1) {
          transform: translate(15%, -33%) rotate(45deg);
      }
      /* center line goes transparent */
      .navbar-toggler:not(.collapsed) span:nth-child(2) {
          opacity: 0;
      }
      /* bottom line rotates 45 degrees counter clockwise, in, and down a bit to close the center of the X in the center of the button  */
      .navbar-toggler:not(.collapsed) span:nth-child(3) {
          transform: translate(15%, 33%) rotate(-45deg) ;
      }
      
      
      /**
       * Animate collapse open into hamburger menu
       */
      
      /* top line moves back to initial position and rotates back to 0 degrees */
      .navbar-toggler span:nth-child(1) {
          transform: translate(0%, 0%) rotate(0deg) ;
      }
      /* middle line goes back to regular color and opacity */
      .navbar-toggler span:nth-child(2) {
          opacity: 1;
      }
      /* bottom line goes back to initial position and rotates back to 0 degrees */
      .navbar-toggler span:nth-child(3) {
          transform: translate(0%, 0%) rotate(0deg) ;
      }
      <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
      <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>
      
      <!-- Bootstrap Navigation -->
      <nav class="navbar bg-light">
              <a class="navbar-toggler collapsed border-0" type="button" data-toggle="collapse" data-target="#collapsingNavbar">
                  <!-- these spans become the three lines -->
                  <span> </span>
                  <span> </span>
                  <span> </span>
              </a>
              <a class="navbar-brand" href="./">
                  Brand
              </a>
              <div class="collapse navbar-collapse" id="collapsingNavbar">
                  <ul class="nav navbar-nav">
                      <li class="nav-item">
                          <a class="nav-link" href="#">About</a>
                      </li>
                      <li class="nav-item">
                          <a class="nav-link" href="#">Contact</a>
                      </li>
                  </ul>
              </div>
      </nav>
      <main class="container">
          <h1>Content Here</h1>
          <p>Shrink the viewport if to expose the hamburger menu.</p>
      </main>

      是什么让它起作用

      具体来说,由于顶线和底线旋转 45 度形成 X,它们的中心线占宽度的 70%,因此它们必须向内移动 15%。这可以使用勾股定理来计算。

      碰巧的是,我们的汉堡菜单是 26x21 像素,或比高度宽 24%,但当您将线条移动到位并考虑线条的高度时,X 最终为 20x20 正方形(此处定义为 3px)。

      在这个特定的实现中,我们将每条线的旋转点定义为左中。这会影响我们向上移动线条的程度,因为线条大约有 3px 高,它们每条都增加了大约 (2.1/2)=1.05px 到 X 的高度,或者大约是 X 高度的 33%。

      因此,它们必须垂直向外移出 33%,以便两条线在 X 的中心相交并形成一个 20x20 像素的正方形。

      定制

      X 总是会变成一个正方形,所以要知道它们移动了多少,您只需要知道 &lt;span&gt; 条的宽度和高度以及生成的汉堡图标的高度。

      将这些数字代入这个等式:

      或者在代码中:

      const line_width = 26; // px
      const line_height = 3; // px
      const hamburger_height = 21; // px
      
      const x_width = x_height = 0.8 * line_width;
      const line_move_y_percent = 100 * (line_width - x_width) / (2 * line_height)
      const line_move_right_percent = 100 * (x_height - hamburger_height) / (2 * line_height)
      

      【讨论】:

        【解决方案3】:

        我尝试了@Zim 的解决方案,效果很好,谢谢分享。 我确实做了 2 处细微的调整:

        1. 我将border-0 更改为border-1 以在汉堡图片周围保留一个边框。
        2. 我在 div 上添加了背景颜色,因为 X 最终与我现有的背景颜色相似。

        【讨论】:

          【解决方案4】:

          Bootstrap 4.1 开始,“汉堡包”切换器不再是 &lt;span&gt; 标记,现在是单个 SVG 图标背景图像。

          因此,用一点 CSS 替换它是最简单的。然后,您可以使用其他字体图标(如 FontAwesome)或简单的“✖”字符...

             <button class="navbar-toggler collapsed border-0" type="button" data-toggle="collapse" data-target="#collapsingNavbar">
                  <span class="navbar-toggler-icon"></span>
                  <div class="close-icon py-1">✖</div>
             </button>
          
             /* hide close when burger shown */
             .navbar-toggler.collapsed .close-icon {
                display: none;
             }
          
             .navbar-toggler:not(.collapsed) .navbar-toggler-icon {
                display: inline;
             }
          

          Demo


          另一个选项是这个动画汉堡:
          https://codeply.com/p/L9HT5GaUtt

          【讨论】:

          • 稍微简单一点:您也可以将 ✖ 放在 .navbar-toggler-icon 本身中,并将其设置为透明(即 color: rgba(0,0,0,0))。然后,您可以使用 CSS :not(.collapsed) 规则将background-image: none 和颜色设置为您想要的任何东西,而不是隐藏图标。需要设置行高以使其居中。
          【解决方案5】:

          不需要通过css使用javascript也可以,请按照下面的代码。

          HTML

          <div class="navbar-header">
               <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                   <span class="icon-bar"></span>
                   <span class="icon-bar"></span>
                   <span class="icon-bar"></span>
               </button>
          </div>
          

          CSS(在 css 中使用 :not,它将执行更快的动画而不是 javascript)

          .navbar-toggle .icon-bar {
              position: relative;
              transition: all 200ms ease-in-out;
          }
          
          .navbar-toggle:not(.collapsed) .icon-bar:nth-of-type(1) {
              top: 6px;
              transform: rotate(45deg);
          }
          
          .navbar-toggle:not(.collapsed) .icon-bar:nth-of-type(2) {
              background-color: transparent;
          }
          
          .navbar-toggle:not(.collapsed) .icon-bar:nth-of-type(3) {
              top: -6px;
              transform: rotate(-45deg);
          }      
          

          【讨论】:

            【解决方案6】:

            Smart decision helped me in codepen

            HTML

            <div class="navbar-header">
                 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                     <span class="icon-bar"></span>
                     <span class="icon-bar"></span>
                     <span class="icon-bar"></span>
                 </button>
            </div>
            

            CSS

            .navbar-toggle .icon-bar:nth-of-type(2) {
                top: 1px;
            }
            .navbar-toggle .icon-bar {
                position: relative;
                transition: all 500ms ease-in-out;
            }
            .navbar-toggle.active .icon-bar:nth-of-type(1) {
                top: 6px;
                transform: rotate(45deg);
            }
            .navbar-toggle.active .icon-bar:nth-of-type(2) {
                background-color: transparent;
            }
            .navbar-toggle.active .icon-bar:nth-of-type(3) {
                top: -6px;
                transform: rotate(-45deg);
            }
            

            JS

            $(".navbar-toggle").on("click", function () {
                $(this).toggleClass("active");
            });
            

            【讨论】:

            • 谢谢,这个解决方案通过使用图标和 ng-click 帮助我解决了我遇到的问题,因为在某些情况下,它们 2 个图标交换时会延迟折叠时间。
            • 确实非常聪明的解决方案。竖起大拇指!
            【解决方案7】:

            您不需要 Javascript,CSS 会完成这项工作

            .navbar-toggle {
                .icon-bar {
                    transition: 300ms ease-in-out;
                    background-color: #fff;
                    position: relative;
                    width: 24px;
                    height: 3px;
                }
                .icon-bar:last-child {
                    -webkit-transform: rotate(-45deg);
                    -ms-transform: rotate(-45deg);
                    -o-transform: rotate(-45deg);
                    transform: rotate(-45deg);
                    top: -7px;
                }
                .icon-bar:nth-child(2) {
                    -webkit-transform: rotate(45deg);
                    -ms-transform: rotate(45deg);
                    -o-transform: rotate(45deg);
                    transform: rotate(45deg);
                    top: 0px;
                }
                .icon-bar:nth-child(3) {
                    opacity: 0;
                }
                &.collapsed {
                    .icon-bar {
                        -webkit-transform: rotate(0deg);
                        -ms-transform: rotate(0deg);
                        -o-transform: rotate(0deg);
                        transform: rotate(0deg);        
                        top: 0;
                        opacity: 1;
                    }
                }
            }
            

            【讨论】:

            • 2020 年更新:这仍然有效并且看起来很棒。 Bootstrap 在 4.0 中删除了 .icon-bar。所以你需要手动重新添加它来获得这个好看的动画: .navbar-toggler .icon-bar { display: block;宽度:22px;高度:2px;边框半径:1px; } .navbar-toggler .icon-bar + .icon-bar { margin-top: 4px; }
            【解决方案8】:

            您的 JavaScript 替换了 #ChangeToggle 元素的内部 html 以显示 X 或汉堡图标。精确单击 X 或汉堡菜单而不是 #ChangeToggle 将删除被单击的元素,我认为它可以防止它冒泡。由于 Bootstrap 的 collapse plugin 使用文档上的事件处理程序来确定是否已单击元素,因此折叠插件将永远不会收到通知。

            我创建了一个小示例,其中粉红色的.outer 区域上的点击处理程序替换了绿色的.inner 区域。请注意,单击粉红色区域(您的#ChangeToggle)将导致两个事件,而单击绿色区域(您的 X 图标)将导致一个事件。

            $(function() {
              $('.outer')
                .click(function() {
                  $('.outer').html('<div class="inner"></div>');
                  fired('.js-outer');
                });
            
              $(document).on('click', '.outer', function() {
                fired('.js-document');
              });
            });
            
            function fired(el) {
              $(el).addClass('event--fire');
              window.setTimeout(function() {
                $(el).removeClass('event--fire')
              }, 100);
            }
            body {
              font-family: Helvetica Neue, Helvetica, Arial;
            }
            .outer,
            .inner {
              display: inline-block;
              padding: 20px;
            }
            .outer {
              border: 1px solid #c66;
              background-color: #f99;
            }
            .inner {
              border: 1px solid #6c6;
              background-color: #9f9;
            }
            .event {
              margin: 10px 0;
            }
            .event::before {
              display: inline-block;
              content: '';
              border: 1px solid #ccc;
              padding: 10px;
              vertical-align: middle;
              margin-right: 10px;
            }
            .event--fire:before {
              background-color: #ff9;
            }
            <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
            
            
            <div class="outer">
              <div class="inner">
              </div>
            </div>
            
            <div class="event js-outer">Event fires on .outer</div>
            <div class="event js-document">Event fires on document</div>

            为您的导航栏解决此问题的最简单方法是隐藏/显示 X 或汉堡图标而不是替换。在下面的示例中,X 和汉堡图标都在 html 中,切换类 .hidden 用于显示正确的图标。

            $(function() {
              $('#ChangeToggle').click(function() {
                $('#navbar-hamburger').toggleClass('hidden');
                $('#navbar-close').toggleClass('hidden');  
              });
            });
            <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" />
            <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
            <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
            
            <nav class="navbar navbar-default">
              <div class="container-fluid">
                <!-- Brand and toggle get grouped for better mobile display -->
                <div class="navbar-header">
                  <button id="ChangeToggle" type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
                    <div id="navbar-hamburger">
                      <span class="sr-only">Toggle navigation</span>
                      <span class="icon-bar"></span>
                      <span class="icon-bar"></span>
                      <span class="icon-bar"></span>
                    </div>
                    <div id="navbar-close" class="hidden">
                      <span class="glyphicon glyphicon-remove"></span>
                    </div>
                  </button>
                  <a class="navbar-brand" href="#">Brand</a>
                </div>
            
                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                  <ul class="nav navbar-nav">
                    <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a>
                    </li>
                  </ul>
                </div>
              </div>
            </nav>

            您也可以使用the events fired by the collapse plugin 隐藏或显示正确的图标,而不是在 Bootstrap 的折叠插件旁边添加一个 jQuery 点击处理程序。使用shown.bs.collapse 事件显示X 图标,使用hidden.bs.collapse 事件显示汉堡图标。

            $(function() {
              
              $('#bs-example-navbar-collapse-1')
                .on('shown.bs.collapse', function() {
                  $('#navbar-hamburger').addClass('hidden');
                  $('#navbar-close').removeClass('hidden');    
                })
                .on('hidden.bs.collapse', function() {
                  $('#navbar-hamburger').removeClass('hidden');
                  $('#navbar-close').addClass('hidden');        
                });
              
            });
            #navbar-close {
              color: #888;
              width: 22px;
              height: 14px;
            }
            <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" />
            <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
            <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
            
            <nav class="navbar navbar-default">
              <div class="container-fluid">
                <!-- Brand and toggle get grouped for better mobile display -->
                <div class="navbar-header">
                  <button id="ChangeToggle" type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
                    <div id="navbar-hamburger">
                      <span class="sr-only">Toggle navigation</span>
                      <span class="icon-bar"></span>
                      <span class="icon-bar"></span>
                      <span class="icon-bar"></span>
                    </div>
                    <div id="navbar-close" class="hidden">
                      <span class="glyphicon glyphicon-remove"></span>
                    </div>
                  </button>
                  <a class="navbar-brand" href="#">Brand</a>
                </div>
            
                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                  <ul class="nav navbar-nav">
                    <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a>
                    </li>
                  </ul>
                </div>
              </div>
            </nav>

            【讨论】:

            • 谢谢,特别是对它为什么会这样的解释..!我真的很喜欢你的两个选项是多么简单明了。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-05-24
            • 2013-03-25
            • 1970-01-01
            • 1970-01-01
            • 2013-02-12
            • 2016-07-08
            • 2020-08-23
            相关资源
            最近更新 更多