Twitter Bootstrap选项卡href="#"锚点跳转

13
我正在使用TW Bootstrap的标签页来切换客户网站上的内容,我已将HTML标记设置为删除"data-toggle",因为我需要在点击时初始化jScrollpane库。
我已经让它正常工作了,但是当您单击其中一个导航图标时,页面会跳下去。
我该如何避免这种情况发生?
我的标记如下:
HTML
<ul class="nav nav-tabs">
          <li class="home_tab active"><a href="#home"></a></li>
          <li class="about_tab"><a href="#about"></a></li>
          <li class="services_tab"><a href="#services"></a></li>
          <li class="cases_tab"><a href="#case_studies"></a></li>
          <li class="contact_tab"><a href="#contact_us"></a></li>
          <li class="news_tab"><a href="#news"></a></li>
</ul>

<div class="tab-content">
          <div id="home" class="tab-pane active scroll_tab">
            <?php if ( have_posts() ) while ( have_posts() ) : the_post(); ?>
            <h2>
              <?php the_title(); ?>
            </h2>
            <?php the_content(); ?>
            <?php endwhile; ?>
          </div>
          <div id="about" class="tab-pane">
            <?php 
                $page_id = 9; 
                $page_data = get_page( $page_id ); 
                echo '<h2>'. $page_data->post_title .'</h2>';// echo the title
                echo apply_filters('the_content', $page_data->post_content); // echo the content and retain Wordpress filters such as paragraph tags. 
            ?>
          </div>
          <div id="services" class="tab-pane">
          <div class="signs">
            <ul class="nav-tabs sub_tabs">
                <li class="roll_labels"><a data-toggle="tab" href="#roll_labels"></a></li>
                <li class="sheeted_labels"><a data-toggle="tab" href="#page1"></a></li>
                <li class="fanfold_labels"><a data-toggle="tab" href="#page1"></a></li>
                <li class="printers"><a data-toggle="tab" href="#page1"></a></li>
            </ul>
          </div>
            <?php 
                $page_id = 11; 
                $page_data = get_page( $page_id ); 
                echo '<h2>'. $page_data->post_title .'</h2>';// echo the title
            echo apply_filters('the_content', $page_data->post_content); // echo the content and retain Wordpress filters such as paragraph tags. 
        ?>
      </div>
      <div id="case_studies" class="tab-pane">
        <?php 
            $page_id = 13; 
            $page_data = get_page( $page_id ); 
            echo '<h2>'. $page_data->post_title .'</h2>';// echo the title
            echo apply_filters('the_content', $page_data->post_content); // echo the content and retain Wordpress filters such as paragraph tags. 
        ?>
      </div>
      <div id="contact_us" class="tab-pane">
        <?php 
            $page_id = 15; 
            $page_data = get_page( $page_id ); 
            echo '<h2>'. $page_data->post_title .'</h2>';// echo the title
            echo apply_filters('the_content', $page_data->post_content); // echo the content and retain Wordpress filters such as paragraph tags. 
        ?>
      </div>
      <div id="news" class="tab-pane">
        <?php 
            $page_id = 144; 
            $page_data = get_page( $page_id ); 
            echo '<h2>'. $page_data->post_title .'</h2>';// echo the title 
        ?>
        <?php
          // Load Latest Blog - Limited to 2 items                                         
          $recent = new WP_Query("tags=blog&showposts=2"); while($recent->have_posts()) : $recent->the_post();?>
      <div class="news_excerpt">
          <h3><?php the_title(); ?></h3>
          <p><?php echo limit_words(get_the_excerpt(), '40'); ?> ...</p>
          <a data-toggle="modal" href="#newsModal-<? the_ID(); ?>" id="newspopup">
                    <img src="<?php bloginfo( 'template_url' ); ?>/assets/img/content/team_read_more.png" alt="Read More" style="border:none;">
          </a>
          <div class="modal hide fade" id="newsModal-<? the_ID(); ?>">
            <div class="modal-header">
              <button data-dismiss="modal" class="close">×</button>
              <h3><?php the_title(); ?></h3>
            </div>
            <div class="modal-body">
                <p><?php the_post_thumbnail('news_image'); ?></p>
                <p><?php the_content(); ?></p>
            </div>
          </div>
          <?php endwhile; ?>
      </div>           
      </div>
      <div id="roll_labels" class="tab-pane">
        <?php 
            $page_id = 109; 
            $page_data = get_page( $page_id ); 
            echo '<h2>'. $page_data->post_title .'</h2>';// echo the title
            echo apply_filters('the_content', $page_data->post_content); // echo the content and retain Wordpress filters such as paragraph tags. 
        ?>
      </div>
    </div>

jQuery

$('.nav-tabs li a').click(function (e) {
        $(this).tab('show');
        $('.tab-content > .tab-pane.active').jScrollPane();
    });

就像我所说的,如何防止页面内容“跳转”到锚点?非常感谢。


如果任何一种解决方案都无法正常工作,您也可以在data-target中指定一个.class而不是#标识符。这样,您将完全跳过浏览器功能。 - Arie
10个回答

21
$('.nav-tabs li a').click(function (e) {
    e.preventDefault();
    $(this).tab('show');
    $('.tab-content > .tab-pane.active').jScrollPane();
});

使用e.preventDefault()。它可以阻止默认行为(在这种情况下,阻止跳转到#)


这个答案在Chrome上完美运行。然而,在Firefox上它不起作用。 - Aryo

15

使用 data-target 而不是 href 在 Bootstrap 3 的 pills 和 tabs 中似乎可行。如果由于没有 href 属性而导致鼠标光标未更改,则可以添加一些 css。

编辑: 根据下面的请求添加代码,注意 href 上缺少目标,并添加了 data-target="#...

      <ul class="nav nav-tabs" >
     <li class="active"><a href="#" data-target="#tab_id_1" data-toggle="tab"> Tab Name 1</a></li>
     <li><a href="#" data-target="#tab_id_2" data-toggle="tab"> Tab Name 2 </a></li>
    </ul>
     <div class="tab-content"> 
         <div id="tab_id_1" class="tab-pane active">
              CONTENT 1
          </div>
          <div id="tab_id_2" class="tab-pane">
              CONTENT 2
          </div>
    </div>

7
我找到了一个非常简单的解决方案。我只需要在选项卡的 href 属性中添加另一个 # 符号即可:
<ul class="nav nav-tabs">
          <li class="home_tab active"><a href="##home"></a></li>
          <li class="about_tab"><a href="##about"></a></li>
          <li class="services_tab"><a href="##services"></a></li>
          ...
</ul>

我不知道这是否是最好的解决方案,但肯定是快速且简单的。在我的情况下,它适用于Chrome和IE 10,并且对我的要求已经足够了。


对我有效的唯一解决方案。适用于Chrome、FF和IE。 - jeesus
这在页面内部很好地运作,但当我尝试通过在URL中添加“##tab-name”来链接到选项卡时,出现了问题...但这可能与我的代码有关-我认为我可能在某个地方覆盖了默认的选项卡行为-不确定。 - ryan2johnson9

3

按照以下方式定义您的标签链接:

<a data-target="#step1" data-toggle="tab">

并且按照以下方式定义您的标签本身:

<div class="tab-pane" id="step1">


1
我不明白为什么会被踩。这个解决方案对我来说很好用。 - Aureliano Far Suau
这对我来说是最好的Bootstrap答案。也没有控制台错误 - 我点了赞。 - DaniB

2

@paulslater19的答案对我没有用。但是,以下代码有效:

$('.nav-tabs li a').click( function(e) {
    history.pushState( null, null, $(this).attr('href') );
});

在Bootstrap 3.2.0上测试通过。

我从Twitter Bootstrap: How To Prevent Jump When Tabs Are Clicked中获取了这段代码。

更新

适用于bootstrap 3.2.0的完整函数:

$().ready(function () {
        // store the currently selected tab in the hash value
        $("ul.nav-tabs > li > a").click(function (e) {
            $(this).tab('show');
            history.pushState(null, null, $(e.target).attr("href"));
        });

        // on load of the page: switch to the currently selected tab
        $('ul.nav-tabs a[href="' + window.location.hash + '"]').tab('show');
    });

我想你的答案适用于较新版本的Bootstrap。在这里,检查回答的日期是关键。 - StuBlackett
这在Bootstrap 3.0和jQuery 2.0.3上对我不起作用。跳转停止了,但选项卡没有显示。尝试在history.pushState之后添加.tab('show'),但它只是重新创建了这种行为。 - Tofuwarrior
1
@Tofuwarrior,我已经编辑了完整的函数答案,适用于Bootstrap 3.2.0。 - Saeid

1
我发现如果选项卡面板的高度不同,选项卡会跳动。
最终我将高度标准化了,不知道为什么,即使在flexbox网格中,垂直定位也会出现问题。
function tabs_normalize() {
    var tabs = $('.tab-content .tab-pane'),
        heights = [],
        tallest;
    // check for tabs and create heights array
    if (tabs.length) {
        function set_heights() {
            tabs.each(function() {
                heights.push($(this).height()); 
            });
            tallest = Math.max.apply(null, heights);
            tabs.each(function() {
                $(this).css('min-height',tallest + 'px');
            });
        };
        set_heights();      
        // detect resize and rerun etc..
        $(window).on('resize orientationchange', function () {
            tallest = 0, heights.length = 0;
            tabs.each(function() {
                $(this).css('min-height','0'); 
            }); 
            set_heights();
        });
    }
}
tabs_normalize();

1

@paulslater19 提供的选定答案对我没用。以下代码解决了问题:

<script>
  $(document).ready(function() {
    var hash = window.location.hash;
    var link = $('a');
    $('.nav-tabs > li > a').click(function (e) {
      e.preventDefault();
      hash = link.attr("href");
      window.location = hash;
    });
  })
</script>

另请参见 SO问题14185974

1
所选答案对我有用,但我还发现了另一种解决方案。只需删除 href 属性,就像下面的示例一样...
<ul class="nav nav-tabs">
    <li class="home_tab active"><a></a></li>
    <li class="about_tab"><a></a></li>
    <li class="services_tab"><a></a></li>
    ...

由于问题似乎是<a>标签优先于jQuery的操作,只需删除href属性即可。 (顺便说一句,不带href属性的<a>标签是允许的。)

在我遇到的情况中,原始问题很令人沮丧,因为它只在生产环境中显示,而不在开发环境中显示(代码相同)。无法找到页面或链接资源之间的任何差异...无论如何,这解决了它。


0

你可以使用 <a data-target="#home"> 代替 <a href="#home">

这里有一个例子:jsfiddle DEMO


0
我在"shown.bs.tab"事件中调用了history.pushState并设置了window.location.hash,我不得不改变这两个调用的顺序。
    history.pushState(null, null, tabId);
    window.location.hash = tabId;

在使用 history.pushState 后,你需要设置 window.location.hash,否则浏览器会跳转到锚点!

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