Исправлено перекрытие заголовка страницы внутри якоря страницы - PullRequest
279 голосов
/ 03 ноября 2010

Если на 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    |
| ...                             |      | ...                             |
+---------------------------------+      +---------------------------------+

Ответы [ 32 ]

206 голосов
/ 03 марта 2015

Если вы не можете или не хотите устанавливать новый класс, добавьте псевдоэлемент фиксированной высоты ::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);
129 голосов
/ 29 октября 2012

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

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

А затем просто css:

.anchor { padding-top: 90px; }
115 голосов
/ 08 марта 2012

Я использую этот подход:

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

36 голосов
/ 29 июня 2016

Официальный ответ принят Bootstrap:

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

Кредиты

Слияние

25 голосов
/ 06 октября 2014

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

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

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

.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 для решения этой проблемы, но если у вас нет другого цвета фона, это решение будет лучшим.

14 голосов
/ 17 февраля 2016

Хотя некоторые из предложенных решений работают для фрагментированных ссылок (= хеш-ссылок) на одной и той же странице (например, ссылка меню, которая прокручивается вниз), я обнаружил, что ни одна из них не работала в текущем 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.

8 голосов
/ 13 января 2016

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

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

См. Пример http://codepen.io/swed/pen/RrZBJo

6 голосов
/ 29 мая 2012

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

var offset = $('.target').offset();
var scrollto = offset.top - 50; // fixed_top_bar_height = 50px
$('html, body').animate({scrollTop:scrollto}, 0);
5 голосов
/ 01 марта 2012

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

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

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

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

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

5 голосов
/ 29 мая 2017

у меня работает:

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

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

HTML-привязка:

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

CSS:

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