Как отключить "прыжок" якоря при загрузке страницы?

Я думаю, что это может быть невозможно, попробуй объяснить и как можно лучше. У меня есть страница, содержащая вкладки (jquery powered), управляемые следующим образом:

Я использую этот код, предоставленный другим пользователем из предыдущего вопроса.

<script type="text/javascript">
    $(function() {

     $('html, body').animate({scrollTop:0}); // this is my "fix"

        var tabContent = $(".tab_content");
        var tabs = $("#menu li");
        var hash = window.location.hash;
     tabContent.not(hash).hide();
        if(hash=="") {
      $('#tab1').fadeIn();
     }
        tabs.find('[href=' + hash + ']').parent().addClass('active');

        tabs.click(function() {
            $(this).addClass('active').siblings().removeClass('active');
            tabContent.hide();
            var activeTab = $(this).find("a").attr("href");

            $(activeTab).fadeIn();
           return false;
        });

    });
</script>

этот код отлично работает, когда я нажимаю на страницу "вкладки".

однако мне нужно привязать к невидимым вкладкам с других страниц - поэтому для этого код получает window.location.hash, а затем показывает соответствующую вкладку.

страница не "прыгает" на якорь из-за "return false".

это событие запускается только при событии клика. следовательно, если я нахожу "вкладки" с любой другой страницы, срабатывает эффект "прыжка". Для борьбы с этим я автоматически прокручиваю верхнюю часть страницы, но я предпочел бы, чтобы этого не произошло.

существует ли способ имитации "return false" при загрузке страницы, что предотвращает "переход" якоря.

надеюсь, что это достаточно ясно.

спасибо

Ответ 1

Не работает ли ваше исправление? Я не уверен, правильно ли понял вопрос - есть ли у вас демо-страница? Вы можете попробовать:

if (location.hash) {
  setTimeout(function() {

    window.scrollTo(0, 0);
  }, 1);
}

Изменить: проверено и работает в Firefox, IE и Chrome на Windows.
Изменить 2: переместить setTimeout() внутри блока if, реквизит @vsync.

Ответ 2

См. мой ответ здесь: Ответ на стоп-запрос

Хитрость заключается в том, чтобы просто удалить hashtag ASAP и сохранить его значение для вашего собственного использования:

Важно, чтобы вы не поместили эту часть кода в функции $() или $(window).load(), поскольку это было бы поздно, и браузер уже переместился в тег.

// store the hash (DON'T put this code inside the $() function, it has to be executed 
// right away before the browser can start scrolling!
var target = window.location.hash,
    target = target.replace('#', '');

// delete hash so the page won't scroll to it
window.location.hash = "";

// now whenever you are ready do whatever you want
// (in this case I use jQuery to scroll to the tag after the page has loaded)
$(window).on('load', function() {
    if (target) {
        $('html, body').animate({
            scrollTop: $("#" + target).offset().top
        }, 700, 'swing', function () {});
    }
});

Ответ 3

Существуют и другие способы отслеживания того, на какой вкладке вы находитесь; возможно, установление файла cookie или значение в скрытом поле и т.д. и т.д.

Я бы сказал, что если вы не хотите, чтобы страница переходила на загрузку, вам было бы лучше использовать один из этих других вариантов, а не хеш, потому что основной причиной использования хэша в предпочтении к ним является разрешение именно то, что вы хотите заблокировать.

Другой момент - страница не будет перескакивать, если ваши хеш-ссылки не совпадают с именами тегов в документе, поэтому, возможно, если вы хотите продолжать использовать хэш, вы можете манипулировать содержимым, чтобы теги были названы иначе. Если вы используете согласованный префикс, вы все равно сможете использовать Javascript для перехода между ними.

Надеюсь, что это поможет.

Ответ 4

Я использовал решение dave1010, но было немного нерешительно, когда я положил его в функцию $(). ready. Поэтому я сделал это: (не внутри $(). Ready)

    if (location.hash) {               // do the test straight away
        window.scrollTo(0, 0);         // execute it straight away
        setTimeout(function() {
            window.scrollTo(0, 0);     // run it a bit later also for browser compatibility
        }, 1);
    }

Ответ 5

  • Браузер переходит на <element id="abc" />, если в адресе есть http://site.com/#abc хэш, а элемент с id = "abc" видно. Таким образом, вы должны просто скрыть элемент по умолчанию: <element id="anchor" style="display: none" />. Если на странице нет видимого элемента с id = hash, браузер не будет прыгать.

  • Создайте script, который проверяет хэш в url, а затем находит и показывает элемент prrpopriate (который по умолчанию скрыт).

  • Отключить поведение по умолчанию "хэш-подобная ссылка", связав событие onclick с ссылкой и указать return false; в результате события onclick.

Когда я реализовал вкладки, я написал что-то вроде этого:

    <script>
    $(function () {         
        if (location.hash != "") {
            selectPersonalTab(location.hash);
        }
        else {
            selectPersonalTab("#cards");
        }
    });

    function selectPersonalTab(hash) {
        $("#personal li").removeClass("active");
        $("a[href$=" + hash + "]").closest("li").addClass("active");
        $("#personaldata > div").hide();
        location.hash = hash;
        $(hash).show();
    }

    $("#personal li a").click(function (e) {
        var t = e.target;
        if (t.href.indexOf("#") != -1) {
            var hash = t.href.substr(t.href.indexOf("#"));
            selectPersonalTab(hash);
            return false;
        }
    });
</script>

Ответ 6

грязный CSS только фиксируется, чтобы оставаться прокручиваемым каждый раз, когда используется якорь (не полезно, если вы все еще хотите использовать привязки для прокрутки, очень полезны для deeplinking):

.elementsWithAnchorIds::before {
   content: "";
   display: block;
   height: 9999px;
   margin-top: -9999px; //higher thin page height
}

Ответ 7

Ни один из ответов не работает достаточно хорошо для меня, я вижу, что страница прыгает на якорь, а затем на вершину для некоторых решений, некоторые ответы не работают вообще, возможно, вещи менялись годами. Надеюсь, моя функция кому-то поможет.

/**
 * Prevent automatic scrolling of page to anchor by browser after loading of page.
 * Do not call this function in $(...) or $(window).on('load', ...),
 * it should be called earlier, as soon as possible.
 */
function preventAnchorScroll() {
    var scrollToTop = function () {
        $(window).scrollTop(0);
    };
    if (window.location.hash) {
        // handler is executed at most once
        $(window).one('scroll', scrollToTop);
    }

    // make sure to release scroll 1 second after document readiness
    // to avoid negative UX
    $(function () {
        setTimeout(
            function () {
                $(window).off('scroll', scrollToTop);
            },
            1000
        );
    });
}

Ответ 8

Несмотря на то, что принятый ответ работает хорошо, я обнаружил это иногда, особенно на страницах с большими изображениями, которые полоска прокрутки скачет дико, используя

 window.scrollTo(0, 0);

Что может быть довольно отвлекающим для пользователя.

Решение, на котором я остановился в конце, на самом деле довольно простое, и что для использования другого идентификатора на целевом объекте, используемого в location.hash

Например:

Вот ссылка на другой странице

<a href="/page/with/tabs#tab2">Some info found in tab2 on tabs page</a>

Итак, конечно, если на странице вкладок есть элемент с идентификатором tab2, окно будет прыгать на него при загрузке.

Итак, вы можете добавить что-то к идентификатору, чтобы предотвратить его:

<div id="tab2-noScroll">tab2 content</div>

И затем вы можете добавить "-noScroll" в location.hash в javascript:

<script type="text/javascript">
    $(function() {

        var tabContent = $(".tab_content");
        var tabs = $("#menu li");
        var hash = window.location.hash;


     tabContent.not(hash + '-noScroll').hide();                           
        if(hash=="") {       //^ here
      $('#tab1-noScroll').fadeIn();
     }
        tabs.find('[href=' + hash + ']').parent().addClass('active');

        tabs.click(function() {
            $(this).addClass('active').siblings().removeClass('active');
            tabContent.hide();
            var activeTab = $(this).find("a").attr("href") + '-noScroll'; 
                                                               //^ and here

            $(activeTab).fadeIn();
           return false;
        });

    });
</script>

Ответ 9

Я думаю, что нашел способ для вкладок пользовательского интерфейса, не переделывая функциональность. До сих пор я не нашел никаких проблем.

    $( ".tabs" ).tabs();
    $( ".tabs" ).not(".noHash").bind("tabsshow", function(event, ui) { 
        window.location.hash = "tab_"+ui.tab.hash.replace(/#/,"");
        return false;
    });

    var selectedTabHash = window.location.hash.replace(/tab_/,"");
    var index = $( ".tabs li a" ).index($(".tabs li a[href='"+selectedTabHash+"']"));
    $( ".tabs" ).not(".noHash").tabs('select', index);

Все в рамках готового события. Он добавляет "tab_" для хеша, но работает как при щелчке, так и при загрузке страницы с хешем.

Ответ 10

В моем случае из-за использования якорной ссылки для всплывающего окна CSS я использовал этот способ:

Просто сначала сохраните страницу YOffset, а затем установите ScrollTop на это:

$(document).on('click','yourtarget',function(){
        var st=window.pageYOffset;
        $('html, body').animate({
                'scrollTop' : st
            });
});

Ответ 11

Другой подход

Попробуйте проверить, была ли прокручена страница и только reset позиция:

var scrolled = false;

$(window).scroll(function(){
  scrolled = true;
});

if ( window.location.hash && scrolled ) {
  $(window).scrollTop( 0 );
}

Heres demo

Ответ 12

У меня не было большого успеха с приведенными выше методами setTimeout в Firefox.

Вместо setTimeout я использовал функцию onload:

window.onload = function () {
    if (location.hash) {
        window.scrollTo(0, 0);
    }
};

Он все еще очень глючный, к сожалению.

Ответ 13

У меня не было последовательного успеха с этими решениями.

По-видимому, из-за того, что прыжок происходит до Javascript = > ссылка (http://forum.jquery.com/topic/preventing-anchor-jump)

Мое решение состоит в том, чтобы поместить все якоря вверху по умолчанию с помощью CSS.

.scroll-target{position:fixed;top:0;left:0;}

Затем используйте jquery для прокрутки к родительскому объекту целевого якоря или к брату (возможно, пустой тег em)

<a class="scroll-target" name="section3"></a><em>&nbsp</em>

Пример jquery для прокрутки для URL-адреса с хешем
(страница не должна быть уже загружена в окно/вкладку, это охватывает ссылки из других/внешних источников)

setTimeout(function() {
    if (window.location.hash) {               
        var hash = window.location.hash.substr(1);   
        var scrollPos = $('.scroll-target[name="'+hash+'"]').siblings('em').offset().top; 
        $("html, body").animate({ scrollTop: scrollPos }, 1000);    
    }
}, 1);

Также вы хотите предотвратить по умолчанию привязку кликов на странице, а затем прокрутить до своих целей.

<a class="scroll-to" href="#section3">section three</a>

и jquery

$('a.scroll-to').click(function(){
    var target = $(this).attr('href').substr(1);
    var scrollPos = $('.scroll-target[name="'+target+'"]').siblings('em').offset().top; 
    $("html, body").animate({ scrollTop: scrollPos }, 1000);
    return false;
});

Хорошая вещь об этом методе - цели привязки тега, остаются структурно рядом с соответствующим контентом, хотя их позиция CSS находится наверху.

Это должно означать, что поисковые роботы не будут иметь проблем.

Привет, я надеюсь, что это поможет
Серый

Ответ 14

Попробуйте, чтобы клиент не выполнял вертикальную прокрутку на hashchanged (внутри обработчика событий):

var sct = document.body.scrollTop;
document.location.hash = '#next'; // or other manipulation
document.body.scrollTop = sct;

(перерисовка браузера)

Ответ 15

Решил мой промлем, сделав это:

// navbar height 
var navHeigth = $('nav.navbar').height();    

// Scroll to anchor function
var scrollToAnchor = function(hash) {
  // If got a hash
  if (hash) {
    // Scroll to the top (prevention for Chrome)
    window.scrollTo(0, 0);
    // Anchor element
    var term = $(hash);

    // If element with hash id is defined
    if (term) {

      // Get top offset, including header height
      var scrollto = term.offset().top - navHeigth;

      // Capture id value
      var id = term.attr('id');
      // Capture name value
      var name = term.attr('name');

      // Remove attributes for FF scroll prevention
      term.removeAttr('id').removeAttr('name');
      // Scroll to element
      $('html, body').animate({scrollTop:scrollto}, 0);

      // Returning id and name after .5sec for the next scroll
      setTimeout(function() {
        term.attr('id', id).attr('name', name);
      }, 500);
    }
  }
};

// if we are opening the page by url
if (location.hash) {
  scrollToAnchor(location.hash);
}

// preventing default click on links with an anchor
$('a[href*="#"]').click(function(e) {
  e.preventDefault();
  // hash value
  var hash = this.href.substr(this.href.indexOf("#"));
  scrollToAnchor(hash);
});`

Ответ 16

Это будет работать с bootstrap v3

$(document).ready(function() {
  if ($('.nav-tabs').length) {
    var hash = window.location.hash;
    var hashEl = $('ul.nav a[href="' + hash + '"]');
    hash && hashEl.tab('show');

    $('.nav-tabs a').click(function(e) {
      e.preventDefault();
      $(this).tab('show');
      window.location.hash = this.hash;
    });

    // Change tab on hashchange
    window.addEventListener('hashchange', function() {
      var changedHash = window.location.hash;
      changedHash && $('ul.nav a[href="' + changedHash + '"]').tab('show');
    }, false);
  }
});
<link rel="stylesheet" href="#" onclick="location.href='https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css'; return false;">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<div class="container">
<ul class="nav nav-tabs">
  <li class="active"><a data-toggle="tab" href="#home">Home</a></li>
  <li><a data-toggle="tab" href="#menu1">Menu 1</a></li>
</ul>

<div class="tab-content">
  <div id="home" class="tab-pane fade in active">
    <h3>HOME</h3>
    <p>Some content.</p>
  </div>
  <div id="menu1" class="tab-pane fade">
    <h3>Menu 1</h3>
    <p>Some content in menu 1.</p>
  </div>
</div>
</div>