Исправлено перекрытие заголовка страницы внутри якоря страницы

359

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

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

http://foo.com/#bar
НЕПРАВИЛЬНО (но обычное поведение): ПРАВИЛЬНО:
+ --------------------------------- + + -------------- ------------------- +
| БАР ///////////////////// header | | //////////////////////// header |
+ --------------------------------- + + -------------- ------------------- +
| Вот остальная часть текста | | БАР |
| ... | | |
| ... | | Вот остальная часть текста |
| ... | | ... |
+ --------------------------------- + + -------------- ------------------- +
Томалак
источник
3
Связанный: stackoverflow.com/questions/10732690/…
0fnt
3
@ax ДА, это лучший ответ. Также проверьте nicolasgallagher.com/jump-links-and-viewport-positioning/demo внутри него. Это лучше всего сработало для меня:.dislocate50px, #bar { padding: 50px 0 0; margin: -50px 0 0; -webkit-background-clip: content-box; background-clip: content-box; }
17
я ищу решение, которое * работает для якорей, приходящих с той же страницы или другой страницы *, и которое настраивает нажатие клавиши вниз страницы, так что содержимое не обрезается заголовком *, и которое позволяет нижнему колонтитулу sib-div прокрутите вверх с помощью content-div. Решение еще не найдено! Но я должен сказать, я думаю, что правильный путь будет нацелен на весь контент div, а не на каждого отдельного якоря. stackoverflow.com/questions/51070758/…
Джонни, почему
@ax. У CSS-tricks.com есть намного лучшая новая статья о scroll-padding-topздесь: css-tricks.com/… Соответствующий ответ: stackoverflow.com/a/56467997/247696
Flimm

Ответы:

167

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

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

А потом просто CSS:

.anchor { padding-top: 90px; }
MutttenXd
источник
19
@ Tomalak Имейте в виду, что это решение делает ссылки внутри области заполнения неактивными. Чтобы это исправить, вы должны использовать z-index и установить значение ссылки выше, чем у якоря. Помните, что верхняя панель должна иметь самое высокое значение z-index, чтобы содержимое страницы не перемещалось поверх верхней панели при прокрутке.
MutttenXd
Не работал в Chrome v28 из-за ошибки фиксированного положения WebKit, из-за которой заголовок исчезал. Этот ответ помог мне.
Knickedi
2
MuttenXd .. ты мой герой. У меня была странная проблема нефункциональной ссылки на моем сайте (не связанная с якорями), которая сводила меня с ума. Ваш не кликабельный комментарий действительно помог. Я должен тебе большой!
zipzit
9
Как предложено в ответе Роя Шоа, добавьте, margin-top: -90px;чтобы противостоять пробелу, создаваемому заполнением.
Скиппи ле Гран Гуру
37
Я использовал .anchor:target {padding-top: 90px;}так, чтобы он добавлял отступ, только когда они использовали тег привязки. Таким образом, не всегда есть куча отступов, если страница загружается сверху. Только когда он загружает эту конкретную точку ниже на странице.
jimmyplaysdrums
265

Если вы не можете или не хотите устанавливать новый класс, добавьте псевдоэлемент фиксированной высоты ::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);
Адриан Гарнер
источник
30
Мне очень нравится ваше решение. Это самое чистое решение, которое я нашел.
Итай Грудев
5
Это решение, которое отлично сработало для меня, не добавляя ничего в макет моей страницы.
Джейми Карл
2
Решение CSS имеет проблему при использовании со списком в WebKit. Смотрите: stackoverflow.com/questions/39547773/…
Мерт С. Каплан
14
Это не будет работать, если у цели есть верхний отступ или граница, так как она полагается на срыв полей.
Крулик
9
:targetбыл просто великолепен!
Бесконечный
125

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

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

Иеремия Эрбс
источник
посмотрите на ссылку, предоставленную Badabam, есть второе решение, которое я использую и которое работает в Chrome и Firefox
scavenger
Протестировал это на последнем Firefox (55.0.3 на ПК) и теперь он работает. :-)
RachieVee
46

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

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

кредиты

Объединить

blnc
источник
1
Большое спасибо за это, +1 за полноту.
amjoconn
2
Это решение имеет проблему при использовании со списком в WebKit. Смотрите: stackoverflow.com/questions/39547773/…
Мерт С. Каплан
Обратите внимание, что это не будет работать, если сам целевой элемент имеет display: flex;или padding-top. В <a name="my_link">{leave this empty}</a>этих случаях используйте выделенный элемент привязки (например ).
ВудроШигеру
Это не сработает, если целевой элемент <tr>
Иван Гусев
42
html {
  scroll-padding-top: 70px; /* height of sticky header */
}

от: https://css-tricks.com/fixed-headers-on-page-links-and-overlapping-content-oh-my/

Франсуа Ромен
источник
Поддержка браузера: caniuse.com/#feat=mdn-css_properties_scroll-padding-top
Flimm
Работает для меня. Я перехожу на якорь с другой страницы. Другие не работали. Спасибо!
Давидлопер
1
Это не работает для прокрутки всей страницы в Edge и Safari ( bugs.webkit.org/show_bug.cgi?id=179379 ).
Юлиуш
1
Спаситель! Просто, по сути. Ни одно из других решений не помогло мне, потому что я использую display: flex. Огромное спасибо, это было очень сложно попробовать все решения.
Прия Паявула
Это КРАСИВОЕ решение, я использовал скролл-поведение: плавный! Важный; Также якорь, очень просто в две строки кода
Yehanny
30

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

Рой Шоа
источник
2
Из всех ответов это единственный, который сработал для меня!
Хавьер Ариас
18

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

Jpsy
источник
3
Я пришел к такому же выводу и решению. Кажется, что все остальные забывают о внешних ссылках, которые используют хэштеги.
AJJ
У меня есть эта проблема сегодня, и я использовал ваше решение. Хотя кажется, что вам не нужен тайм-аут. Это работает как IIFE, а также.
kwiat1990
1
@ kwiat1990: Да, это возможно, но только если ваш JS находится в самом конце HTML-кода. В противном случае ваша цель прокрутки может быть еще не в DOM. На самом деле в этом весь смысл использования onDomReady. Так что я думаю, что версия с тайм-аутом - это стабильный путь.
Jpsy
Этот ответ был единственным, который работал для внешних ссылок. Однако это не работает для меня, когда ссылка называется на той же странице :( Есть идеи?
Аугусто Самаме Барриентос
@ Августо ты нашел решение? У меня такая же проблема.
Джесси
9

Когда в игру вступает спецификация CSS Scroll Snap , это легко сделать с помощью scroll-margin-topсвойства. В настоящее время работает на Chrome и Opera (апрель 2019). Также Safari 11+ должен поддерживать это, но я не смог запустить его на Safari 11. Вероятно, нам нужно подождать, пока парни не исправят это.

Пример Codepen

body {
  padding: 0;
  margin: 0;
}

h1,
p {
  max-width: 40rem;
  margin-left: auto;
  margin-right: auto;
}
h1 {
  scroll-margin-top: 6rem; /* One line solution. :-) */
}
.header {
  position: sticky;
  top: 0;
  background-color: red;
  text-align: center;
  padding: 1rem;
}
.header .scroll {
  display: block;
  color: white;
  margin-bottom: 0.5rem;
}
.header .browsers {
  color: black;
  font-size: 0.8em;
}
<header class="header">
  <a class="scroll" href="#heading">Scroll to heading</a>
  <span class="browsers" >Chrome 69+, Opera 56+ and Safari 11+ only</span>
</header>
<p>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</p>
<h1 id="heading">What is Lorem Ipsum?</h1>
<p>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</p>
<p>
  

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent pulvinar eleifend dolor, in cursus augue interdum quis. Morbi volutpat pulvinar nisl et condimentum. Quisque elit lacus, egestas non ante sit amet, hendrerit commodo dui. Nunc ac sagittis dolor. Proin iaculis ante non est pharetra, et ullamcorper nisl accumsan. Aenean quis leo vel sapien eleifend aliquam. Pellentesque finibus dui ex, blandit tristique risus vestibulum vitae. Nam a quam ac turpis porta eleifend. Sed at hendrerit risus, ac efficitur ante. Aenean pretium justo feugiat condimentum consectetur. Etiam mattis urna id porta hendrerit.
</p>
<p>
Mauris venenatis quam sed egestas auctor. Fusce lacus eros, condimentum nec quam vel, malesuada gravida libero. Praesent vel sollicitudin justo. Donec mattis nisl id mauris scelerisque, quis placerat lectus scelerisque. Ut id justo a magna mattis luctus. Suspendisse massa est, pretium vel suscipit sit amet, iaculis at mi. Aenean vulputate ipsum non consectetur sodales. Proin aliquet erat nec mi eleifend, eu dapibus enim ultrices. Sed fringilla tortor ac rhoncus consectetur. Aliquam aliquam orci ultrices tortor bibendum facilisis.
</p>
<p>
Donec ultrices diam quam, non tincidunt purus scelerisque aliquam. Nam pretium interdum lacinia. Donec sit amet diam odio. Donec eleifend nibh ut arcu dictum, in vulputate magna malesuada. Nam id dignissim tortor. Suspendisse commodo, nunc sit amet blandit laoreet, turpis nibh rhoncus mi, et finibus nisi diam sed erat. Vivamus diam arcu, placerat in ultrices eu, porta ut tellus. Aliquam vel nisi nisi.
</p>
<p>
Integer ornare finibus sem, eget vulputate lacus ultrices ac. Vivamus aliquam arcu sit amet urna facilisis consectetur. Sed molestie dolor et tortor elementum, nec bibendum tortor cursus. Nulla ipsum nulla, luctus nec fringilla id, sagittis et sem. Etiam at dolor in libero pharetra consequat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse quis turpis non diam mattis varius. Praesent at gravida mi. Etiam suscipit blandit dolor, nec convallis lectus mattis vitae. Mauris placerat erat ipsum, vitae interdum mauris consequat quis. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
Nunc efficitur scelerisque elit. Integer ac massa ipsum. Cras volutpat nulla purus, quis molestie dolor iaculis eget. Maecenas ut ex nulla. Pellentesque sem augue, ornare ut arcu eu, porttitor consectetur orci. Aenean iaculis blandit quam, in efficitur justo sodales auctor. Vivamus dignissim pellentesque risus eget consequat. Pellentesque sit amet nisi in urna convallis egestas vitae nec mauris. 
</p>

dakur
источник
1
Это довольно мило. Будем надеяться, что оно получит более широкое распространение!
Томалак
В чем разница между scroll-padding-topи scroll-margin-top?
Flimm
scroll-margin-topдля этого варианта
fabb
В Safari это называется scroll-snap-margin-top: caniuse.com/#search=scroll-margin-top
Му-
@ Mu-TsunTsai Это немного сложнее. Это действительно существует в Safari, но оно не работает с поведением прокрутки к фрагменту. Смотрите мой комментарий в проблеме с браузерными данными: github.com/mdn/browser-compat-data/issues/…
dakur
8

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

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

Смотрите пример http://codepen.io/swed/pen/RrZBJo

MrSwed
источник
7

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

var offset = $('.target').offset();
var scrollto = offset.top - 50; // fixed_top_bar_height = 50px
$('html, body').animate({scrollTop:scrollto}, 0);
webvitaly
источник
Не ".target", должно быть ": target"
Мерт С. Каплан
@ MertS.Kaplan ".target" - это класс 'target'.
webvitaly 19.09.16
7

Просто обнаружил еще одно чистое CSS-решение, которое для меня сработало!

html {
  scroll-padding-top: 80px; /* height of your sticky header */
}

Нашел на этом сайте !

jamawe
источник
2
Несколько другие обнаружили это решение , прежде чем, увидеть ответы на странице 1, например stackoverflow.com/a/56467997/18771
Томалак
Извините, не заметил! Спасибо!
Джамав
Это не работает для прокрутки всей страницы в Edge и Safari ( bugs.webkit.org/show_bug.cgi?id=179379 ).
Юлиуш
5

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

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

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

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

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

ygoe
источник
Миллигенри Неплохо, но все же довольно взломано (и не работает в IE, к сожалению).
Томалак
5

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

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

Эрик Вуд
источник
5

Меня устраивает:

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

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

Якорь HTML:

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

CSS:

.anchor::before {
    content: "";
    display: block;
    margin-top: -50px;
    position: absolute;
}
Avila
источник
5

Мне не повезло с ответом, перечисленным выше, и я решил использовать это решение, которое отлично сработало ...

Создайте пустой промежуток, где вы хотите установить свой якорь.

<span class="anchor" id="section1"></span>
<div class="section"></div>

И применить следующий класс:

.anchor {
  display: block;
  height: 115px;       /* same height as header */
  margin-top: -115px;  /* same height as header */
  visibility: hidden;
}

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

Мэтт Андервуд
источник
1
Разве это не тот же метод, который Гийом Ле Мьер и некоторые другие показали в этой теме?
Томалак
Это очень похоже, но я думаю, что это легче понять и более подробный ответ с еще более углубленной ссылкой на внешний источник.
Мэтт Андервуд
Это то же самое решение, но я могу легко понять и следовать этому. Другие не дали мне достаточно информации.
MacroMan
4

Я использую ответ @ 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();
      }
  };
sandre89
источник
ОП попросил не использовать JavaScript.
Джулио Качин
Работает с внешними ссылками, но не со ссылками на странице.
оснастка
4

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

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

  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элемент не только скрыт, он по существу свернут и не дополняет ваш контент.

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

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

SteveCinq
источник
1
Спасибо вам большое за обмен! Как ни крути, но до сих пор не существует единственного канонического решения этой проблемы.
Томалак
1
+ SteveCinq Вы прочитали мои мысли - я столкнулся с теми же проблемами, когда общие решения не работали, как и предполагалось. Добавление в <span>с якорем в промежутке, наряду с добавлением в padding и margin работал для меня. Большое спасибо, что нашли время, чтобы представить этот ответ, несмотря на возраст темы!
Twknab
3

Мне кажется, что это немного странно, но в качестве решения только для 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>

Moob
источник
1
Это совсем не так! Хорошее решение.
Томалак
3

Я нашел , что я должен был использовать как MutttenXd «s и Badabam » CSS решения s вместе, как первый не работает в 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>
...
tshalif
источник
3

Путь, который я считаю самым чистым, следующий:

  #bar::before {
    display: block;
    content: " ";
    margin-top: -150px;
    height: 150px;
    visibility: hidden;
    pointer-events: none;
  }
Гийом Ле Мьер
источник
2

Минимально навязчивый подход с использованием 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, но другой более популярный вопрос закрыт из-за этого, и я не смог ответить на него.

Хусейн Яглы
источник
2

Мне нужно что-то, что работает для входящих ссылок, ссылок на странице и на что может ориентироваться JS, чтобы страница могла реагировать на изменения высоты заголовка

HTML

<ul>
  <li><a href="#ft_who">Who?</a></li>
  <li><a href="#ft_what">What?</a></li>
  <li><a href="#ft_when">When?</a></li>
</ul>
...
<h2 id="ft_who" class="fragment-target">Who?</h2> 
...
<a href="#">Can I be clicked?</a>
<h2 id="ft_what" class="fragment-target">What?</h2>
...
<h2 id="ft_when" class="fragment-target">When?</h2> 

CSS

.fragment-target {
    display: block;
    margin-top: -HEADER_HEIGHTpx;
    padding-top: HEADER_HEIGHTpx;
    z-index: -1;
}

z-index: -1Позволяет ссылки в «области отступа» выше фрагмент-мишени до сих пор быть интерактивными, так прокомментировало @MuttenXd своего ответа

Я еще не нашел проблему в IE 11, Edge 15+, Chrome 38+, FF 52+ или Safari 9.1+

Arth
источник
1
<div style="position:relative; top:-45px;">
    <a name="fragment"> </a>
</div>

Этот код должен сделать свое дело. Поменяйте 45px на высоту панели заголовка.

РЕДАКТИРОВАТЬ: Если использование jQuery является опцией, я также успешно использовал jQuery.localScroll с установленным значением смещения. Параметр смещения является частью jQuery.scrollTo, на котором построен jQuery.localScroll. Демонстрация доступна здесь: http://demos.flesler.com/jquery/scrollTo/ (второе окно, под «смещением»)

fourk
источник
это решение действительно работает, но оно не является пуленепробиваемым и требует много настроек для разных браузеров :( хорошо, попробуйте. Я ищу решение без дополнительной разметки.
vlad saling
Позор, это так грязно, означает, что вы не можете просто использовать идентификаторы. Хотел бы найти решение, я перепробовал все виды вещей.
Теория
1

Вот полное решение 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) {

    });
}
гром
источник
Мне удалось использовать слегка модифицированную версию этого кода от Thunder. Я попробовал многие из простых и простых CSS-решений на этой странице и на stackoverflow.com/questions/10732690/…, а также на stackoverflow.com/questions/10732690/…, но они не были применимы из-за моих требований. Страница представляет собой страницу часто задаваемых вопросов, на которую можно ставить множество якорей, как на странице, так и за ее пределами, поэтому может иметь много пустых мест. Продолжение в следующем комментарии ....
Джеффри Саймон
1
Чтобы это работало для меня, вот небольшие изменения: (1) измените «<=» в строке href.index на «<», чтобы разрешить навигацию на странице; (2) изменить «a.navigation», которое должно было быть «#faq a» для моего использования; (3) измените var с Top = 250 на троичный на основе window.innerWidth для различий между мобильным и настольным компьютером; (4) изменить 400 в анимации на 1, так как анимация нежелательна и 0 не работает; (5) добавьте if ($ ('my-page-selector'). Length перед вызовом offSetScrollFromLocation в анонимной функции, чтобы предотвратить ненужные вызовы на страницах, где они не нужны.
Джеффри Саймон,
1

Реализация с использованием :beforeработала отлично, пока мы не поняли, что псевдоэлемент фактически покрывал и блокировал события указателя, которые находились в области псевдоэлемента. Использование чего-либо вроде « pointer-events: noneна» :beforeили даже непосредственно на якоре никак не повлияло.

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

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

.section-marker {

    position: absolute;
    top: -300px;
}

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

skabob11
источник
1

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

var offset = 90;

 $('.navbar li a').click(function(event) {
    event.preventDefault();
    $($(this).attr('href'))[0].scrollIntoView();
    scrollBy(0, -offset);
 });
Миля Миятович
источник
2
Решает проблему, но не «без помощи Javascript» часть ...
Томалак
1

Я создал div с несколькими переносами строк и дал идентификатор, а затем поместил код, который хотел показать ниже. Затем ссылка приведет вас к месту над изображением, и заголовок больше не будет мешать:

<a href="#image">Image</a>
<div id="image"><br><br></div>
<img src="Image.png">

Конечно, вы можете изменить количество разрывов строк в соответствии с вашими потребностями. Это отлично сработало для меня, но я не уверен, что есть какие-то проблемы, но я все еще изучаю HTML.

анонимное
источник
Прагматичный, но есть и обратная сторона - он работает только для первого заголовка на странице. Если заголовков больше, вы начнете видеть большие пропуски в тексте из-за <br>тегов перед каждым заголовком.
Томалак
1

Использовал этот скрипт

$(document).on('click', 'a[href^="#"]', function (event) {
    event.preventDefault();

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top -140
    }, 1000);
});
Адиль Мемон
источник
Пожалуйста, попробуйте объяснить, почему вы думаете, что этот сценарий решит проблему
Али Канат
1

Я думаю, что этот подход более полезен:

<h2 id="bar" title="Bar">Bar</h2>

[id]:target {
    display: block;
    position: relative;
    top: -120px;
    visibility: hidden;
}

[id]:target::before {
    content: attr(title);
    top: 120px;
    position: relative;
    visibility: visible;
}
Энес Шахин
источник
1

Теперь вы можете использовать scroll-margin-top , который довольно широко используется .

Просто добавьте следующий CSS к элементу, к которому вы хотите перейти:

.element {
  scroll-margin-top: 2em;
}
dutzi
источник
scroll-margin-topбыло предложено ранее в этой теме
Томалак
Запас прокрутки не применяется для прокруток, чтобы фрагментировать цель ... это не будет работать для якорных тегов developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin-top
Crystal Gardner