[英]How to use scrollIntoView with overflow:hidden and without scrolling the page?
如何在overflow:hidden
容器上使用 scrollIntoView overflow:hidden
並且它不應該滾動頁面?
這是一個示例:在容器<div class="cnt'>
中的頁面文本底部,它具有固定寬度和溢出隱藏。我想在不滾動頁面的情況下滾動此容器中的項目。
在頁面頂部的兩個按鈕滾動到第一個和最后一個元素。 如果我單擊按鈕,它將滾動容器中的文本並滾動到頁面底部的該容器。
我不能使用 scrollLeft 因為溢出是隱藏的。 :(
有人知道如何解決嗎?
const cnt = document.querySelector('.cnt') const spanElements = cnt.querySelectorAll('span'); const lastSpan = spanElements[spanElements.length - 1] const firstSpan = spanElements[0] lastSpan.scrollIntoView() const buttons = Array.from(document.querySelectorAll('button')) const [buttonToFirstEl, buttonToLastEl] = buttons; buttonToFirstEl.onclick = function() { firstSpan.scrollIntoView() } buttonToLastEl.onclick = function() { lastSpan.scrollIntoView() }
.cnt { width: 90px; overflow: hidden; white-space: nowrap; padding: 8px; border: solid #ccc 1px; } .filler { width: 100%; height: 200px; border: dashed 2px #ccc; margin: 20px; } .root { border: solid 1px; }
<div class="root"> <button id="button">scroll to first element</button> <button id="button">scroll to last element</button> <div class="filler"> </div> <div class="filler"> </div> <div class="filler"> </div> <div class="filler"> </div> <div class="cnt"> <span> first:tessst </span> <span> 2:dddd </span> <span> 3:cccddd </span> <span> 4:rreeee </span> <span> last:dddrreddd </span> </div> </div>
如果你想在 .cnt 類中滾動元素
.cnt 跨度{
/* relative + block for make elements solid & listed*/ position : relative; display : block;
color: red; font-size : 16px;
}
.cnt {
width: 90px;
/* for example 28px */
height : 28px;
overflow: hidden;
white-space: nowrap;
padding: 4px;
border: solid black 1px;
/* overflow y or x for making scroll*/
overflow-y : scroll;
}
為了正確地做到這一點(即支持所有寫入模式、方向和塊內聯選項),您基本上必須從頭開始重寫scrollIntoView ,同時省略向上滾動框樹的循環。 這不是一項微不足道的任務。
如果您不需要防彈解決方案,您可以簡單地獲取最近的滾動框並檢查它應該滾動多少以顯示元素的開頭:
const cnt = document.querySelector('.cnt') const spanElements = cnt.querySelectorAll('span'); const lastSpan = spanElements[spanElements.length - 1] const firstSpan = spanElements[0] const buttons = Array.from(document.querySelectorAll('button')) const [buttonToFirstEl, buttonToLastEl] = buttons; buttonToFirstEl.onclick = function() { scrollIntoParentView( firstSpan ); } buttonToLastEl.onclick = function() { scrollIntoParentView( lastSpan ); } function scrollIntoParentView( elem, options ) { const directions = getSimpleScrollIntoViewDirections( elem, options ); const left = directions.inline_direction || 0; const top = directions.block_direction || 0; const new_options = { left, top, behavior: (options && options.behavior) || "auto" }; directions.scrolling_box.scrollBy( new_options ); } function getSimpleScrollIntoViewDirections( elem, { block = "start", inline = "start" } = {} ) { const element_bbox = elem.getBoundingClientRect(); const scrolling_box = getNearestScrollingBox( elem ); const scrolling_box_bbox = scrolling_box.getBoundingClientRect(); const block_direction = Math.round( element_bbox.top - scrolling_box_bbox.top); const inline_direction = Math.round( element_bbox.left - scrolling_box_bbox.left); return { scrolling_box, block_direction, inline_direction }; } function getNearestScrollingBox( elem ) { if( !elem.isConnected ) { return null; } const elem_computed_styles = getComputedStyle( elem ); // not in specs, but that seems to be what browser implementations do if( elem_computed_styles.getPropertyValue( 'position' ) === "fixed" ) { return null; } const scrolling_box = elem.parentElement; if( !scrolling_box ) { return elem === document.scrollingElement ? null : document.scrollingElement; } const computed_styles = getComputedStyle( scrolling_box ); const scroll_x = computed_styles.getPropertyValue( "overflow-x"); const scroll_y = computed_styles.getPropertyValue( "overflow-y"); if( (scroll_x === 'clip' && scroll_y === 'clip') || (scrolling_box.offsetHeight <= scrolling_box.scrollingHeight) || (scrolling_box.offsetWidth <= scrolling_box.scrollingWidth) ) { return getNearestScrollingBox( scrolling_box ); } return scrolling_box; }
.cnt { width: 90px; overflow: hidden; white-space: nowrap; padding: 8px; border: solid #ccc 1px; } .filler { width: 100%; height: 200px; border: dashed 2px #ccc; margin: 20px; } .root { border: solid 1px; }
<div class="root"> <button id="button">scroll to first element</button> <button id="button">scroll to last element</button> <div class="filler"> </div> <div class="filler"> </div> <div class="filler"> </div> <div class="filler"> </div> <div class="cnt"> <span> first:tessst </span> <span> 2:dddd </span> <span> 3:cccddd </span> <span> 4:rreeee </span> <span> last:dddrreddd </span> </div> </div>
scrollLeft
和scrollTop
與overflow:hidden
配合得很好。 我在第一個 span 元素而不是它的容器上檢查scrollLeft
屬性
更改span的父元素上的scrollLeft
,解決這個問題
firstSpan.parentElement.scrollLeft = 0;
const cnt = document.querySelector('.cnt') const spanElements = cnt.querySelectorAll('span'); const lastSpan = spanElements[spanElements.length - 1] const firstSpan = spanElements[0] lastSpan.scrollIntoView() const buttons = Array.from(document.querySelectorAll('button')) const [buttonToFirstEl, buttonToLastEl] = buttons; buttonToFirstEl.onclick = function() { firstSpan.parentElement.scrollLeft = 0; } buttonToLastEl.onclick = function() { const cnt = lastSpan.parentElement; cnt.scrollLeft = cnt.scrollWidth; }
.cnt { width: 90px; overflow: hidden; white-space: nowrap; padding: 8px; border: solid #ccc 1px; } .filler { width: 100%; height: 200px; border: dashed 2px #ccc; margin: 20px; } .root { border: solid 1px; }
<div class="root"> <button id="button">scroll to first element</button> <button id="button">scroll to last element</button> <div class="filler"> </div> <div class="filler"> </div> <div class="filler"> </div> <div class="filler"> </div> <div class="cnt"> <span> first:tessst </span> <span> 2:dddd </span> <span> 3:cccddd </span> <span> 4:rreeee </span> <span> last:dddrreddd </span> </div> </div>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.