Ошибка JavaScript с scrollTo() в Chrome

Я пытаюсь создать веб-страницу с фиксированной панелью навигации вверху, которая покрывает содержимое внизу. При загрузке страницы с привязкой в ​​URL, нормальное поведение заключается в том, что страница прокручивает привязку до верхней части окна. Но тогда этот контент скрыт под панелью навигации. Поэтому я пытаюсь решить эту проблему с помощью JavaScript scrollTo(). Мое решение отлично работает с Firefox и Opera, но не в Chrome. Пожалуйста, попробуйте пример. Есть идеи, как исправить эту проблему в Chrome? Спасибо.

test.htm:

<!DOCTYPE HTML>
<html>
  <head>
    <title>Test</title>
    <meta charset='UTF-8'>
    <style type='text/css'>
      #navi { position:fixed; left:0; top:0; width:100%; height:100px; background-color:yellow; }
      #spacer { background-color:cyan; height:100px; }
      #spacer2 { height:1000px; }
      .style1 { background-color:green; height:200px; }
    </style>
    <script type='text/javascript'>
      /* <![CDATA[ */
      function scrollAnchor() {  // doesn't work in Chrome
        var y = document.getElementById(window.location.hash.substr(1)).offsetTop - 110;
        window.scrollTo(0, y);
        //alert(y);
      }
      /* ]]> */
    </script>
  </head>
  <body id='top' onload='scrollAnchor();'>
    <div id='navi'>
      <a href='./test2.htm'>Menu</a>
    </div>
    <div id='main'>
      <div id='spacer'></div>
      <h3 id='1'>Heading 1</h3><p class='style1'></p>
      <h3 id='2'>Heading 2</h3><p class='style1'></p>
      <h3 id='3'>Heading 3</h3><p class='style1'></p>
      <h3 id='4'>Heading 4</h3><p class='style1'></p>
      <h3 id='5'>Heading 5</h3><p class='style1'></p>
      <h3 id='6'>Heading 6</h3><p class='style1'></p>
      <div id='spacer2'></div>
    </div>
  </body>
</html>

Test2.htm:

<!DOCTYPE HTML>
<html>
  <head>
    <title>Test</title>
    <meta charset='UTF-8'>
  </head>
  <body>
    <a href='test.htm#1'>Heading 1</a>
    <a href='test.htm#2'>Heading 2</a>
    <a href='test.htm#3'>Heading 3</a>
    <a href='test.htm#4'>Heading 4</a>
    <a href='test.htm#5'>Heading 5</a>
    <a href='test.htm#6'>Heading 6</a>
  </body>
</html>

1 ответ

Решение

Chrome настолько быстр, что ваше действие scrollTo() срабатывает до того, как Chrome прокрутит событие html по умолчанию.

Дайте ему небольшую задержку с помощью

setTimeout(function() {window.scrollTo(0, y);},1)

Или просто не используйте фактический идентификатор элемента в качестве имени хеша

Вместо того, чтобы использовать

test.htm#6

использование

test.htm#link_6

тогда вы можете получить реальный идентификатор, сделав что-то вроде

window.location.hash.split('_')[1]

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

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

Это уже хорошо описано в /questions/44548388/smeschenie-html-yakorya-dlya-korrektirovki-na-fiksirovannyij-zagolovok/44548614#44548614.

Тогда ваш код будет выглядеть примерно так:

<div id='navi'>
  <a href='./test2.htm'>Menu</a>
</div>
<div id='main'>
  <div id='spacer'></div>
  <div class='article-wrapper'>
    <a class='anchor' id='1'></a>
    <h3 id='1'>Heading 1</h3><p class='style1'></p>
  </div>
  <div class='article-wrapper'>
    <a class='anchor' id='2'></a>
    <h3 id='2'>Heading 2</h3><p class='style1'></p>
  </div>
  ...
</div>
#navi {
  height: 50px;
}

#main a.anchor {
    display: block;
    position: relative;
    top: -50px;
    visibility: hidden;
}

Или используйте переменные CSS, чтобы удалить как можно больше тесной связи:

:root {
  --header-height: 50px;
}

#navi {
  height: var(--header-height);
}

#main a.anchor {
    display: block;
    position: relative;
    top: -var(--header-height);
    visibility: hidden;
}
Другие вопросы по тегам