如何滚动查看 DOM 范围?

use*_*170 -26 javascript dom js-scrollintoview

Element接口提供了一种scrollIntoView设置所有祖先元素的滚动位置的方法,以便给定元素在屏幕上可见。

如何使用 DOM 执行类似的操作Range,也就是说,滚动需要滚动的任何内容,以便该范围在屏幕上可见?

我可能可以忍受手动计算范围的边界框并查找要滚动的元素,但我不希望以任何方式修改 DOM 的内容。

Sal*_*n A 13

Range有一个有用的方法,getBoundingClientRect它返回一个描述范围相对于视口的DOMRect位置。然后,您可以使用 将元素滚动到视图中。一个非常简单的例子:window.scrollBy

document.querySelector("#scroll-demo").addEventListener("click", function() {
  let selection = window.getSelection();
  if (selection.rangeCount === 0) {
    return;
  }
  let range = selection.getRangeAt(0);
  let rect = range.getBoundingClientRect();
  // scroll to top if:
  // - some part of selection is above the viewport
  // - some part of selection is below the viewport
  if (rect.top < 0 || rect.bottom > document.documentElement.clientHeight) {
    window.scrollBy(0, rect.y);
  }
});
Run Code Online (Sandbox Code Playgroud)
p {
  max-width: 30em;
}
p:nth-child(even) {
  background-color: #EEE;
}
#demos {
  position: fixed;
  right: 0;
  top: 0;
  padding: 1em;
  color: #FFF;
  background-color: #000A;
}
Run Code Online (Sandbox Code Playgroud)
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc aliquam ultricies quam, non porttitor diam iaculis vitae. Nulla rutrum erat et tortor aliquet bibendum. Ut suscipit sapien id accumsan rutrum. Quisque eleifend tempor dolor sit amet luctus.
  Quisque non malesuada tortor. Nam sapien orci, consectetur dignissim magna eget, cursus gravida ligula. Quisque efficitur ornare felis, et venenatis ipsum laoreet vel. Sed nunc risus, imperdiet a porttitor eget, auctor eget neque. Donec tincidunt a
  est nec sodales. Suspendisse pellentesque est at luctus interdum. Quisque justo orci, vestibulum eget sapien et, faucibus imperdiet turpis. Etiam vel volutpat orci. Nullam tellus elit, bibendum a nulla quis, porttitor euismod sem.</p>
<p>Fusce vehicula nulla quis iaculis commodo. In in efficitur urna. Quisque sem nisl, luctus id porta ac, pellentesque a tellus. Pellentesque lacinia nisl non neque bibendum accumsan. Praesent vitae facilisis dolor. Sed vel ipsum non mauris consequat aliquet.
  Pellentesque tellus purus, consequat ut erat convallis, pretium molestie justo.</p>
<p>Maecenas sit amet laoreet leo, vel consectetur purus. Nunc in rhoncus ex. Etiam ultricies mauris ac felis aliquam semper. Morbi eleifend, justo a tincidunt pellentesque, est erat tincidunt nisi, tincidunt dictum nisi ipsum id nunc. Aliquam vel libero
  ipsum. In hac habitasse platea dictumst. Curabitur rhoncus risus in ultricies tempus. Vivamus elementum augue ac elit facilisis interdum. Duis tincidunt eget tortor posuere facilisis. Suspendisse fringilla, purus et faucibus tempus, dui elit viverra
  arcu, et iaculis massa justo eget ante. Nunc maximus gravida nulla ac tristique. Etiam vel tellus erat.</p>
<p>Nunc vitae risus dignissim, ultricies turpis at, bibendum erat. Mauris at ullamcorper lorem, eget posuere arcu. Aliquam quis libero turpis. Nullam maximus nisl enim, quis pellentesque lacus efficitur non. Fusce consectetur, erat vel elementum porttitor,
  risus libero vulputate risus, at porta ante lorem nec lorem. Sed vitae dolor in nisl tincidunt dapibus. Aliquam id velit sit amet ipsum pulvinar condimentum ut quis massa. Aenean id urna a nunc efficitur pulvinar. Ut sed hendrerit lectus. Sed fringilla
  urna eu nibh egestas, ac euismod sem hendrerit. Aliquam et risus accumsan, congue leo sed, ornare lacus. Nunc luctus erat odio, ut ultricies dui efficitur ut.</p>
<p>Praesent dapibus est nulla. Cras posuere, risus vel molestie porttitor, ipsum sapien pretium dolor, vitae bibendum arcu massa eget velit. Nunc laoreet lacinia ligula, vel ullamcorper est suscipit finibus. Sed sagittis ipsum vitae odio faucibus porta.
  In hac habitasse platea dictumst. Cras vitae consectetur nisl. Ut id arcu condimentum, auctor erat quis, volutpat ligula. Nulla vitae diam at odio dapibus auctor id sed lectus. Integer ac pharetra nisi, ac tincidunt dolor. Cras nec massa et purus dictum
  faucibus eget sed nisi. Phasellus interdum urna nec sem lobortis, non condimentum erat porta. Pellentesque sodales sit amet erat ut vulputate. Sed laoreet quis eros quis mollis. Pellentesque scelerisque mauris ornare interdum commodo. Nunc id rhoncus
  purus. Nullam sed enim nec ex dignissim pretium.</p>
<div id="demos">
  Select something in the document<br>
  then scroll it outside the viewport<br>
  <button id="scroll-demo">Scroll selection into view</button>
</div>
Run Code Online (Sandbox Code Playgroud)

如果范围存在于嵌套的可滚​​动容器内,事情就会变得复杂。一个棘手的解决方案是将“最近的滚动父级”滚动到视图中并将其与视口的顶部对齐,然后使用上述逻辑将范围滚动到视图中(边界矩形将为您提供相对于视口的位置,但在此时所有滚动父级都与视口顶部对齐,因此它应该可以工作)。

Range.commonAncestorContainer对于简单的用例,一个简单的解决方案是识别包含 using和 use范围的元素Element.scrollIntoView

document.querySelector("#scroll-demo").addEventListener("click", function() {
  let selection = window.getSelection();
  if (selection.rangeCount === 0) {
    return;
  }
  let range = selection.getRangeAt(0);
  let element = range.commonAncestorContainer;
  if (element.nodeType === Node.TEXT_NODE) {
    element = element.parentElement;
  }
  element.scrollIntoView();
});
Run Code Online (Sandbox Code Playgroud)
p {
  max-width: 30em;
}
p:nth-child(even) {
  background-color: #EEE;
}
#scrollable {
  max-width: 30em;
  height: 20em;
  overflow: auto;
  box-shadow: 0 0 4px 2px #F00;
}
#demos {
  position: fixed;
  right: 0;
  top: 0;
  padding: 1em;
  color: #FFF;
  background-color: #000A;
}
Run Code Online (Sandbox Code Playgroud)
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc aliquam ultricies quam, non porttitor diam iaculis vitae. Nulla rutrum erat et tortor aliquet bibendum. Ut suscipit sapien id accumsan rutrum. Quisque eleifend tempor dolor sit amet luctus.
  Quisque non malesuada tortor. Nam sapien orci, consectetur dignissim magna eget, cursus gravida ligula. Quisque efficitur ornare felis, et venenatis ipsum laoreet vel. Sed nunc risus, imperdiet a porttitor eget, auctor eget neque. Donec tincidunt a
  est nec sodales. Suspendisse pellentesque est at luctus interdum. Quisque justo orci, vestibulum eget sapien et, faucibus imperdiet turpis. Etiam vel volutpat orci. Nullam tellus elit, bibendum a nulla quis, porttitor euismod sem.</p>
<p>Fusce vehicula nulla quis iaculis commodo. In in efficitur urna. Quisque sem nisl, luctus id porta ac, pellentesque a tellus. Pellentesque lacinia nisl non neque bibendum accumsan. Praesent vitae facilisis dolor. Sed vel ipsum non mauris consequat aliquet.
  Pellentesque tellus purus, consequat ut erat convallis, pretium molestie justo.</p>
<p>Maecenas sit amet laoreet leo, vel consectetur purus. Nunc in rhoncus ex. Etiam ultricies mauris ac felis aliquam semper. Morbi eleifend, justo a tincidunt pellentesque, est erat tincidunt nisi, tincidunt dictum nisi ipsum id nunc. Aliquam vel libero
  ipsum. In hac habitasse platea dictumst. Curabitur rhoncus risus in ultricies tempus. Vivamus elementum augue ac elit facilisis interdum. Duis tincidunt eget tortor posuere facilisis. Suspendisse fringilla, purus et faucibus tempus, dui elit viverra
  arcu, et iaculis massa justo eget ante. Nunc maximus gravida nulla ac tristique. Etiam vel tellus erat.</p>
<div id="scrollable">
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc aliquam ultricies quam, non porttitor diam iaculis vitae. Nulla rutrum erat et tortor aliquet bibendum. Ut suscipit sapien id accumsan rutrum. Quisque eleifend tempor dolor sit amet luctus.
    Quisque non malesuada tortor. Nam sapien orci, consectetur dignissim magna eget, cursus gravida ligula. Quisque efficitur ornare felis, et venenatis ipsum laoreet vel. Sed nunc risus, imperdiet a porttitor eget, auctor eget neque. Donec tincidunt
    a est nec sodales. Suspendisse pellentesque est at luctus interdum. Quisque justo orci, vestibulum eget sapien et, faucibus imperdiet turpis. Etiam vel volutpat orci. Nullam tellus elit, bibendum a nulla quis, porttitor euismod sem.</p>
  <p>Fusce vehicula nulla quis iaculis commodo. In in efficitur urna. Quisque sem nisl, luctus id porta ac, pellentesque a tellus. Pellentesque lacinia nisl non neque bibendum accumsan. Praesent vitae facilisis dolor. Sed vel ipsum non mauris consequat aliquet.
    Pellentesque tellus purus, consequat ut erat convallis, pretium molestie justo.</p>
  <p>Maecenas sit amet laoreet leo, vel consectetur purus. Nunc in rhoncus ex. Etiam ultricies mauris ac felis aliquam semper. Morbi eleifend, justo a tincidunt pellentesque, est erat tincidunt nisi, tincidunt dictum nisi ipsum id nunc. Aliquam vel libero
    ipsum. In hac habitasse platea dictumst. Curabitur rhoncus risus in ultricies tempus. Vivamus elementum augue ac elit facilisis interdum. Duis tincidunt eget tortor posuere facilisis. Suspendisse fringilla, purus et faucibus tempus, dui elit viverra
    arcu, et iaculis massa justo eget ante. Nunc maximus gravida nulla ac tristique. Etiam vel tellus erat.</p>
  <p>Nunc vitae risus dignissim, ultricies turpis at, bibendum erat. Mauris at ullamcorper lorem, eget posuere arcu. Aliquam quis libero turpis. Nullam maximus nisl enim, quis pellentesque lacus efficitur non. Fusce consectetur, erat vel elementum porttitor,
    risus libero vulputate risus, at porta ante lorem nec lorem. Sed vitae dolor in nisl tincidunt dapibus. Aliquam id velit sit amet ipsum pulvinar condimentum ut quis massa. Aenean id urna a nunc efficitur pulvinar. Ut sed hendrerit lectus. Sed fringilla
    urna eu nibh egestas, ac euismod sem hendrerit. Aliquam et risus accumsan, congue leo sed, ornare lacus. Nunc luctus erat odio, ut ultricies dui efficitur ut.</p>
  <p>Praesent dapibus est nulla. Cras posuere, risus vel molestie porttitor, ipsum sapien pretium dolor, vitae bibendum arcu massa eget velit. Nunc laoreet lacinia ligula, vel ullamcorper est suscipit finibus. Sed sagittis ipsum vitae odio faucibus porta.
    In hac habitasse platea dictumst. Cras vitae consectetur nisl. Ut id arcu condimentum, auctor erat quis, volutpat ligula. Nulla vitae diam at odio dapibus auctor id sed lectus. Integer ac pharetra nisi, ac tincidunt dolor. Cras nec massa et purus
    dictum faucibus eget sed nisi. Phasellus interdum urna nec sem lobortis, non condimentum erat porta. Pellentesque sodales sit amet erat ut vulputate. Sed laoreet quis eros quis mollis. Pellentesque scelerisque mauris ornare interdum commodo. Nunc
    id rhoncus purus. Nullam sed enim nec ex dignissim pretium.</p>
</div>
<p>Nunc vitae risus dignissim, ultricies turpis at, bibendum erat. Mauris at ullamcorper lorem, eget posuere arcu. Aliquam quis libero turpis. Nullam maximus nisl enim, quis pellentesque lacus efficitur non. Fusce consectetur, erat vel elementum porttitor,
  risus libero vulputate risus, at porta ante lorem nec lorem. Sed vitae dolor in nisl tincidunt dapibus. Aliquam id velit sit amet ipsum pulvinar condimentum ut quis massa. Aenean id urna a nunc efficitur pulvinar. Ut sed hendrerit lectus. Sed fringilla
  urna eu nibh egestas, ac euismod sem hendrerit. Aliquam et risus accumsan, congue leo sed, ornare lacus. Nunc luctus erat odio, ut ultricies dui efficitur ut.</p>
<p>Praesent dapibus est nulla. Cras posuere, risus vel molestie porttitor, ipsum sapien pretium dolor, vitae bibendum arcu massa eget velit. Nunc laoreet lacinia ligula, vel ullamcorper est suscipit finibus. Sed sagittis ipsum vitae odio faucibus porta.
  In hac habitasse platea dictumst. Cras vitae consectetur nisl. Ut id arcu condimentum, auctor erat quis, volutpat ligula. Nulla vitae diam at odio dapibus auctor id sed lectus. Integer ac pharetra nisi, ac tincidunt dolor. Cras nec massa et purus dictum
  faucibus eget sed nisi. Phasellus interdum urna nec sem lobortis, non condimentum erat porta. Pellentesque sodales sit amet erat ut vulputate. Sed laoreet quis eros quis mollis. Pellentesque scelerisque mauris ornare interdum commodo. Nunc id rhoncus
  purus. Nullam sed enim nec ex dignissim pretium.</p>
<div id="demos">
  Select something in the document<br>
  then scroll it outside the viewport<br>
  <button id="scroll-demo">Scroll selection into view</button>
</div>
Run Code Online (Sandbox Code Playgroud)