Çapa bağlantısının bağlantılı olduğu yerin birkaç piksel üstüne gitmesini sağlayın


124

Bu soruyu sormanın / aramanın en iyi yolunun ne olduğundan emin değilim:

Bir bağlantı linkine tıkladığınızda, sizi sayfanın ÇOK ÜSTÜNDE şimdi bağlantılı alana sahip o bölümüne götürür. Bağlantı bağlantısının beni sayfanın o kısmına göndermesini istiyorum, ancak üstte biraz boşluk istiyorum. Olduğu gibi, beni VERY TOP'daki bağlantılı bölüme göndermesini istemiyorum, orada 100 kadar piksel boşluk istiyorum.

Bu mantıklı mı? Mümkün mü?

Kodu gösterecek şekilde düzenlendi - bu yalnızca bir bağlantı etiketidir:

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

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


Yanıtlar:


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

Bu, tarayıcının bizim için çapaya atlama işini yapmasına izin verecek ve sonra bu konumu dengelemek için kullanacağız.

DÜZENLEME 1:

@Erb tarafından belirtildiği gibi, bu yalnızca hash değiştirilirken sayfadaysanız çalışır. #somethingZaten URL’de olan sayfaya girmek yukarıdaki kodla çalışmaz. İşte bunu halletmek için başka bir versiyon:

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

NOT: jQuery'yi kullanmak için, sadece örneklerde window.addEventListenerile değiştirebilirsiniz $(window).on. Teşekkürler @Neon.

DÜZENLEME 2:

Birkaç kişinin işaret ettiği gibi, aynı bağlantı bağlantısına arka arkaya iki veya daha fazla kez tıklarsanız yukarıdakiler başarısız olacaktır, çünkü hashchangeofseti zorlayacak bir olay yoktur .

Bu çözüm, @Mave'nin önerisinin çok az değiştirilmiş bir sürümüdür ve basitlik için jQuery seçicilerini kullanır

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

Bu örnek için JSFiddle burada


1
Kullanıcı, sayfada zaten olduğunda bu yalnızca çalışır, kullanıcının ziyaret örneğin yapmaz example.com/#anchordan example.com/about/.
erb

7
Teşekkürler @erb. OP'nin sorusu bu davayı gerektirmiyordu, ancak başkalarına yardım etmek için uygulamanın başka bir versiyonunu ekledim.
Eric Olson

2
Hala küçük bir ayrıntı eksik. Bir bağlantıya tıklar, ardından yukarı kaydırıp aynı bağlantıya tekrar tıklarsanız, hashchange yoktur, bu nedenle ofseti kullanmaz. Fikirler?
Teo Maragakis

Sen gidebilirsin $('a[href^="#"]').on('click', function() { offsetAnchor(); });. Bu şekilde, hrefbir aelemanın a ile başlıyorsa #, aynı işlevi çağırırsınız.
Mave

2
JQuery'ye gerek yok - $(window).on("hashchange",şununla değiştirinwindow.addEventListener("hashchange",
Neon

90

Yalnızca css ile çalışarak bağlantılı öğeye dolgu ekleyebilirsiniz (yukarıdaki çözümde olduğu gibi) Gereksiz boşluklardan kaçınmak için aynı yükseklikte bir negatif kenar boşluğu ekleyebilirsiniz:

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

Bunun en iyi çözüm olup olmadığından emin değilim, ancak benim için iyi çalışıyor.


3
50 piksel içinde bir bağlantı varsa, üstü örtülmüş ve tıklanamaz hale gelmiş olabilir sanırım
Andrew

@Andrew Bu, IE10 veya Chrome'da bir sorun gibi görünmüyor.
Uğursuz Sakal

11
position: relativecss özelliğini kullanarak da aynısını yapabilirsiniz . Yani, şöyle olurduposition: relative; top: -50px;
Aleks Dorohovich

@AleksDorohovich - Mevcut cevaplara özel olduğu için bunu ayrı bir cevap olarak gönderebilirsiniz.
BSMP

Sayfam çıldırdı ... * _ *

64

Daha da iyi çözüm:

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

Sadece pozisyon <a>nispeten yerleştirilmiş nesne mutlak konumlama içiyle etiketi.

Sayfaya girerken veya sayfa içinde bir karma değişikliği yoluyla çalışır.


4
Çözümünüzü javascript kullanmadığı için tercih ediyorum. Teşekkürler!
Rosario Russo

1
Bu cevabı anlamıyorum. Bu bağlantıyı nesneye mi yoksa nesnenin kendisine mi gönderiyorsunuz?
CZorio

3
Bootstrap sabit üst gezinme çubuklarıyla çok kullanışlı
Outside_Box

1
@CZorio Eğer doğru anladıysam, bu (ustaca) bir çapa öğesi oluşturmaktır ("a" yerine "açıklık" gibi başka bir şey olabilir) ve onu nispeten aşağıda konumlandırır, böylece içindeki çapa href="#anchor"orayı gösterir, <p>doğrudan öğeye işaret etmek yerine . Ancak bir uyarı: HTML5 idyerine kullanın name, bkz: stackoverflow.com/questions/484719/html-anchors-with-name-or-id
17'de 5

1
Gerçekten daha iyi bir çözüm :)
Bobby Ax

23

İşte bunun için 2020 cevabı:

#anchor {
  scroll-margin-top: 100px;
}

Çünkü yaygın olarak destekleniyor !


1
Olumsuz oy verildi, çünkü bu iyi olsa da, geniş çapta desteklenmiyor. Ne opera mobile / mini ne de safari tarayıcısı / ios, ilk Edge bile bunu tam olarak desteklemiyor.
Beda Schmid

1
Tüm tarayıcıların (scroll-snap-margin-top ile iOS dahil) biraz daha azı, özellikle kullanıcı etkisi sadece kaydırmak zorunda kalıyorsa, bir javascript çözümünü devre dışı bırakmak için yeterli olmalıdır. Ama hey, bu yaklaşımı birine zarar vermeden önce olumsuz oylayalım.
user127091

Çok basit ve işe yarar bir cevap. Çok yakında (modern tarayıcılar için) desteğin% 100'üne ulaşacak.
Leonel Becerra

17

En İyi Çözüm

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

8
Bu neden en iyi çözüm? Ayrıca, bir cevapla birlikte bir miktar açıklama / akıl yürütme yaparsanız çok daha yararlı olur.
Phill Healey

Yine de bir çapa yapmak için HTML eklerken, bir aralık eklemek çok da farklı değildir. Sonra biraz CSS ekleyerek bu sorunu herhangi bir hata olmadan çözmeyi başarırsınız; diğer bazı çözümlerin yapabileceği gibi.
Sondre

11

Bu, jQuery olmadan ve sayfa yüklemesinde çalışacaktır.

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

1
Benim için çalışıyor ve bir sayfadaki tüm hash konumlarına uyguladığı css yöntemine göre avantaja sahip , böylece dahil edilen her hash ile bir stil yazmak zorunda kalmazsınız ve başka bir para eklediğinizde stili değiştirmeyi unutmayın. yeni bir hash. Ayrıca, yukarıda @ user3364768'den gelen yanıtta olduğu gibi 100px (veya her neyse) genişletmeden hedefin arka plan rengiyle biçimlendirilmesine izin verir, ancak bunun etrafında bir yol vardır.
David

4

Bir öğeye bağlanmak ve ardından bu öğeyi, saf CSS kullanarak sayfanın üstünden rastgele bir mesafede 'konumlandırmak' için, öğeyi kullanmanız gerekir padding-top, bu şekilde öğe hala pencerenin en üstünde konumlandırılır, ancak görüntülenir , gözle görülür bir şekilde, örneğin, görüntüleme bağlantı üst belirli bir mesafede yerleştirilmiş olması:

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

Düz bir JavaScript yaklaşımı kullanmak için:

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

window.addEventListener('hashchange', addMargin);

JS Fiddle demosu .


1
Bununla ilgili tek sorun, artık gerçek div'i sayfanın daha aşağıya doğru itmesidir. İdeal olarak, çapa bağlantısı normalde olduğundan 100 piksel daha az düşer. Bunu başarmak için gerekirse JS veya jQuery kullanmaya hazırım.
damon

3
Bu sorunu çözmez, bu sadece öğeden önce boşluk ekler.
XCS

user1925805: JavaScript çözümü için güncellenmiş yanıta bakın. @Cristy: Biliyorum , cevabın kendisinde açıkça belirttim: öğe hala pencerenin üstünde konumlanıyor, ancak gözle görülür bir şekilde yukarıdan biraz uzakta konumlanmış görünüyor .
David, Monica

JS'nizle en iyi, temiz çözüm. Teşekkürler benim için çok iyi çalışıyor!
DanielaB67

Bu, yalnızca sayfa içinde gerçekleşen hashchanges çalışır. Ancak kullanım ID ile yeniden yönlendirildi, sonra bu işe
yaramıyor

4

Bu çalışmalı:

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

Sadece .top-49'u bağlantı bağlantınıza uyanla değiştirin.


3

Şunun gibi açık bağlantı adları kullanırsanız,

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

sonra css'de basitçe ayarlayabilirsiniz

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

Bu, HREF bağlantı etiketleriniz de bir NAME özniteliği belirtmediği sürece çalışacaktır.


Teşekkürler. Bu listeden benim için çalışan tek çözüm budur.
MikeyBunny

3

Eric'in cevabı harika, ama gerçekten o zaman aşımına ihtiyacın yok. JQuery kullanıyorsanız, sayfanın yüklenmesini bekleyebilirsiniz. Bu yüzden kodu şu şekilde değiştirmenizi öneririm:

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

Bu aynı zamanda bizi keyfi faktörden kurtarır.


3

bu kodu deneyin, bağlantıya tıklandığında zaten düzgün bir animasyona sahip.

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

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

1

En kolay çözüm:

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

Thomas'ın çözümünün bir çeşidi: CSS öğesi> öğe seçicileri burada kullanışlı olabilir:

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>

Bağlantıya tıklandığında kaydırma konumu, sınıfına sahip öğenin konumlandırıldığı her yerde 100 piksel üstüne çıkar paddedAnchor.

IE olmayan tarayıcılarda ve sürüm 9'dan itibaren IE'de desteklenir. IE 7 ve 8'de destek için, a <!DOCTYPE>bildirilmelidir.


1

Kendim için kolay bir çözüm buldum. 15 piksellik bir kenar boşluğu vardı

HTML

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

CSS

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

1

Yalnızca css kullanmak ve daha önce kapsanan ve tıklanamayan içerikle hiçbir sorun yaşamamak (bunun amacı işaretçi olaylarıdır: yok):

CSS

.anchored::before {
    content: '';
    display: block;
    position: relative;
    width: 0;
    height: 100px;
    margin-top: -100px;
}

HTML

<a href="#anchor">Click me!</a>
<div style="pointer-events:none;">
<p id="anchor" class="anchored">I should be 100px below where I currently am!</p>
</div>

1

Bunu bir stil haline getirin:

.hash_link_tag{margin-top: -50px; position: absolute;}

ve bu sınıfı divbağlantılardan önce ayrı bir etiket içinde kullanın , örneğin:

<div class="hash_link_tag" id="link1"></div> 
<a href="#link1">Link1</a>

veya yankı bağlantı etiketi için bu php kodunu kullanın:

function HashLinkTag($id)
{
    echo "<div id='$id' class='hash_link_tag'></div>";
}

0

Bunun biraz geç olduğunu biliyorum, ancak Bootstrap's Scrollspy kullanıyorsanız kodunuza koyacak çok önemli bir şey buldum. ( http://getbootstrap.com/javascript/#scrollspy )

Bu beni saatlerdir deli ediyordu.

Kaydırma casusu için ofset, window.scrollY ile eşleşmelidir ZORUNLU, yoksa şu risklerle karşılaşırsınız:

  1. Kaydırırken garip bir titreme efekti elde etmek
  2. Çapalara tıkladığınızda, o bölüme ineceğinizi göreceksiniz, ancak casus kaydırma, sizin onun üzerinde bir bölüm olduğunuzu varsayacaktır.

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


Parçacıkta yalnızca js mi? Ne olursa olsun işe yaramayacak

0

@Eric Olson çözümüne dayanarak, özellikle gitmek istediğim bağlantı öğesini eklemek için biraz değişiklik yapın

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

Bende de aynı sorun var. Pikselli bir navigasyon var ve angkorun navigasyonun altından başlamasını istiyorum. Çözüm window.addEventListener...benim için işe yaramıyor çünkü sayfamı scroll-behavior:smoothöyle ayarladım ki ofseti ayarlamak yerine angkor'a kaydırın. setTimeout()iş zamanı sona kaydırma için anough ise ancak hala iyi görünüyor değil. Benim çözüm yüzden birlikte, angkor bir oturtulması mutlak div eklemek oldu height:[the height of the nav]ve bottom:100%. bu durumda, bu div angkor öğesinin tepesinde sona erer ve angkorun kaydırılacağı konumdan başlar. şimdi yaptığım tek şey angkor bağlantısını bu mutlak div'e ayarlamak ve en kötüsü yapıldı :)

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

benzer bir sorunla karşı karşıyaydım ve aşağıdaki kodu kullanarak çözdüm

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

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

4
Bu temelde aynı cevabı bu bir . Eski soruya yanıt gönderirseniz, yeni bir şey eklemeyi deneyin. Örneğin, bunun neden işe yaradığını açıklayabilirsiniz.
Artjom B.10

1
Herhangi bir cevabın neden işe yaradığına dair bir çeşit açıklaması olması gerektiğini iddia ediyorum. ;-)
Phill Healey
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.