Фиксированного заголовка перекрывает странице в разделе анкеры
Если у меня есть заголовок без прокрутки на 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 ответов:
у меня была та же проблема. Я решил это, добавив класс к элементу привязки с высотой верхней панели в качестве значения 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/
лучший способ, который я нашел, чтобы справиться с этой проблемой (заменить 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, поэтому смещение заголовка не помогло, так как остальная часть контента просто останется там, где она была. Поэтому я подумал, что отправлю сообщение.
то, что я в конечном итоге сделал, было составным из нескольких решений:
CSS:
.bookmark { margin-top:-120px; padding-bottom:120px; display:block; }
где "120px" - это ваша фиксированная высота заголовка (возможно, плюс некоторые маржа.)
ссылка на закладку HTML:
<a href="#01">What is your FAQ question again?</a>
содержимое закладок 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-->
- эффект прокрутки не жесткий, а гладкий; плавная прокрутка