it-roy-ru.com

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

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

Когда вы нажимаете на ссылку привязки, вы попадаете в тот раздел страницы с областью, на которую указывает ссылка, в ОЧЕНЬ ВЕРХНУЮ часть страницы. Я хотел бы, чтобы якорная ссылка отправила меня на эту часть страницы, но мне бы хотелось немного места сверху. Например, я не хочу, чтобы он отправлял меня на связанную с ним часть в ОЧЕНЬ ТОП, мне бы хотелось, чтобы там было около 100 пикселей.

Имеет ли это смысл? Это возможно? 

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

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

<p id="anchor">I should be 100px below where I currently am!</p>
90
damon
window.addEventListener("hashchange", function () {
    window.scrollTo(window.scrollX, window.scrollY - 100);
});

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

Правка 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.

Правка 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 для этого примера - здесь

113
Eric Olson

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

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

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

69
user3364768

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

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

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

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

49
Thomas

Лучшее решение

<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>
16

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

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

Чтобы связать элемент с последующим «позиционированием» этого элемента на произвольном расстоянии от вершины страницы, используя чистый CSS, вам нужно будет использовать padding-top, чтобы элемент все еще располагался вверху окна, но он появляется, видимо, для размещения на некотором расстоянии от вершины порта просмотра, например:

<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 демо .

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

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

window.addEventListener('hashchange', addMargin);

JS Fiddle демо .

4
David Thomas

Ответ Эрика великолепен, но вам действительно не нужен этот тайм-аут. Если вы используете 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();
});

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

3
rppc

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

    $(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 на то, что соответствует вашей якорной ссылке.

3
dMehta

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

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

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

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

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

3
Mespr

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

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

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

Я только что нашел простое решение для себя .. Имел запас вершины 15px

HTML

<h2 id="Anchor">Anchor</h2>

CSS

h2{margin-top:-60px; padding-top:75px;}
1
Gero

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

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>
1
Edalat Mojaveri

Вариант решения Томаса: CSS element> element селекторы могут быть полезны здесь:

CSS

.paddedAnchor{
  position: relative;
}
.paddedAnchor > a{
  position: absolute;
  top: -100px;
}

HTML

<a href="#myAnchor">Click Me!</a>

<span class="paddedAnchor"><a name="myAnchor"></a></span>

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

Поддерживается в браузерах, отличных от IE, и в IE версии 9. Для поддержки IE 7 и 8 должен быть объявлен <!DOCTYPE>.

0
HondaGuy

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

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>

0
Yosef Tukachinsky

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

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

Смещение для шпиона прокрутки ДОЛЖНО совпадать с window.scrollY, иначе вы рискуете:

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

 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);
});

0
beefsupreme

Основано на @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);
});
0
Carlos A. Ortiz

я столкнулся с подобной проблемой, и я решил, используя следующий код 

$(document).on('click', 'a.page-scroll', function(event) {
        var $anchor = $(this);
        var desiredHeight = $(window).height() - 577;
        $('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top - desiredHeight
        }, 1500, 'easeInOutExpo');
        event.preventDefault();
    });
0
Umair Mehmood