Bootstrap切换开关动画的“X”图标

9

我想让导航栏中的水平线在页面缩小时变成“X”形动画。

我的导航栏代码如下:

<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
        <div class="container">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="index.html">Company</a>
            </div>
            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav navbar-right">
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">About<b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            <li>
                                <a href="about.html">About Us</a>
                            </li>
                            <li>
                                <a href="certification.html">Certification</a>
                            </li>
                            <li>
                                <a href="downloads.html">Download PDF</a>
                            </li>
                        </ul>
                    </li>
                    <li>
                        <a href="products.html">Products</a>
                    </li>
                    <li>
                        <a href="inquiry.html">Inquiry</a>
                    </li>
                    <li>
                        <a href="events.html">Events</a>
                    </li>
                    <li>
                        <a href="contact.html">Contact</a>
                    </li>
                    <li>
                        <a href="#">Login</a>
                    </li>
                </ul>
            </div>
            <!-- /.navbar-collapse -->
        </div>
        <!-- /.container -->
    </nav>

当我尝试使用这里所示的CSS时,它无法正常工作。我需要针对我的导航栏进行修改吗?我还注意到,当我添加CSS时,冒号会消失。
 &:hover {
    background: transparent !important;
  }

闭合的右花括号没有识别到对应的左花括号。我错过了什么吗?

你需要调整你的HTML,使其与你发布的示例相似。 - vanburen
5个回答

15

这是因为该教程使用了CSS预处理器Less,扩展了CSS语言。

但是,您只需要使用编译后的CSS,并进行一些更改即可。

在您的html中,添加一些类来区分每个条形图:

<span class="icon-bar top-bar"></span>
<span class="icon-bar middle-bar"></span>
<span class="icon-bar bottom-bar"></span>

此外,请使用类collapsed来初始化您的按钮,否则它会首先呈现为“X”。

然后添加编译后的CSS:

.navbar-toggle {
  border: none;
  background: transparent !important;
}
.navbar-toggle:hover {
  background: transparent !important;
}
.navbar-toggle .icon-bar {
  width: 22px;
  transition: all 0.2s;
}
.navbar-toggle .top-bar {
  transform: rotate(45deg);
  transform-origin: 10% 10%;
}
.navbar-toggle .middle-bar {
  opacity: 0;
}
.navbar-toggle .bottom-bar {
  transform: rotate(-45deg);
  transform-origin: 10% 90%;
}
.navbar-toggle.collapsed .top-bar {
  transform: rotate(0);
}
.navbar-toggle.collapsed .middle-bar {
  opacity: 1;
}
.navbar-toggle.collapsed .bottom-bar {
  transform: rotate(0);
}

现在它应该能够完美地工作了。

这是一个 JsFiddle:演示


你知道为什么我的“X”看起来有点不对吗?就像两个横杆没有在它们的中心相遇一样。 - user5306470
为什么只有宽度为22像素时才有效?我改成16像素后,发现很难穿过那两条线...!! - Micky
@Micky,你需要将该行翻译为旋转角度,大约为汉堡菜单宽度与X宽度之差的1/2,并且这些线条必须向垂直方向移动,距离大约为X高度与汉堡菜单图标高度之差的1/2。请参阅我的解释:https://dev59.com/BZfga4cB1Zd3GeqPC-xM#64265878 - Adonis Gaitatzis

10

这对我起了作用

理论

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">
            <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%,但是当您将线条放置到位并考虑到线条的高度(在此定义为3px)时,X成为20x20正方形。

在这种特定的实现中,我们将每条线的旋转点定义为左侧中心。这影响了我们抬起线条的程度,因为线条高约3px,它们分别会增加X高度的1.05px(即2.1/2=1.05px),或约为X高度的33%。

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

线条必须移动如此

自定义

X总是会形成一个正方形,因此要找出如何移动线条,只需知道 栏的宽度和高度以及结果汉堡图标的高度。

将这些数字代入以下方程:

方程

或者在代码中:

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)

赞同这个深入的回答,但我不明白为什么要引用jQuery,如果“CSS提供了所有必要的动画工具”。 - Hashim Aziz
1
@hashimAziz 我只包含了jQuery,因为Bootstrap喜欢它,可能是因为它的下拉菜单和警告框。这与代码演示无关。 - Adonis Gaitatzis

1
我成功地采用Adonis的优秀答案(去投票)来处理Bootstrap 5的导航栏示例之一,做了一些显著的更改:
  • 使用Bootstrap 5现有的navbar-toggler-icon span,只需要两个额外的span来表示图标条,而不是三个
  • 按钮需要具有collapsed类,以避免初始化为X而不是菜单
  • 加快了动画速度

考虑到这些变化,下面是在Bootstrap 5中实现动画汉堡菜单的反射标记:

<nav class="navbar navbar-expand-lg navbar-light bg-light collapsed" aria-label="Eighth navbar example">
    <div class="container">
        <a class="navbar-brand me-6 me-xl-7" href="#">Brand</a>
        <button class="navbar-toggler collapsed" type="button" data-bs-toggle="collapse" data-bs-target="navbarsExample07" aria-controls="navbarsExample07" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
            <span></span>
            <span></span>
        </button>

        <div class="collapse navbar-collapse" id="navbar-home">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <li class="nav-item mx-sm-1 mx-lg-2 mx-xl-3">
                    <a class="nav-link active" aria-current="page" href="#">Home</a>
                </li>
                <li class="nav-item mx-sm-1 mx-lg-2 mx-xl-3">
                    <a class="nav-link" href="#">Find My Car</a>
                </li>
                <li class="nav-item mx-sm-1 mx-lg-2 mx-xl-3">
                    <a class="nav-link" href="#">Frequently Asked Questions</a>
                </li>
                <li class="nav-item mx-sm-1 mx-lg-2 mx-xl-3">
                    <a class="nav-link" href="#">Testimonials</a>
                </li>
                <li class="nav-item mx-sm-1 mx-lg-2 mx-xl-3">
                    <a class="nav-link" href="#">Contact Us</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

还有CSS:

.navbar-toggler span {
    display: block;
    background-color: #000;
    height: 3px;
    width: 25px;
    margin-top: 5px;
    margin-bottom: 5px;
    position: relative;
    left: 0;
    opacity: 1;
    transition: all 0.2s ease-out;
    transform-origin: center left;
}

.navbar-toggler span:nth-child(1) {
    margin-top: 0.3em;
}

.navbar-toggler:not(.collapsed) span:nth-child(1) {
    transform: translate(15%, -33%) rotate(45deg);
}

.navbar-toggler:not(.collapsed) span:nth-child(2) {
    opacity: 0;
}

.navbar-toggler:not(.collapsed) span:nth-child(3) {
    transform: translate(15%, 33%) rotate(-45deg) ;
}

.navbar-toggler span:nth-child(1) {
    transform: translate(0%, 0%) rotate(0deg) ;
}

.navbar-toggler span:nth-child(2) {
    opacity: 1;
}
.navbar-toggler span:nth-child(3) {
    transform: translate(0%, 0%) rotate(0deg) ;
}

1
展示一下,这对我很有效,Bootstrap 5.0。 - Flávio

0

根据上面的答案,我对Bootstrap 5.1进行了适应。同时使用折叠和侧边栏。我使用了jQuery,但不是必需的。

按钮:

<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbar" aria-controls="offcanvasNavbar">
  <span></span><span></span><span></span>
</button>

JavaScript:

let $btn = $('.navbar-toggler');
$($btn.data('bs-target')).on('show.bs.collapse hide.bs.collapse show.bs.offcanvas hide.bs.offcanvas', function(){
    $btn.toggleClass('opened');
});

CSS:

.navbar-toggler {
    border: 0;
    box-shadow: none;
}
.navbar-toggler:focus {
    box-shadow: none;
}
.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.2s ease-out;
    transform-origin: left center;
}
.navbar-toggler span:nth-child(1) {
    margin-top: 0.3em;
}
.navbar-toggler:not(.opened) span:nth-child(1){
    transform: translate(0%, 0%) rotate(0deg) ;
}
.navbar-toggler:not(.opened) span:nth-child(2) {
    opacity: 1;
}
.navbar-toggler:not(.opened) span:nth-child(3) {
    transform: translate(0%, 0%) rotate(0deg) ;
}
.navbar-toggler span:nth-child(1) {
    transform: translate(15%, -33%) rotate(45deg);
}
.navbar-toggler span:nth-child(2) {
    opacity: 0;
}
.navbar-toggler span:nth-child(3) {
    transform: translate(15%, 33%) rotate(-45deg) ;
}

0
.navbar-toggle .icon-bar {
  width: 26px;
  height: 2px;
  transition: all 0.2s;
}

如果不行,尝试将宽度值调整在20px-26px的范围内。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接