使用带有固定位置标题的scrollIntoView

时间:2012-11-28 20:48:27

标签: javascript twitter-bootstrap

我的网站标题设置为position: fixed。在我的一个页面上,我在元素上使用scrollIntoView(true)。我的问题是,当调用scrollIntoView时,元素将位于标题下方。我如何解决这个问题,以便元素显示在标题下方?

我正在使用Bootstrap框架,标题的样式为navbar navbar-fixed-top

10 个答案:

答案 0 :(得分:52)

这有点hacky但是这是一个解决方法。

var node = 'select your element';
var yourHeight = 'height of your fixed header';

// scroll to your element
node.scrollIntoView(true);

// now account for fixed header
var scrolledY = window.scrollY;

if(scrolledY){
  window.scroll(0, scrolledY - yourHeight);
}

答案 1 :(得分:22)

您可以使用CSS解决此问题,方法是将padding-top和否定margin-top应用于要滚动到的元素。

Demo

document.querySelector('.scroll-to-working-inline').addEventListener('click', function() {
  document.querySelector('.working-inline').scrollIntoView();
});

document.querySelector('.scroll-to-working-block').addEventListener('click', function() {
  document.querySelector('.working-block').scrollIntoView();
});

document.querySelector('.scroll-to-broken').addEventListener('click', function() {
  document.querySelector('.broken').scrollIntoView();
});
body {
  margin: 0;
  padding-top: 60px;
}

header {
  position: fixed;
  top: 0;
  background-color: tomato;
  color: white;
  width: 100%;
  height: 60px;
  line-height: 60px;
  text-align: center;
}

[class^='working'],
[class^='broken'] {
  font-size: 3rem;
}

.working-inline {
  padding-top: 60px;
  margin-top: -60px;
}

.working-block {
  padding-top: 60px;
  margin-top: -60px;
}
<header>
  scroll to...
  <button class="scroll-to-working-inline">working inline element</button>
  <button class="scroll-to-working-block">working block element</button>
  <button class="scroll-to-broken">broken element</button>
</header>

<main>
  <p>Sql daemon epoch all your base are belong to us packet system perl semaphore. Interpreter warez pragma kilo worm back door baz continue chown blob unix Dennis Ritchie stack mutex bar throw fopen man pages linux. Sql suitably small values bit infinite loop pwned rm -rf.</p>
  
  <a class="working-inline">Working inline</a>
  
  <p>Syn baz man pages unix vi crack leapfrog semaphore fail pwned afk null socket cd long leet emacs Donald Knuth bin grep todo pragma stdio.h January 1, 1970. Alloc gc system new finally sql stack trace syn mainframe cat machine code memory leak server salt flood tunnel in back door thread. Bytes fatal throw ctl-c Dennis Ritchie over clock eof tera perl regex.</p>
  
  <div class="working-block">Working block element</div>
  
  <p>Public injection class unix malloc error script kiddies packet less fail int I'm sorry Dave, I'm afraid I can't do that. Tarball memory leak double rsa pwned public all your base are belong to us. False bytes bang bar tarball semaphore warez cd port daemon exception mountain dew sql mainframe gcc ifdef chown private.</p>
  
  <div class="broken">Broken element</div>
  
  <p>Daemon bubble sort protected mutex overflow grep snarf crack warez I'm compiling bit if memory leak Starcraft nak script kiddies long it's a feature. Hello world public server James T. Kirk injection terminal wannabee race condition syn alloc. Gobble leapfrog finally bypass concurrently while irc gurfle do back door blob man pages sql over clock.</p>
  
  <p>Char hello world then man pages ascii long salt while char fatal do boolean tunnel in system else foo packet sniffer float terminal int default. Trojan horse ssh ifdef /dev/null chown cache error protocol afk todo rm -rf mainframe piggyback pwned regex xss warez Starcraft try catch stdio.h bubble sort. It's a feature I'm sorry Dave, I'm afraid I can't do that *.* port bypass ip.</p>
  
  <p>Stdio.h epoch mutex flood wannabee do race condition sql access exception. Bar pragma man pages dereference flush todo highjack while buffer bit nak big-endian syn xss salt for d00dz. Leslie Lamport linux server error hexadecimal snarf tunnel in rm -rf firewall then shell all your base are belong to us.</p>

  <p>Ascii gcc grep int flood kilo linux access mailbomb hash *.* fork semaphore frack else win bar ssh Leslie Lamport. Man pages strlen cache gnu segfault tarball race condition perl packet sniffer root cookie private chown d00dz January 1, 1970. Rsa public crack bit warez throw for void concurrently ip mutex.</p>
  
  <p>Char hello world then man pages ascii long salt while char fatal do boolean tunnel in system else foo packet sniffer float terminal int default. Trojan horse ssh ifdef /dev/null chown cache error protocol afk todo rm -rf mainframe piggyback pwned regex xss warez Starcraft try catch stdio.h bubble sort. It's a feature I'm sorry Dave, I'm afraid I can't do that *.* port bypass ip.</p>
  
  <p>Stdio.h epoch mutex flood wannabee do race condition sql access exception. Bar pragma man pages dereference flush todo highjack while buffer bit nak big-endian syn xss salt for d00dz. Leslie Lamport linux server error hexadecimal snarf tunnel in rm -rf firewall then shell all your base are belong to us.</p>

  <p>Ascii gcc grep int flood kilo linux access mailbomb hash *.* fork semaphore frack else win bar ssh Leslie Lamport. Man pages strlen cache gnu segfault tarball race condition perl packet sniffer root cookie private chown d00dz January 1, 1970. Rsa public crack bit warez throw for void concurrently ip mutex.</p>
  
  <p>Char hello world then man pages ascii long salt while char fatal do boolean tunnel in system else foo packet sniffer float terminal int default. Trojan horse ssh ifdef /dev/null chown cache error protocol afk todo rm -rf mainframe piggyback pwned regex xss warez Starcraft try catch stdio.h bubble sort. It's a feature I'm sorry Dave, I'm afraid I can't do that *.* port bypass ip.</p>
  
  <p>Stdio.h epoch mutex flood wannabee do race condition sql access exception. Bar pragma man pages dereference flush todo highjack while buffer bit nak big-endian syn xss salt for d00dz. Leslie Lamport linux server error hexadecimal snarf tunnel in rm -rf firewall then shell all your base are belong to us.</p>

  <p>Ascii gcc grep int flood kilo linux access mailbomb hash *.* fork semaphore frack else win bar ssh Leslie Lamport. Man pages strlen cache gnu segfault tarball race condition perl packet sniffer root cookie private chown d00dz January 1, 1970. Rsa public crack bit warez throw for void concurrently ip mutex.</p>
</main>

答案 2 :(得分:14)

以下代码生成一个平滑的滚动到元素的顶部,并带有固定标题的偏移量:

var topOfElement = document.querySelector('#targetElement').offsetTop - XX;
window.scroll({ top: topOfElement, behavior: "smooth" });

其中XX是固定标题的高度。

答案 3 :(得分:1)

如果有任何人遇到问题,你的容器div的上边距在scrollIntoView之后被忽略,那么不要将你的元素滚动到视图中,而是相对于其父滚动容器执行scrollTop,如下所示:

var topOfElementToView= $('#elementToScroll').position().top;
$('#parentScrollingContainer').scrollTop(topOfElementToView);

在此帖子中获得了user113716的回答:How to go to a specific element on page?

答案 4 :(得分:1)

scroll-margin-top:$ header-height;

有一种新的非骇客方式可实现此目的,该方式适用于标准HTML链接和js scrollIntoView。使用scroll-margin-top CSS属性。

您可以使用CSS属性scroll-margin-top与标题相同的高度。

这不会增加任何可见的边距,但在链接到元素时会在元素上方增加间距。

/*
  Add a scroll-margin-top to all elements that you want to be able to link to.
  (you may need to select items that don't have an id as well)
*/

*[id] {
  scroll-margin-top: 100px;
}

Can I use scroll-margin-top?在IE和Edge HTML(2020年前)中不起作用。

MDN docs scroll-margin-top


我在下面的演示中添加了平滑滚动,因此很明显这是使用scrollIntoView。

Veiw in codepen

links = [ ...document.getElementsByClassName("js-link")]
links.map(element => {
  element.addEventListener("click", e => {
    e.preventDefault()
    document.getElementById(e.target.dataset.target).scrollIntoView({
      behavior: "smooth", block: "start", inline: "nearest"
    })
    // For safari, ie and edge (pre-2020)
    // document.getElementById(e.target.dataset.target).scrollIntoView(true)
  })
})
body {
  margin: 0;
}

header {
  position: sticky;
  top: 0;
  left: 0;
  right: 0;
  height: 100px;
  background: #eee;
  display: flex;
  align-items: center;
}
header a {
  padding: 0.5em;
}

h1 {
  padding: 0.7em;
}

*[id] {
  scroll-margin-top: 100px;
}

p {
  padding: 1em;
}
<header>
  <h1>page title</h1>
  <nav>
    <a href="#p1" class="js-link" data-target="p1">1</a>
    <a href="#p2" class="js-link" data-target="p2">2</a>
    <a href="#p3" class="js-link" data-target="p3">3</a>
    <a href="#p4" class="js-link" data-target="p4">4</a>
    <a href="#p5" class="js-link" data-target="p5">5</a>
  </nav>
</header>

<main>
  <p id="p1">
    paragraph 1.
    <br>
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsu
  </p>
  <p id="p2">
    paragraph 2.
    <br>
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsu
  </p>
  <p id="p3">
    paragraph 3.
    <br>
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsu
  </p>
  <p id="p4">
    paragraph 4.
    <br>
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsu
  </p>
  <p id="p5">
    paragraph 5.
    <br>
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsu
  </p>
</main>

答案 5 :(得分:0)

如果某人具有固定的导航栏,该导航栏在滚动后隐藏Header \ Title,则以下为解决方法(基于@coco puffs的答案和this one):

let anchorLinks = document.querySelectorAll('a[href^="#"]')

for (let item of anchorLinks) {
  item.addEventListener('click', (e) => {
    let hashVal = item.getAttribute('href')
    let topOfElement = document.querySelector(hashVal).offsetTop - 70

    window.scroll({ top: topOfElement, behavior: "smooth" })
    history.pushState(null, null, hashVal)
    e.preventDefault()
  })
}

使用代码70px

答案 6 :(得分:0)

我怀疑对个人有效的方法在很大程度上取决于他们的页面布局,因此,此答案旨在作为一种附加选项,而不是篡夺任何人。

我要做的就是传递false滚动到视图scrollIntoView(false)

it('should be able to click a button selector', function () {
    let EC = protractor.ExpectedConditions;
    let button = element(by.css('.my-button-css));

    browser.executeScript('arguments[0].scrollIntoView(false)', button.getWebElement()).then(function () {
        browser.wait(EC.elementToBeClickable(button), 3000).then(function () {
            expect(button.isDisplayed()).toBeTruthy();
            button.click();

            // more test logic here

        });
    });
});

感谢reboot jeff

答案 7 :(得分:0)

尝试以下方法。对我来说很好:

  const headerHeight = 50; /* PUT HEADER HEIGHT HERE */
  const buffer = 25; /* MAY NOT BE NEEDED */
  const scrollToEl = document.querySelector("#YOUR-ELEMENT-SELECTOR");

  const topOfElement = window.pageYOffset + scrollToEl.getBoundingClientRect().top - headerHeight - buffer;
  window.scroll({ top: topOfElement, behavior: "smooth" });

答案 8 :(得分:0)

一个很棒的简单解决方案(受Sanyam Jain的评论启发)是使用{block: 'center'}来使选择垂直居中,如下所示:

scrollIntoView({block: 'center'})

编辑-我在MDN页面上不幸地发现此功能是“实验性的-不应在生产中使用”。另外,IE不支持它(如果需要)。

enter image description here

答案 9 :(得分:0)

对我来说,将元素滚动到窗口中心是可行的。

scrollIntoViewIfNeeded({ block: "center" }) 可以很好地做到这一点,但遗憾的是浏览器兼容性有限(https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded)。它不适用于 IE 和 Firefox。

但是,您可以自己轻松构建此函数:

function scrollIntoCenter(element) {
  // first scroll element into view. This means element is at the very top.
  element.scrollIntoView();
  
  // calculate new scrollYPosition by subtracting half of window-height
  let y = window.scrollY - window.innerHeight/2;
  
  // scroll up by half of window height
  window.scroll(0, y);
}