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

Я не уверен, что лучший способ задать/найти этот вопрос:

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

имеет ли это смысл? Есть это возможно?

редактировать, чтобы показать код - это просто якорный тег:

<a href="#anchor">Click me!</a>

<p id="anchor">I should be 100px below where I currently am!</p>

15 ответов


window.addEventListener("hashchange", function () {
    window.scrollTo(window.scrollX, window.scrollY - 100);
});

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

EDIT 1:

как было указано @erb, это работает только в том случае, если вы находитесь на странице во время изменения хэша. Ввод страницы с #something уже в URL не работает с указанным выше кодом. Вот еще одна версия, чтобы справиться с этим:

// The function actually applying the offset
function offsetAnchor() {
    if(location.hash.length !== 0) {
        window.scrollTo(window.scrollX, window.scrollY - 100);
    }
}

// This will capture hash changes while on the page
window.addEventListener("hashchange", offsetAnchor);

// This is here so that when you enter the page with a hash,
// it can provide the offset in that case too. Having a timeout
// seems necessary to allow the browser to jump to the anchor first.
window.setTimeout(offsetAnchor, 1); // The delay of 1 is arbitrary and may not always work right (although it did in my testing).

Примечание.: Чтобы использовать jQuery, вы можете просто замените window.addEventListener С $(window).on в примерах. Спасибо @Neon.

EDIT 2:

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

это решение является очень слегка измененной версией предложения от @Mave и использует селекторы jQuery для простоты

// The function actually applying the offset
function offsetAnchor() {
  if (location.hash.length !== 0) {
    window.scrollTo(window.scrollX, window.scrollY - 100);
  }
}

// Captures click events of all <a> elements with href starting with #
$(document).on('click', 'a[href^="#"]', function(event) {
  // Click events are captured before hashchanges. Timeout
  // causes offsetAnchor to be called after the page jump.
  window.setTimeout(function() {
    offsetAnchor();
  }, 0);
});

// Set the offset when entering page with hash present in the url
window.setTimeout(offsetAnchor, 0);

JSFiddle для этого примера здесь


работа только с css вы можете добавить дополнение к закрепленному элементу (как в решении выше) Чтобы избежать ненужных пробелов, вы можете добавить отрицательное поле той же высоты:

#anchor {
    padding-top: 50px;
    margin-top: -50px;
}

Я не уверен, что это лучшее решение в любом случае, но он отлично работает для меня.


еще лучше решение:

<p style="position:relative;">
    <a name="anchor" style="position:absolute; top:-100px;"></a>
    I should be 100px below where I currently am!
</p>

просто позиция <a> тега с абсолютным позиционированием внутри относительно позиционированного объекта.

работает при входе на страницу или через изменение хэша внутри страницы.


Лучшим Решением

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

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

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

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

Это будет работать без jQuery и при загрузке страницы.

(function() {
    if (document.location.hash) {
        setTimeout(function() {
            window.scrollTo(window.scrollX, window.scrollY - 100);
        }, 10);
    }
})();

чтобы связать элемент, а затем "расположить" этот элемент на произвольном расстоянии от верхней части страницы, используя чистый CSS, вам придется использовать padding-top, таким образом, элемент по-прежнему находится в верхней части окна, но это появляется, заметно, чтобы быть расположен на некотором расстоянии от верхней части view-port, например:

<a href="#link1">Link one</a>
<a href="#link2">Link two</a>

<div id="link1">
    The first.
</div>

<div id="link2">
    The second.
</div>

CSS:

div {
    /* just to force height, and window-scrolling to get to the elements.
       Irrelevant to the demo, really */
    margin-top: 1000px;
    height: 1000px;
}

#link2 {
    /* places the contents of the element 100px from the top of the view-port */
    padding-top: 100px;
}

JS Fiddle demo.

использовать простой JavaScript подход:

function addMargin() {
    window.scrollTo(0, window.pageYOffset - 100);
}

window.addEventListener('hashchange', addMargin);

JS Fiddle demo.


Если вы используете явные имена Привязок, такие как,

<a name="sectionLink"></a>
<h1>Section<h1>

тогда в css вы можете просто установить

A[name] {
    padding-top:100px;
}

это будет работать до тех пор, пока ваши теги привязки HREF также не укажут атрибут NAME


Это должно работать:

    $(document).ready(function () {
    $('a').on('click', function (e) {
        // e.preventDefault();

        var target = this.hash,
            $target = $(target);

       $('html, body').stop().animate({
        'scrollTop': $target.offset().top-49
    }, 900, 'swing', function () {
    });

        console.log(window.location);

        return false;
    });
});

просто изменить .top-49 к тому, что соответствует вашей якорной ссылке.


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

// The function actually applying the offset
function offsetAnchor() {
    if (location.hash.length !== 0) {
        window.scrollTo(window.scrollX, window.scrollY - 100);
    }
}

// This will capture hash changes while on the page
$(window).on("hashchange", function () {
    offsetAnchor();
});

// Let the page finish loading.
$(document).ready(function() {
    offsetAnchor();
});

Это также избавляет нас от этого произвольного фактора.


самое простое решение:

в CSS

#link {
    top:-120px; /* -(some pixels above) */
    position:relative;
    z-index:5;
}

HTML-код

<body>
    <a href="#link">Link</a>
    <div>
        <div id="link"></div> /*this div should placed inside a target div in the page*/
        text
        text
        text
    <div>
</body>

попробуйте этот код, он уже имеет плавную анимацию при нажатии на ссылку.

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

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top - 100
    }, 500);
});

Я знаю, что это немного поздно, но я нашел что-то очень важное, чтобы поместить в ваш код, если вы используете Scrollspy Bootstrap. (http://getbootstrap.com/javascript/#scrollspy)

Это сводит меня с ума в течение нескольких часов.

смещение для Scroll spy должно соответствовать окну.scrollY, иначе вы рискуете:

  1. получение странного эффекта мерцания при прокрутке
  2. вы обнаружите, что когда вы нажимаете на якоря, вы земля в этом разделе, но scroll spy будет считать, что вы раздел выше него.

 var body = $('body');
    body.scrollspy({
        'target': '#nav',
        'offset': 100 //this must match the window.scrollY below or you'll have a bad time mmkay
});

$(window).on("hashchange", function () {
        window.scrollTo(window.scrollX, window.scrollY - 100);
});

на основе @Eric Olson решение просто измените немного, чтобы включить элемент якоря, который я хочу пойти конкретно

// Function that actually set offset
function offsetAnchor(e) {
    // location.hash.length different to 0 to ignore empty anchor (domain.me/page#)
    if (location.hash.length !== 0) {
        // Get the Y position of the element you want to go and place an offset
        window.scrollTo(0, $(e.target.hash).position().top - 150);
    }
}

// Catch the event with a time out to perform the offset function properly
$(document).on('click', 'a[href^="#"]', function (e) {
    window.setTimeout(function () {
        // Send event to get the target id later
        offsetAnchor(e);
    }, 10);
});

у меня просто такая же проблема. У меня есть навигатор, и я хочу, чтобы Ангкор начинался под навигатором. Решение window.addEventListener... не работает для меня, потому что я поставил мои страницы scroll-behavior:smooth задает смещение вместо прокрутите до Ангкора. the setTimeout() работа, если время достаточно для прокрутки до конца, но это все еще не выглядит хорошо. поэтому моим решением было добавить положенный абсолютный div в Ангкор, с height:[the height of the nav] и bottom:100%. в этом случае этот div закончился в верхней части Ангкора элемент, и начать с позиции, где вы, что Ангкор для прокрутки. теперь все, что я делаю, это установить ссылку angkor на этот абсолютный div и WOR done:)

html,body{
    margin:0;
    padding:0;
    scroll-behavior:smooth;
}

nav {
    height:30px;
    width:100%;
    font-size:20pt;
    text-align:center;
    color:white;
    background-color:black;
    position:relative;
}

#my_nav{
    position:fixed;
    z-index:3;
}
#fixer_nav{
    position:static;
}

#angkor{
    position:absolute;
    bottom:100%;
    height:30px;
}
<nav id="my_nav"><a href="#angkor">fixed position nav<a/></nav>
<nav id="fixer_nav"></nav>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec lacus vel eros rutrum volutpat. Cras ultrices enim sit amet odio dictum, eget consectetur mi pellentesque. Sed mollis gravida nulla, eu euismod turpis efficitur id. Integer pretium posuere fringilla. Aenean laoreet, augue non pharetra elementum, lectus massa congue orci, a imperdiet neque enim ut dui. Praesent commodo orci bibendum leo suscipit viverra. Nunc fermentum semper eleifend. Pellentesque suscipit nulla aliquet, egestas lectus sed, egestas dui. Vivamus scelerisque maximus nibh, ac dignissim nunc tempor a. Praesent facilisis non lacus et aliquam. Proin ultricies lacus vitae nibh ullamcorper gravida. Proin elit arcu, convallis eget posuere quis, placerat id augue. Fusce ex risus, tempus nec orci vitae, feugiat faucibus quam. Integer risus metus, ornare et rhoncus vitae, accumsan a urna.
</p>

<nav><div id="angkor"></div>The angkor</nav>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec lacus vel eros rutrum volutpat. Cras ultrices enim sit amet odio dictum, eget consectetur mi pellentesque. Sed mollis gravida nulla, eu euismod turpis efficitur id. Integer pretium posuere fringilla. Aenean laoreet, augue non pharetra elementum, lectus massa congue orci, a imperdiet neque enim ut dui. Praesent commodo orci bibendum leo suscipit viverra. Nunc fermentum semper eleifend. Pellentesque suscipit nulla aliquet, egestas lectus sed, egestas dui. Vivamus scelerisque maximus nibh, ac dignissim nunc tempor a. Praesent facilisis non lacus et aliquam. Proin ultricies lacus vitae nibh ullamcorper gravida. Proin elit arcu, convallis eget posuere quis, placerat id augue. Fusce ex risus, tempus nec orci vitae, feugiat faucibus quam. Integer risus metus, ornare et rhoncus vitae, accumsan a urna.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec lacus vel eros rutrum volutpat. Cras ultrices enim sit amet odio dictum, eget consectetur mi pellentesque. Sed mollis gravida nulla, eu euismod turpis efficitur id. Integer pretium posuere fringilla. Aenean laoreet, augue non pharetra elementum, lectus massa congue orci, a imperdiet neque enim ut dui. Praesent commodo orci bibendum leo suscipit viverra. Nunc fermentum semper eleifend. Pellentesque suscipit nulla aliquet, egestas lectus sed, egestas dui. Vivamus scelerisque maximus nibh, ac dignissim nunc tempor a. Praesent facilisis non lacus et aliquam. Proin ultricies lacus vitae nibh ullamcorper gravida. Proin elit arcu, convallis eget posuere quis, placerat id augue. Fusce ex risus, tempus nec orci vitae, feugiat faucibus quam. Integer risus metus, ornare et rhoncus vitae, accumsan a urna.

</p>

<a href="#anchor">Click me!</a>

<div style="margin-top: -100px; padding-top: 100px;" id="anchor"></div>
<p>I should be 100px below where I currently am!</p>