Buat tautan jangkar menjadi beberapa piksel di atas tempat tautan itu ditautkan


124

Saya tidak yakin cara terbaik untuk menanyakan / mencari pertanyaan ini:

Saat Anda mengklik tautan jangkar, ini membawa Anda ke bagian halaman dengan area tertaut ke sekarang di SANGAT ATAS halaman. Saya ingin tautan jangkar mengirim saya ke bagian halaman itu, tetapi saya ingin beberapa ruang di bagian atas. Seperti di, saya tidak ingin itu mengirim saya ke bagian yang ditautkan dengannya di SANGAT TOP, saya ingin 100 atau lebih piksel ruang di sana.

Apakah ini masuk akal? Apakah ini mungkin?

Diedit untuk menampilkan kode - itu hanya tag jangkar:

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

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


Jawaban:


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

Ini akan memungkinkan browser melakukan pekerjaan melompat ke jangkar untuk kita dan kemudian kita akan menggunakan posisi itu untuk mengimbangi.

EDIT 1:

Seperti yang ditunjukkan oleh @erb, ini hanya berfungsi jika Anda berada di halaman saat hash diubah. Memasuki halaman dengan yang #somethingsudah ada di URL tidak bekerja dengan kode di atas. Berikut adalah versi lain untuk mengatasinya:

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

CATATAN: Untuk menggunakan jQuery, Anda bisa mengganti window.addEventListenerdengan $(window).ondalam contoh. Terima kasih @Neon.

EDIT 2:

Seperti yang ditunjukkan oleh beberapa orang, hal di atas akan gagal jika Anda mengklik tautan jangkar yang sama dua kali atau lebih berturut-turut karena tidak ada hashchangeperistiwa untuk memaksa pengimbangan.

Solusi ini adalah versi yang sedikit dimodifikasi dari saran dari @Mave dan menggunakan pemilih jQuery untuk kesederhanaan

// 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 untuk contoh ini ada di sini


1
Ini hanya berfungsi ketika pengguna sudah berada di halaman, tidak misalnya ketika pengguna berkunjung example.com/#anchordari example.com/about/.
erb

7
Terima kasih @erb. Pertanyaan OP tidak membutuhkan kasus itu, tetapi untuk membantu orang lain saya menambahkan versi implementasi yang lain.
Eric Olson

2
Masih kurang detail kecil. Jika Anda klik pada sebuah anchor, kemudian scroll ke atas lalu klik anchor yang sama lagi, tidak ada perubahan hash sehingga tidak akan menggunakan offset. Ide ide?
Teo Maragakis

Anda bisa pergi $('a[href^="#"]').on('click', function() { offsetAnchor(); });. Dengan cara ini, jika hrefdari sebuah aelemen dimulai dengan a #, Anda memanggil fungsi yang sama.
Mave

2
Tidak perlu jQuery - cukup ganti $(window).on("hashchange",denganwindow.addEventListener("hashchange",
Neon

90

Bekerja hanya dengan css Anda dapat menambahkan padding ke elemen berlabuh (seperti dalam solusi di atas) Untuk menghindari spasi kosong yang tidak perlu Anda dapat menambahkan margin negatif dengan tinggi yang sama:

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

Saya tidak yakin apakah ini adalah solusi terbaik dalam hal apa pun, tetapi berfungsi dengan baik untuk saya.


3
jika ada tautan dalam jarak 50 piksel di atasnya, tautan itu mungkin ditutup-tutupi dan dibuat tidak dapat diklik. Saya yakin
Andrew

@Andrew Tampaknya tidak menjadi masalah di IE10 atau Chrome.
Sinister Beard

11
Anda dapat melakukan hal yang sama menggunakan position: relativeproperti css. Jadi, ini akan menjadi sepertiposition: relative; top: -50px;
Aleks Dorohovich

@AleksDorohovich - Anda dapat memposting jawaban itu sebagai jawaban terpisah karena unik untuk jawaban yang sudah ada.
BSMP

Halaman saya menjadi liar ... * _ *

64

Solusi yang lebih baik:

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

Posisikan saja <a>tag dengan pemosisian absolut di dalam objek yang posisinya relatif.

Berfungsi saat memasuki halaman atau melalui perubahan hash dalam halaman.


4
Saya lebih suka solusi Anda karena tidak menggunakan javascript. Terima kasih!
Rosario Russo

1
Saya tidak mengerti jawaban ini. Apakah Anda mengarahkan tautan ini ke objek atau objek itu sendiri?
CZorio

3
Sangat berguna dengan bilah navigasi atas tetap bootstrap
Outside_Box

1
@CZorio Jika saya melakukannya dengan benar, itu (dengan cerdik) membuat elemen jangkar (bisa jadi sesuatu yang lain, seperti "span" daripada "a") dan memposisikannya secara relatif di bawah, sehingga jangkar yang ada href="#anchor"di dalamnya akan mengarah ke sana, alih-alih menunjuk ke <p>elemen secara langsung. Tapi satu peringatan: gunakan idbukan namedi HTML5, lihat: stackoverflow.com/questions/484719/html-anchors-with-name-or-id
flen

1
Benar-benar solusi yang lebih baik :)
Bobby Axe

23

Inilah jawaban tahun 2020 untuk ini:

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

Karena itu didukung secara luas !


1
Tidak disukai karena meskipun ini bagus, TIDAK didukung secara luas. Baik opera mobile / mini, maupun safari browser / ios, bahkan Edge pertama tidak mendukung ini sepenuhnya.
Beda Schmid

1
Sedikit kurang dari 90% dari semua browser (termasuk iOS dengan scroll-snap-margin-top) sudah cukup untuk menyisih dari solusi javascript, terutama jika dampak pengguna hanya perlu menggulir. Tapi, hei, mari kita kurangi pendekatan ini sebelum merugikan seseorang.
pengguna127091

Jawaban yang sederhana dan berhasil. Akan segera mencapai 100% dukungan (untuk browser modern).
Leonel Becerra

17

Solusi terbaik

<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
Mengapa ini solusi terbaik? Juga, jauh lebih membantu jika Anda memberikan penjelasan / alasan tertentu dengan jawaban.
Phill Healey

Saat Anda menambahkan HTML untuk membuat jangkar, menambahkan rentang tidak jauh berbeda. Kemudian dengan hanya menambahkan sedikit CSS Anda berhasil menyelesaikan masalah ini tanpa mendapatkan bug; seperti yang mungkin dilakukan beberapa solusi lain.
Sondre

11

Ini akan bekerja tanpa jQuery dan saat memuat halaman.

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

1
Berfungsi untuk saya, dan memiliki keunggulan dibandingkan metode css yang berlaku untuk semua lokasi hash pada halaman, sehingga Anda tidak perlu menulis gaya dengan setiap hash disertakan dan ingat untuk mengubah gaya saat Anda menambahkan para dengan hash baru. Hal ini juga memungkinkan seseorang untuk mengatur gaya target dengan warna latar belakang tanpa memperpanjang 100px (atau apa pun) di atas seperti dalam jawaban dari @ user3364768, meskipun ada jalan lain.
David

4

Untuk menautkan ke sebuah elemen, dan kemudian 'memposisikan' elemen itu pada jarak yang sewenang-wenang dari bagian atas halaman, menggunakan CSS murni, Anda harus menggunakan padding-top, dengan cara itu elemen masih diposisikan di bagian atas jendela, tetapi itu muncul , tampak, untuk diposisikan agak jauh dari atas port tampilan, misalnya:

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

Demo JS Fiddle .

Untuk menggunakan pendekatan JavaScript biasa:

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

window.addEventListener('hashchange', addMargin);

Demo JS Fiddle .


1
Satu-satunya masalah dengan ini adalah sekarang mendorong div yang sebenarnya lebih jauh ke bawah halaman. Idealnya, tautan jangkar hanya akan turun 100px kurang dari biasanya. Saya bersedia menggunakan JS atau jQuery jika perlu untuk mencapai ini.
Damon

3
Ini tidak menyelesaikan masalah, ini hanya menambahkan spasi sebelum elemen.
XCS

user1925805: lihat jawaban yang diperbarui untuk solusi JavaScript. @Cristy: Saya tahu , saya secara eksplisit menyatakan bahwa dalam jawabannya itu sendiri: elemen masih diposisikan di bagian atas jendela, tetapi tampaknya, secara kasat mata, ditempatkan agak jauh dari atas .
David mengatakan mengembalikan Monica

Solusi terbaik dan bersih dengan JS Anda. Terima kasih, ini bekerja dengan sangat baik untuk saya!
DanielaB67

Ini hanya berfungsi, perubahan hash terjadi di dalam halaman. Tetapi penggunaan dialihkan dengan ID, maka ini tidak berfungsi
Rohan Khude

4

Ini harus bekerja:

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

Ubah saja .top-49 menjadi yang sesuai dengan tautan jangkar Anda.


3

Jika Anda menggunakan nama jangkar eksplisit seperti,

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

lalu di css Anda cukup mengaturnya

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

Ini akan bekerja selama tag anchor HREF Anda tidak juga menentukan atribut NAME


Terima kasih. Ini adalah satu-satunya solusi dari daftar ini yang berhasil untuk saya.
MikeyBunny

3

Jawaban Eric bagus, tetapi Anda benar-benar tidak membutuhkan waktu tunggu itu. Jika Anda menggunakan jQuery, Anda tinggal menunggu halaman dimuat. Jadi saya sarankan untuk mengubah kode menjadi:

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

Ini juga membuat kita menyingkirkan faktor sembarangan itu.


3

coba kode ini, sudah animasi yang mulus saat mengklik link.

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

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

1

Solusi termudah:

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

Varian solusi Thomas: elemen CSS > pemilih elemen dapat digunakan di sini:

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>

Sebuah klik pada link akan memindahkan posisi scroll ke 100px di atas dimanapun elemen dengan kelas paddedAnchordiposisikan.

Didukung di browser non-IE, dan di IE dari versi 9. Untuk dukungan pada IE 7 dan 8, a <!DOCTYPE>harus diumumkan.


1

Saya baru saja menemukan solusi mudah untuk diri saya sendiri. Memiliki margin-top 15px

HTML

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

CSS

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

1

Hanya menggunakan css dan tidak memiliki masalah dengan konten yang tertutup dan tidak dapat diklik sebelumnya (intinya adalah pointer-events: none):

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

Taruh ini dengan gaya:

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

dan gunakan kelas ini dalam divtag terpisah sebelum tautan, contoh:

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

atau gunakan kode php ini untuk tag tautan gema:

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

0

Saya tahu ini agak terlambat, tetapi saya menemukan sesuatu yang sangat penting untuk dimasukkan ke dalam kode Anda jika Anda menggunakan Scrollspy Bootstrap. ( http://getbootstrap.com/javascript/#scrollspy )

Ini membuatku gila selama berjam-jam.

Offset untuk mata-mata gulir HARUS cocok dengan window.scrollY atau Anda akan menjalankan risiko:

  1. Mendapatkan efek flicker aneh saat di-scroll
  2. Anda akan menemukan bahwa ketika Anda mengklik jangkar, Anda akan mendarat di bagian itu, tetapi mata-mata gulir akan menganggap Anda adalah bagian di atasnya.

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


Hanya js di cuplikan? Itu tidak akan berfungsi apa pun yang terjadi

0

Berdasarkan solusi @Eric Olson cukup modifikasi sedikit untuk memasukkan elemen jangkar yang ingin saya tuju secara khusus

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

Saya hanya memiliki masalah yang sama. Saya memiliki nav posited pixed dan saya ingin angkor mulai di bawah nav. Solusi window.addEventListener...tidak berhasil untuk saya karena saya mengatur halaman saya menjadi scroll-behavior:smoothjadi itu mengatur offset bukan gulir ke angkor. yang setTimeout()bekerja jika waktu yang anough untuk gulir sampai akhir tetapi masih tidak terlihat baik. jadi solusi saya adalah menambahkan div absolut yang ditempatkan di angkor, dengan height:[the height of the nav]dan bottom:100%. dalam hal ini div ini berakhir di bagian atas elemen angkor, dan mulai dari posisi di mana Anda ingin menggulir angkor. sekarang yang saya lakukan hanyalah mengatur tautan angkor ke div absolut ini dan selesai :)

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

saya menghadapi masalah serupa dan saya menyelesaikannya dengan menggunakan kode berikut

$(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
Itu pada dasarnya jawaban yang sama dengan yang ini . Jika Anda memposting jawaban untuk pertanyaan lama, coba tambahkan sesuatu yang baru. Misalnya, Anda bisa menjelaskan mengapa itu berhasil.
Artjom B.

1
Saya berpendapat bahwa jawaban apa pun harus memiliki semacam deskripsi tentang mengapa itu berhasil. ;-)
Phill Healey
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.