Фиксированного заголовка перекрывает странице в разделе анкеры


Если у меня есть заголовок без прокрутки на HTML-странице, закрепленный сверху, имеющий определенную высоту:

есть ли способ использовать привязку URL (#fragment часть), чтобы браузер прокручивался до определенной точки на странице, но все же уважал высоту фиксированного элемента без помощи JavaScript?

http://foo.com/#bar
WRONG (but the common behavior):         CORRECT:
+---------------------------------+      +---------------------------------+
| BAR///////////////////// header |      | //////////////////////// header |
+---------------------------------+      +---------------------------------+
| Here is the rest of the Text    |      | BAR                             |
| ...                             |      |                                 |
| ...                             |      | Here is the rest of the Text    |
| ...                             |      | ...                             |
+---------------------------------+      +---------------------------------+
26 234

26 ответов:

у меня была та же проблема. Я решил это, добавив класс к элементу привязки с высотой верхней панели в качестве значения padding-top.

<h1><a class="anchor" name="barlink">Bar</a></h1>

а потом просто css:

.anchor { padding-top: 90px; }

если вы не можете или не хотите устанавливать новый класс, добавьте фиксированную высоту ::before псевдо-элемент :target псевдо-класс в CSS:

:target::before {
  content: "";
  display: block;
  height: 60px; /* fixed header height*/
  margin: -60px 0 0; /* negative fixed header height */
}

или прокрутите страницу относительно :target С помощью jQuery:

var offset = $(':target').offset();
var scrollto = offset.top - 60; // minus fixed header height
$('html, body').animate({scrollTop:scrollto}, 0);

Я использую такой подход:

/* add class="jumptarget" to all targets. */

.jumptarget::before {
  content:"";
  display:block;
  height:50px; /* fixed header height*/
  margin:-50px 0 0; /* negative fixed header height */
}

Он добавляет невидимый элемент перед каждой целью. Он работает в IE8+.

вот еще решения: http://nicolasgallagher.com/jump-links-and-viewport-positioning/

Официальный Бутстрэп Принял Ответ:

*[id]:before { 
  display: block; 
  content: " "; 
  margin-top: -75px; // Set the Appropriate Height
  height: 75px; // Set the Appropriate Height
  visibility: hidden; 
}

кредиты

слияние

лучший способ, который я нашел, чтобы справиться с этой проблемой (заменить 65px с фиксированной высоты элемента):

div:target {
  padding-top: 65px; 
  margin-top: -65px;
}

Если вы не любите использовать цель селектор вы также можете сделать это таким образом:

.my-target {
    padding-top: 65px;
    margin-top: -65px;
}

Примечание: этот пример не будет работать, если целевой элемент имеет цвет фона, который отличается от своего родителя. например:

<div style="background-color:red;height:100px;"></div>
<div class="my-target" style="background-color:green;height:100px;"></div>

в этом случае зеленый цвет элемента my-target будет перезаписывать его Родительский красный элемент в 65px. Я не нашел чистого CSS-решения для решения этой проблемы, но если у вас нет другого цвета фона, это решение является лучшим.

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

так называя www.mydomain.com/page.html#foo с нуля будет не смещение вашей цели в текущем Chrome с любым из заданных решений CSS или JS решения.

есть еще и отчет об ошибке jQuery описание некоторых деталей проблемы.

решение

единственный вариант, который я нашел до сих пор, который действительно работает в Chrome, - это JavaScript, который не вызывается onDomReady, но с задержкой.

// set timeout onDomReady
$(function() {
    setTimeout(delayedFragmentTargetOffset, 500);
});

// add scroll offset to fragment target (if there is one)
function delayedFragmentTargetOffset(){
    var offset = $(':target').offset();
    if(offset){
        var scrollto = offset.top - 95; // minus fixed header height
        $('html, body').animate({scrollTop:scrollto}, 0);
    }
}

резюме

без задержки JS решения, вероятно, будут работать в Firefox, IE, Safari, но не в Chrome.

для Chrome / Safari / Firefox вы можете добавить display: block и использовать отрицательное поле для компенсации смещения, например:

a[name] {
    display: block;
    padding-top: 90px;
    margin-top: -90px;
}

см. пример http://codepen.io/swed/pen/RrZBJo

вы можете сделать это с помощью jQuery:

var offset = $('.target').offset();
var scrollto = offset.top - 50; // fixed_top_bar_height = 50px
$('html, body').animate({scrollTop:scrollto}, 0);

это работает для меня:

HTML ссылка на якорь:

<a href="#security">SECURITY</a>

привязки HTML:

<a name="security" class="anchor"></a>

CSS:

.anchor::before {
    content: "";
    display: block;
    margin-top: -50px;
    position: absolute;
}

вы можете попробовать это:

<style>
h1:target { padding-top: 50px; }
</style>

<a href="#bar">Go to bar</a>

<h1 id="bar">Bar</h1>

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

Я легко работаю с CSS и HTML, используя метод "anchor:before", упомянутый выше. Я думаю, что это работает лучше всего, потому что он не создает массивную прокладку между вашими дивами.

.anchor:before {
  content:"";
  display:block;
  height:60px; /* fixed header height*/
  margin:-60px 0 0; /* negative fixed header height */
}

это, кажется, не работает для первого div на странице, но вы можете противостоять этому, добавив дополнение к этому первому div.

#anchor-one{padding-top: 60px;}

вот рабочая скрипка:http://jsfiddle.net/FRpHE/24/

он чувствует себя несколько хакерским для моего пуристского ума, но в качестве css-единственного решения вы можете добавить дополнение к активному привязанному элементу с помощью :target селектор:

html, body {height:100%; min-height:100%; margin:0;}
body {min-height:200%;}
header {display:inline-block; position:fixed; font-size:1.5em; height:100px; top:0; left:0; right:0; line-height:100px; background:black; text-align:center;}
header a {color:#fff;}
section {padding:30px; margin:20px;}
section:first-of-type, section:target {padding-top:130px;}
<header><a href="#one">#One</a> <a href="#two">#two</a> <a href="#three">#three</a></header>
<section id="one"><h1>One</h1>Aenean lacinia bibendum nulla sed consectetur. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</section>
<section id="two"><h1>Two</h1>Aenean lacinia bibendum nulla sed consectetur. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</section>
<section id="three"><h1>Three</h1>Aenean lacinia bibendum nulla sed consectetur. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</section>

способ, который я нахожу самым чистым, следующий:

  #bar::before {
    display: block;
    content: " ";
    margin-top: -150px;
    height: 150px;
    visibility: hidden;
    pointer-events: none;
  }

у меня было много проблем со многими ответами здесь и в других местах, поскольку мои закладки были заголовками разделов на странице FAQ, поэтому смещение заголовка не помогло, так как остальная часть контента просто останется там, где она была. Поэтому я подумал, что отправлю сообщение.

то, что я в конечном итоге сделал, было составным из нескольких решений:

  1. CSS:

    .bookmark { margin-top:-120px; padding-bottom:120px; display:block; }

где "120px" - это ваша фиксированная высота заголовка (возможно, плюс некоторые маржа.)

  1. ссылка на закладку HTML:

    <a href="#01">What is your FAQ question again?</a>

  2. содержимое закладок HTML:

    <span class="bookmark" id="01"></span> <h3>What is your FAQ question again?</h3> <p>Some FAQ text, followed by ...</p> <p>... some more FAQ text, etc ...</p>

хорошая вещь об этом решении является то, что span элемент не только скрыт, он по существу свернут и не заполняет ваше содержимое.

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

вы можете увидеть фактический результат здесь.

Я обнаружил, что мне пришлось использовать иMutttenXdи Badabamрешения CSS вместе, так как первый не работал в Chrome, а второй не работал в Firefox:

a.anchor { 
  padding-top: 90px;
}

a.anchor:before { 
  display: block;
  content: "";
  height: 90px;
  margin-top: -90px;
}

<a class="anchor" name="shipping"></a><h2>Shipping (United States)</h2>
...

Я использую ответ @Jpsy, но по соображениям производительности я только устанавливаю таймер, если хэш присутствует в URL.

$(function() {
      // Only set the timer if you have a hash
      if(window.location.hash) {
        setTimeout(delayedFragmentTargetOffset, 500);
      }
  });

function delayedFragmentTargetOffset(){
      var offset = $(':target').offset();
      if(offset){
          var scrollto = offset.top - 80; // minus fixed header height
          $('html, body').animate({scrollTop:scrollto}, 0);
          $(':target').highlight();
      }
  };

минимально интрузивный подход с использованием jQuery:

ссылки:

<a href="#my-anchor-1" class="anchor-link">Go To Anchor 1</a>

содержание:

<h3 id="my-anchor-1">Here is Anchor 1</a>

сценарий:

$(".anchor-link").click(function() {
    var headerHeight = 120;
    $('html, body').stop(true, true).animate({
        scrollTop: $(this.hash).offset().top - headerHeight
    }, 750);
    return false;
});

назначая класс привязки к ссылкам, поведение других ссылок (например, аккордеон или элементы управления вкладками) не влияет.

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

<div style="position:relative; top:-45px;">
    <a name="fragment"> </a>
</div>

этот код должен делать трюк. Замените 45px на высоту вашего заголовка.

EDIT: если использование jQuery является опцией, я также успешно использовал jQuery.localScroll с установленным значением смещения. Опция offset является частью jQuery.scrollTo, который jQuery.localScroll построен на основе. Демо доступно здесь:http://demos.flesler.com/jquery/scrollTo/ (второе окно, под 'offset')

вот полное решение jquery, которое будет работать в IE:

предположим, что элементы панели навигации являются чем-то вроде этого:

<ul>
    <li><a class="navigation" href="/#contact-us">Contact us</a></li>
    <li><a class="navigation" href="/#about-us">About us</a></li>
</ul>

вы можете использовать следующий фрагмент jQuery для смещения прокрутки:

$(function() {
    $("a.navigation").click(function(event) {
        event.preventDefault();
        offSetScroll($(this));
    });
    offSetScrollFromLocation(window.location.href.toLowerCase());
});

function offSetScroll(anchor) {
    var href = anchor.attr("href");
    offSetScrollFromLocation(href);
}

function offSetScrollFromLocation(href) {
    //Change this according to the height of the navigation bar
    var fromTop = 250;
    if(href.indexOf("#")<=0)
        return;
    var hash=href.substring(href.indexOf("#"));
    var targetOffset = $(hash).offset().top-fromTop;
    $('html, body').animate({scrollTop: targetOffset}, 400, function(e) {

    });
}

реализовать с помощью :before работал отлично, пока мы не поняли, что псевдо-элемент на самом деле покрывает и блокирует события указателя, которые сидели внутри область псевдо элемента. Используя что-то вроде pointer-events: none на :before или даже непосредственно на якорь не повлияло.

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

Смещение Якоря без блокировки событий указателя

.section-marker {

    position: absolute;
    top: -300px;
}

значение с этим заключается в том, что мы не блокируем любые элементы, которые могут попасть в эти 300px. Недостатком является то, что захват позиции этого элемента из Javascript должен учитывать это смещение, поэтому любая логика должна быть скорректирована.

вот как я получил его, чтобы, наконец, перейти в нужное место, когда вы нажимаете на навигацию. Я добавил обработчик событий для навигации кликов. Затем вы можете просто использовать "scrollBy" для перемещения вверх по смещению.

var offset = 90;

 $('.navbar li a').click(function(event) {
    event.preventDefault();
    $($(this).attr('href'))[0].scrollIntoView();
    scrollBy(0, -offset);
 });
// handle hashes when page loads
// <http://stackoverflow.com/a/29853395>
function adjustAnchor() {
  const $anchor = $(':target');
  const fixedElementHeight = $('.navbar-fixed-top').outerHeight();
  if ($anchor.length > 0)
    window.scrollTo(0, $anchor.offset().top - fixedElementHeight);
}
$(window).on('hashchange load', adjustAnchor);
$('body').on('click', "a[href^='#']", function (ev) {
  if (window.location.hash === $(this).attr('href')) {
    ev.preventDefault();
    adjustAnchor();
  }
});

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

section {
   position: relative;
   border-top: 52px solid transparent; /* navbar height +2 */
   margin: -30px 0 0;
   -webkit-background-clip: padding-box;
   -moz-background-clip: padding;
   background-clip: padding-box;
}

section:before {
   content: "";
   position: absolute;
   top: -2px;
   left: 0;
   right: 0;
   border-top: 2px solid transparent;
}

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

источник: перейти ссылки и видового экрана позиционирования

  • протестировано на Firefox 45 и Chrome 52.
  • bootstrap версия: 3.3.7

для тех, кто не верит мне, я любезно подготовил jsfiddle с решение в нем:решение

CSS трюк будет обходным путем. Правильное решение, которое будет работать во всех сценариях, может быть реализовано с помощью jQuery.

см.https://codepen.io/pikeshmn/pen/mMxEdZ

подход: мы получаем высоту фиксированной навигации с помощью документ.getElementById ('header').offsetHeight И смещение прокрутки к этому значению.

var jump=function(e){  

e.preventDefault();                        //prevent "hard" jump
  var target = $(this).attr("href");       //get the target

      //perform animated scrolling
      $('html,body').animate(
        {
          scrollTop: $(target).offset().top - document.getElementById('header').offsetHeight - 5  //get top-position of target-element and set it as scroll target
        },1000,function()                  //scrolldelay: 1 seconds
        {
          location.hash = target;          //attach the hash (#jumptarget) to the pageurl
        });
      }

  $(document).ready(function()
  {
    $('a[href*="#"]').bind("click", jump); //get all hrefs
    return false;
  });

P. S:

  • оно включает славную разницу в 5 пикселов между заголовок и текст!--17-->
  • эффект прокрутки не жесткий, а гладкий; плавная прокрутка

добавить класс с "paddingtop", так что это работает;)

<h1><a class="paddingtop">Bar</a></h1>

а для css у вас есть:

    .paddingtop{ 
       padding-top: 90px; 
     }

очень простой ответ CSS только поставить это в верхней части таблицы стилей:

a{padding-top: 90px;}
a:link{padding-top: unset;}

первый стиль регулирует все теги привязки, где вторые стили привязывают теги с гиперссылкой.

Примечание: В настоящее время это работает в Firefox и Edge, но не в Chrome.