web-dev-qa-db-ja.com

scrollIntoViewスクロールが遠すぎます

Divを含むテーブル行を含むスクロールバーがデータベースから動的に生成されるページがあります。各表の行はリンクのように機能し、動画プレーヤーの横にあるYouTubeプレイリストに表示されるようなものです。

ユーザーがページにアクセスすると、ユーザーが選択しているオプションはスクロールするdivの一番上に移動することになっています。この機能は機能しています。問題は、それがちょっと行き過ぎていることです。それらがオンになっているオプションと同様に、約10ピクセル高すぎます。そのため、ページにアクセスし、URLを使用して選択されたオプションを識別し、スクロールdivの上部にそのオプションをスクロールします。注:これはウィンドウのスクロールバーではなく、スクロールバーを持つdivです。

このコードを使用して、選択したオプションをdivの一番上に移動しています:

var pathArray = window.location.pathname.split( '/' );

var el = document.getElementById(pathArray[5]);

el.scrollIntoView(true);

Divの最上部に移動しますが、約10ピクセル離れています。誰でもそれを修正する方法を知っていますか?

62
Matthew Wilson

約10ピクセルの場合、_divのスクロールオフセットを次のように手動で調整できると思います。

el.scrollIntoView(true);
document.getElementById("containingDiv").scrollTop += 10;
37

次の2つの手順で実行できます。

el.scrollIntoView(true);
window.scrollBy(0, -10); // Adjust scrolling with a negative value here
58
fred727

絶対法による位置アンカー

これを行う別の方法は、オフセットによるスクロールに依存するのではなく、ページ上の希望する場所にアンカーを配置することです。私はそれが各要素のより良い制御を可能にすることを見つけます(たとえば、特定の要素に異なるオフセットが必要な場合)、またブラウザAPIの変更/相違に対してより耐性があるかもしれません。

<div id="title-element" style="position: relative;">
  <div id="anchor-name" style="position: absolute; top: -100px; left: 0" />
</div>

これで、オフセットは要素に対して-100pxとして指定されます。コードを再利用するためにこのアンカーを作成する関数を作成します。または、Reactなどの現代のJSフレームワークを使用している場合は、アンカーをレンダリングするコンポーネントを作成してこれを行い、それぞれのアンカー名とアライメントを渡します同じ要素である場合とそうでない場合がある要素。

次に使用するだけです:

const element = document.getElementById('anchor-name')
element.scrollIntoView({ behavior: 'smooth', block: 'start' });

100pxのオフセットでスムーズにスクロールします。

40
Steve Banton

適切な位置までスムーズにスクロール

正しいY座標を取得し、window.scrollToを使用するだけです。

const yourElement = document.getElementById('profilePhoto');
const yCoordinate = yourElement.getBoundingClientRect().top + window.pageYOffset;
const yOffset = -10; 

window.scrollTo({
    top: yCoordinate + yOffset,
    behavior: 'smooth'
});
19
Arseniy-II

これはChromeで機能します(スムーズなスクロールとタイミングハックなし)

要素を移動し、スクロールを開始してから元に戻します。

要素がすでに画面上にある場合、目に見える「ポップ」はありません。

pos = targetEle.style.position;
top = targetEle.style.top;
targetEle.style.position = 'relative';
targetEle.style.top = '-20px';
targetEle.scrollIntoView({behavior: 'smooth', block: 'start');
targetEle.style.top = top;
targetEle.style.position = pos;
6
Ryan How

以前の回答に基づいて、私はこれをAngular5プロジェクトで行っています。

で始まる:

// el.scrollIntoView(true);
el.scrollIntoView({
   behavior: 'smooth',
   block: 'start'
});
window.scrollBy(0, -10); 

しかし、これによりいくつかの問題が発生し、次のようにscrollBy()のsetTimeoutが必要になりました。

//window.scrollBy(0,-10);
setTimeout(() => {
  window.scrollBy(0,-10)
  }, 500);

また、MSIE11およびChrome 68+で完全に機能します。私はFFでテストしていません。 500ミリ秒は、私が挑戦する最短の遅延でした。スムーズスクロールがまだ完了していないため、低くなることができませんでした。独自のプロジェクトの必要に応じて調整します。

+1〜 Fred727 このシンプルだが効果的なソリューション。

5
PrimaryW

element.scrollIntoView()options を使用することもできます

el.scrollIntoView(
  { 
    behavior: 'smooth', 
    block: 'start' 
  },
);

ほとんどのブラウザ サポート

4
Nicholas Murray

DOMですべて同じレベルにあり、クラス名が「scroll-with-offset」であるdivにスクロールすると仮定すると、このCSSは問題を解決します。

.scroll-with-offset {    
  padding-top: 100px;
  margin-bottom: -100px;
}

ページの上部からのオフセットは100pxです。 block: 'start'で意図したとおりにのみ機能します:

element.scrollIntoView({ behavior: 'smooth', block: 'start' });

何が起こっているのかというと、divの最上部は通常の位置にありますが、それらの内部コンテンツは通常の位置より100ピクセル下で始まります。それがpadding-top:100pxの目的です。 margin-bottom:-100pxは、下のdivの余分なマージンをオフセットします。ソリューションを完全にするには、このCSSを追加して、最上部と最下部のdivのマージン/パディングをオフセットします。

.top-div {
  padding-top: 0;
}
.bottom-div {
  margin-bottom: 0;
}
3
George P

私はこれを持っています、それは私にとって見事に動作します:

// add a smooth scroll to element
scroll(el) {
el.scrollIntoView({
  behavior: 'smooth',
  block: 'start'});

setTimeout(() => {
window.scrollBy(0, -40);
}, 500);}

それが役に立てば幸い。

2

私のために働く最も簡単なソリューション:

 $('html, body').animate({ scrollTop: $(yourElement).offset().top - 20}, 800);
0
Offir Pe'er

私の主なアイデアは、スクロールするビューの上にtempDivを作成することです。私のプロジェクトで遅れることなくうまく機能します。

scrollToView = (element, offset) => {
    var rect = element.getBoundingClientRect();
    var targetY = rect.y + window.scrollY - offset;

    var tempDiv;
    tempDiv = document.getElementById("tempDiv");
    if (tempDiv) {
        tempDiv.style.top = targetY + "px";
    } else {
        tempDiv = document.createElement('div');
        tempDiv.id = "tempDiv";
        tempDiv.style.background = "#F00";
        tempDiv.style.width = "10px";
        tempDiv.style.height = "10px";
        tempDiv.style.position = "absolute";
        tempDiv.style.top = targetY + "px";
        document.body.appendChild(tempDiv);
    }

    tempDiv.scrollIntoView({ behavior: 'smooth', block: 'start' });
}

使用例

onContactUsClick = () => {
    this.scrollToView(document.getElementById("contact-us"), 48);
}

お役に立てば幸いです

0
Phan Van Linh