앵커 링크를 링크 된 위치보다 몇 픽셀 위로 이동합니다.


124

이 질문을 요청 / 검색하는 가장 좋은 방법을 모르겠습니다.

앵커 링크를 클릭하면 페이지의 맨 위에 링크 된 영역이있는 페이지의 해당 섹션으로 이동합니다. 앵커 링크를 통해 페이지의 해당 부분으로 이동하고 싶지만 상단에 약간의 공간이 필요합니다. 에서와 같이 VERY TOP에서 연결된 부분으로 나를 보내지 않기를 원합니다. 100 픽셀 정도의 공간을 원합니다.

이게 말이 돼? 이게 가능해?

코드를 표시하도록 편집 됨-단지 앵커 태그 일뿐입니다.

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

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


답변:


157
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은 여기에 있습니다.


1
이는 사용자가 이미 페이지에있는 경우에만 작동하며 예를 들어 사용자가 example.com/#anchor에서 방문한 경우에는 작동하지 않습니다 example.com/about/.
erb

7
감사합니다 @erb. OP의 질문에는 그 경우가 필요하지 않았지만 다른 사람들을 돕기 위해 다른 버전의 구현을 추가했습니다.
Eric Olson

2
여전히 사소한 세부 사항이 누락되었습니다. 앵커를 클릭 한 다음 위로 스크롤 한 다음 동일한 앵커를 다시 클릭하면 해시 변경이 없으므로 오프셋을 사용하지 않습니다. 아이디어?
테오 Maragakis

당신은 갈 수 $('a[href^="#"]').on('click', function() { offsetAnchor(); });있습니다. 이렇게 href하면 a요소의가로 시작하는 #경우 동일한 함수를 호출합니다.
MAVE

2
jQuery를 할 필요가 없습니다 - 그냥 교체 $(window).on("hashchange",와 함께window.addEventListener("hashchange",
네온

90

css로만 작업하면 고정 된 요소에 패딩을 추가 할 수 있습니다 (위의 솔루션에서와 같이) 불필요한 공백을 방지하려면 동일한 높이의 음수 여백을 추가 할 수 있습니다.

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

이것이 최선의 해결책인지 확실하지 않지만 잘 작동합니다.


3
위 50 픽셀에 포함 된 링크가 있다면, 그것은 은폐하고 unclickable 될 수 있습니다 저는 믿습니다
앤드류

@Andrew IE10이나 Chrome에서는 문제가되지 않는 것 같습니다.
Sinister Beard

11
position: relativecss 속성을 사용하여 동일한 작업을 수행 할 수 있습니다 . 그래서, 그것은 같은 것position: relative; top: -50px;
하기 Aleks Dorohovich

@AleksDorohovich-기존 답변에 고유하기 때문에 별도의 답변으로 게시 할 수 있습니다.
BSMP

내 페이지가 거칠어

64

더 나은 솔루션 :

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

<a>상대적으로 배치 된 개체 내부에 절대 위치로 태그를 배치하기 만하면 됩니다.

페이지에 들어갈 때 또는 페이지 내 해시 변경을 통해 작동합니다.


4
자바 스크립트를 사용하지 않기 때문에 귀하의 솔루션을 선호합니다. 감사!
Rosario Russo

1
이 대답을 이해하지 못합니다. 이 링크를 개체 또는 개체 자체에 참조하고 있습니까?
CZorio

3
매우 유용한 부트 스트랩 고정 탑 navbars와
Outside_Box

1
@CZorio 내가 옳다면, 앵커 요소 ( "a"대신 "span"과 같은 다른 것이 될 수 있음)를 생성하고 상대적으로 아래에 배치하여 앵커가 href="#anchor"거기를 가리 키도록합니다. <p>요소를 직접 가리키는 대신 . 그러나 한 가지 경고 : HTML5 id대신 사용 name, 참조 : stackoverflow.com/questions/484719/html-anchors-with-name-or-id
flen

1
정말 더 나은 솔루션 :
바비 도끼

22

이에 대한 2020 년 답은 다음과 같습니다.

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

널리 지원 되기 때문입니다 !


1
이것이 좋지만 널리 지원되지 않기 때문에 반대 투표했습니다. 오페라 모바일 / 미니, 사파리 브라우저 / iOS 모두, 심지어 첫 번째 엣지조차도이를 완벽하게 지원하지 않습니다.
Beda Schmid

1
모든 브라우저의 90 % 미만 (scroll-snap-margin-top이있는 iOS 포함)은 자바 스크립트 솔루션을 옵트 아웃하기에 충분해야합니다. 특히 사용자 영향이 스크롤 만해야하는 경우에는 더욱 그렇습니다. 하지만 누군가에게 해를 끼치기 전에이 접근 방식을 반대표로 지정합시다.
user127091

간단하고 효과적인 답변입니다. 곧 100 % 지원 (최신 브라우저)에 도달 할 것입니다.
Leonel Becerra

17

최고의 솔루션

<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
이것이 최고의 솔루션 인 이유는 무엇입니까? 또한 답변으로 어느 정도의 설명 / 추론을 제공하면 훨씬 더 유용합니다.
Phill Healey

어쨌든 앵커를 만들기 위해 HTML을 추가하고 있으므로 스팬을 추가하는 것은 크게 다르지 않습니다. 그런 다음 약간의 CSS 만 추가하면 버그없이이 문제를 해결할 수 있습니다. 다른 솔루션이 할 수 있습니다.
Sondre

11

이것은 jQuery없이 및 페이지로드시 작동합니다.

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

1
나를 위해 작동 하며 페이지의 모든 해시 위치에 적용되는 CSS 방법보다 이점이 있으므로 각 해시가 포함 된 스타일을 작성할 필요가 없으며 다른 매개 변수를 추가 할 때 스타일을 수정하는 것을 기억하십시오 새로운 해시. 또한 @ user3364768의 답변에서와 같이 100px (또는 기타)를 확장하지 않고도 배경색으로 대상을 스타일링 할 수 있습니다.
David

4

요소에 연결 한 다음 순수한 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 데모 .


1
이것의 유일한 문제는 실제 div를 페이지 아래로 더 밀어 넣는 것입니다. 이상적으로는 앵커 링크가 평소보다 100px 아래로 내려갑니다. 이를 달성하기 위해 필요한 경우 JS 또는 jQuery를 사용할 의향이 있습니다.
damon

3
이것은 문제를 해결하지 못하고 단순히 요소 앞에 공백을 추가합니다.
XCS 2013

user1925805 : JavaScript 솔루션에 대한 업데이트 된 답변을 참조하십시오. @Cristy : 알아요 , 대답 자체 에서 요소가 여전히 창 상단에 위치하지만 눈에 띄게 상단에서 약간 떨어진 위치에 있다고 명시 적으로 언급했습니다 .
다윗은 분석 재개 모니카 말한다

JS로 가장 깨끗한 솔루션. 감사합니다. 아주 잘 작동합니다!
DanielaB67

이것은 페이지 내에서 발생한 해시 변경 만 작동합니다. 그러나 사용이 ID로 리디렉션있어,이 나던 작품
로한 Khude

4

이것은 작동합니다.

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

다음과 같은 명시 적 앵커 이름을 사용하는 경우

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

그런 다음 CSS에서 간단히 설정할 수 있습니다.

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

이것은 HREF 앵커 태그가 NAME 속성도 지정하지 않는 한 작동합니다.


감사. 이것은이 목록에서 나를 위해 일한 유일한 솔루션입니다.
MikeyBunny 2016-09-11

3

Eric의 대답은 훌륭하지만 실제로는 시간 초과가 필요하지 않습니다. 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

이 코드를 시도하면 링크를 클릭했을 때 이미 부드러운 애니메이션이 있습니다.

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

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

1

가장 쉬운 솔루션 :

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의 솔루션 변형 : CSS 요소> 요소 선택자 는 여기에서 편리 할 수 ​​있습니다.

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>

링크를 클릭하면 클래스가있는 요소가있는 곳 어디에서나 스크롤 위치가 100px 위로 이동합니다. paddedAnchor .

비 IE 브라우저 및 버전 9의 IE에서 지원됩니다. IE 7 및 8에서 지원 <!DOCTYPE>하려면 a 를 선언해야합니다.


1

나는 나 자신을위한 쉬운 해결책을 찾았습니다. 여백 상단이 15px입니다.

HTML

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

CSS

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

1

CSS 만 사용하고 이전에 덮고 클릭 할 수없는 콘텐츠에 문제가 없습니다 (이 점은 포인터 이벤트 : 없음).

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

이것을 스타일에 넣으십시오.

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

div링크 앞에 별도의 태그 에이 클래스를 사용 합니다. 예 :

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

또는 에코 링크 태그에 다음 PHP 코드를 사용하십시오.

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

0

나는 이것이 조금 늦었다는 것을 알고 있지만 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);
});


스 니펫의 js 만? 그것은 상관없이 작동하지 않습니다

0

@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

나는 단지 같은 문제가 있습니다. 내비게이션이 픽스로 설정되어 있고 내비게이션 아래에서 앙코르가 시작되기를 원합니다. window.addEventListener...내 페이지를 설정했기 때문에 나를 위해 작동하지 않는 해결책은 대신scroll-behavior:smooth 오프셋을 설정했습니다. 앙코르로 스크롤합니다. setTimeout()작품은 시간을 끝으로 스크롤을 위해 anough 경우하지만 여전히 좋은 찾고 없습니다. 내 솔루션 있도록하여, 앙코르에 상정 절대 사업부를 추가하는 것이 었습니다 height:[the height of the nav]bottom:100%. 이 경우이 div는 앙코르 요소의 상단에서 끝났고, 앙코르가 스크롤 할 위치에서 시작합니다. 이제 내가하는 모든 일은 앙코르 링크를이 절대 div 및 wor 완료 :)

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

나는 비슷한 문제에 직면했고 다음 코드를 사용하여 해결했습니다.

$(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
그것은 본질적으로 이것 과 같은 대답 입니다. 이전 질문에 대한 답변을 게시하는 경우 새로운 것을 추가하십시오. 예를 들어, 작동하는 이유를 설명 할 수 있습니다.
Artjom B.

1
나는 어떤 대답이든 그것이 작동하는 이유에 대한 일종의 설명을 가져야한다고 주장합니다. ;-)
Phill Healey
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.