StuBlackett
StuBlackett

Reputation: 3857

Twitter Bootstrap Tabs href="#" anchor tag jumping

I am using TW Bootstrap's tabs to tab through content on my clients' site I have set the HTML Markup to remove the "data-toggle" as I need to intialise the jScrollpane library on click.

I have got this to work, However when you click one of the navigation icons the page jumps down.

How do I avoid this from happening?

My markup is as follows :

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();
    });

Like I say, How do I prevent the page content from "jumping" to the anchor? Many Thanks..

Upvotes: 13

Views: 37460

Answers (10)

Darth Sonic
Darth Sonic

Reputation: 105

I was calling history.pushState and setting window.location.hash within "shown.bs.tab" event and I had to change the order of the two calls:

    history.pushState(null, null, tabId);
    window.location.hash = tabId;

You need to set the window.location.hash after the history.pushState, otherwise the browser will jump to the anchor!

Upvotes: 0

Chris D&#39;Arcy Bean
Chris D&#39;Arcy Bean

Reputation: 21

I have found that the tabs will jump if the tab pane heights are different.

I ended up standardising the heights, for some reason, even in a flexbox grid vertical positioning has gremlins

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();

Upvotes: 1

Roman
Roman

Reputation: 1396

You can use <a data-target="#home"> instead of <a href="#home">

See here for an example:jsfiddle DEMO

Upvotes: 0

Dave
Dave

Reputation: 159

Using data-target instead of href seems to work with bootstrap 3 pills and tabs. If the mouse curser doesn't change due to the fact that there is no href attribute, then you could add a bit of css

EDIT: Code added as per request below, note lack of a target on the href and the addition of 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>

Upvotes: 15

DrinkBird
DrinkBird

Reputation: 834

Define your tab link like this:

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

and your tab itself like this:

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

Upvotes: 3

paulslater19
paulslater19

Reputation: 5917

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

Use e.preventDefault(). It prevents the default action (in this case, "navigating" to #)

Upvotes: 21

karpy47
karpy47

Reputation: 900

The selected answer did work for me, but I also discovered another solution. Simply remove the href-attribute, like in the example below...

<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>
    ...

Since the problem seems to be that the <a>-tag has "priority" over jQuery's action, just removing the href-attribute is enough. (<a>-tags without href-attribute are allowed by the way.)

In my case the original problem was frustrating to find, since it only showed in production environment and not in development (identical code). Couldn't find any difference between the pages in html or in linked resources... Anyway, this solved it.

Upvotes: 1

znn
znn

Reputation: 501

I have found a very simple solution. I just add another # in the tabs 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>

I don't know if it's the best solution, but for sure is quick and easy. In my case it works on Chrome and IE 10 and for my requirements it's enough.

Upvotes: 7

Saeid
Saeid

Reputation: 493

The answer from @paulslater19 didn't work for me. But, The following code did:

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

Tested on Bootstrap 3.2.0.

I've got this code from Twitter Bootstrap: How To Prevent Jump When Tabs Are Clicked.

UPDATE

The complete function for 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');
    });

Upvotes: 2

kalu
kalu

Reputation: 2682

The selected answer from @paulslater19 did not work for me. The following code did the trick:

<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>

Also see SO question 14185974.

Upvotes: 1

Related Questions