テーブルの上下にある水平スクロールバー


159

私はとても大きい table私のページです。そこで、テーブルの下部に水平スクロールバーを配置することにしました。しかし、このスクロールバーもテーブルの一番上に配置したいと思います。

テンプレートにあるのはこれです:

<div style="overflow:auto; width:100%; height:130%">
<table id="data" style="width:100%">...</table>
</div>

これはHTMLとCSSでのみ可能ですか?


1
stackoverflow.com/questions/2274627/… この解決策は便利だと思いました。
VARSHA DAS 2015

回答:


234

要素の上にある2番目の水平スクロールバーをシミュレートするには、水平スクロールがある要素の上に、スクロールバーにdiv十分な高さの「ダミー」を配置します。次に、ダミー要素と実際の要素の「スクロール」イベントのハンドラーをアタッチして、どちらかのスクロールバーが移動されたときに他の要素を同期させます。ダミー要素は、実際の要素の上にある2番目の水平スクロールバーのように見えます。

ライブの例についてはこのフィドルを参照してください

これがコードです

HTML:

<div class="wrapper1">
  <div class="div1"></div>
</div>
<div class="wrapper2">
  <div class="div2">
    <!-- Content Here -->
  </div>
</div>

CSS:

.wrapper1, .wrapper2 {
  width: 300px;
  overflow-x: scroll;
  overflow-y:hidden;
}

.wrapper1 {height: 20px; }
.wrapper2 {height: 200px; }

.div1 {
  width:1000px;
  height: 20px;
}

.div2 {
  width:1000px;
  height: 200px;
  background-color: #88FF88;
  overflow: auto;
}

JS:

$(function(){
  $(".wrapper1").scroll(function(){
    $(".wrapper2").scrollLeft($(".wrapper1").scrollLeft());
  });
  $(".wrapper2").scroll(function(){
    $(".wrapper1").scrollLeft($(".wrapper2").scrollLeft());
  });
});

本当に素晴らしい答えです!どうもありがとう!:)だからあなたの例を使ってみましたが、上のバーが機能しません、そして幅を広げようとするとスクロールバーが消えます。なぜか?
ソア

1
機能しましたか?jQueryの詳細については、api.jquery.com / scrollLeftを参照してください (もちろん、onscrollハンドラーを直接アタッチすることにより、jQueryなしでそれを行うことができます。)JSを持たないユーザーのための適切なパフォーマンス低下のために、JSによってDOMにダミーdivを追加できます。 。
StanleyH 2010年

1
はい、動作しました。<head>に<script type = "text / javascript" src = "path"> </ script>を追加するだけでした。したがって、jqueryを追加するたびに、@ fudgeyが追加したものを追加する必要がありましたか?申し訳ありませんが、javascriptとjqueryはまだ私にとって中国語の一種です
psoares

4
@StanleyH:div内のテーブルの幅を自動的に取得するように設定する方法 div2の幅を手動で指定したくありませんが、div2に含まれるテーブルの幅を自動的に取得します。
sqlchild 2014年

3
@CodyGuldner:divを設定して、内部のテーブルの幅を自動的に取得する方法 div2の幅を手動で指定したくありませんが、div2に含まれるテーブルの幅を自動的に取得します。
sqlchild 2014年

38

jquery.doubleScrollプラグインを使用してみてください:

jQuery:

$(document).ready(function(){
  $('#double-scroll').doubleScroll();
});

CSS:

#double-scroll{
  width: 400px;
}

HTML:

<div id="double-scroll">
  <table id="very-wide-element">
    <tbody>
      <tr>
        <td></td>
      </tr>
    </tbody>
  </table>
</div>

5
jQueryUIを必要としないPawelの素晴らしいプラグインのバージョンについては、github.com / avianey / jqDoubleScrollを参照してください。
fatal_error 2016

1
リンクすると、メンテナンスされていないGitHubにつながり、リンクが壊れています。実際のjsを試していません。
ポールゴルバス

19

まず第一に、素晴らしい答え、@ StanleyH。動的な幅のダブルスクロールコンテナーを作成する方法を誰かが疑問に思っている場合:

CSS

.wrapper1, .wrapper2 { width: 100%; overflow-x: scroll; overflow-y: hidden; }
.wrapper1 { height: 20px; }
.div1 { height: 20px; }
.div2 { overflow: none; }

js

$(function () {
    $('.wrapper1').on('scroll', function (e) {
        $('.wrapper2').scrollLeft($('.wrapper1').scrollLeft());
    }); 
    $('.wrapper2').on('scroll', function (e) {
        $('.wrapper1').scrollLeft($('.wrapper2').scrollLeft());
    });
});
$(window).on('load', function (e) {
    $('.div1').width($('table').width());
    $('.div2').width($('table').width());
});

html

<div class="wrapper1">
    <div class="div1"></div>
</div>
<div class="wrapper2">
    <div class="div2">
        <table>
            <tbody>
                <tr>
                    <td>table cell</td>
                    <td>table cell</td>
                    <!-- ... -->
                    <td>table cell</td>
                    <td>table cell</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

デモ

http://jsfiddle.net/simo/67xSL/


3
$('.div1').width( $('.div1')[0].scrollWidth)コンテンツの実際のスクロール幅を取得するために使用します。テーブルのようなコンテナーを特に使用していない場合に役立ちます。@simo素晴らしい努力仲間。
Clain Dsilva、2015

明確にするために、「div2」div内のコンテンツの幅がそこにあるサーバー側の動的コンテンツのために可変である私のコードが機能するように、コードをscrollWidthに変更する必要もありました。
AdamJones

15

JQueryなし(2017)

あなたはJQueryを必要としないかもしれないので、ここに@StanleyH回答に基づいた実用的なバニラJSバージョンがあります:

var wrapper1 = document.getElementById('wrapper1');
var wrapper2 = document.getElementById('wrapper2');
wrapper1.onscroll = function() {
  wrapper2.scrollLeft = wrapper1.scrollLeft;
};
wrapper2.onscroll = function() {
  wrapper1.scrollLeft = wrapper2.scrollLeft;
};
#wrapper1, #wrapper2{width: 300px; border: none 0px RED;
overflow-x: scroll; overflow-y:hidden;}
#wrapper1{height: 20px; }
#wrapper2{height: 100px; }
#div1 {width:1000px; height: 20px; }
#div2 {width:1000px; height: 100px; background-color: #88FF88;
overflow: auto;}
<div id="wrapper1">
    <div id="div1">
    </div>
</div>
<div id="wrapper2">
    <div id="div2">
    aaaa bbbb cccc dddd aaaa bbbb cccc 
    dddd aaaa bbbb cccc dddd aaaa bbbb 
    cccc dddd aaaa bbbb cccc dddd aaaa 
    bbbb cccc dddd aaaa bbbb cccc dddd
    </div>
</div>


幅がわからない場合、これは実際にはレスポンシブ/ダイナミックではありません
eladシルバー

はい!@StanleyHによる元の回答と同じ警告があります
rap-2-h

11

あなたのために仕事をするjQueryプラグインを使うことができます:

プラグインはすべてのロジックを処理します。


2
このプラグインはsuwala / jquery.doubleScrollプラグインと同じことを行いますが、window.resizeで幅を再計算するなどのオプションがあります
IvanHušnjakSep

1
また、jquery UIにも依存しません。
tribe84 2015

1
私はこのプラグインをお勧めします。それはsuwala / jquery.doubleScrollの改善されたバージョンのように見え、私のために機能します
Russell England

最初に素晴らしいプラグインをありがとう!ただし、スクロール方向に問題があります:rtl。正しく対応していないようです。javascriptsの達人のいずれかがそれを修正する方法を知っている場合、フィドルはjsfiddle.net/qsn7tupc/3です。Chromeでは機能しますが、他のブラウザでは機能しないことに注意してください。
Vlado

10

StanleyHの答えは素晴らしかったが、残念なバグが1つありました。スクロールバーの影付きの領域をクリックしても、クリックした選択にジャンプしなくなりました。代わりに、スクロールバーの位置が非常に小さく、やや煩わしい増分になります。

テスト済み:4バージョンのFirefox(100%影響あり)、4バージョンのChrome(50%影響あり)。

これが私のjsfiddleです。これを回避するには、一度に1つのonScroll()イベントのみをトリガーできるon / off(true / false)変数を使用します。

var scrolling = false;
$(".wrapper1").scroll(function(){
    if(scrolling) {
      scrolling = false;
      return true;
    }
    scrolling = true;
    $(".wrapper2")
        .scrollLeft($(".wrapper1").scrollLeft());
});
$(".wrapper2").scroll(function(){
    if(scrolling) {
      scrolling = false;
      return true;
    }
      scrolling = true;
    $(".wrapper1")
        .scrollLeft($(".wrapper2").scrollLeft());
});

回答が承認された問題の動作:

実際に望ましい行動:

それで、なぜこれが起こるのですか?コードを実行すると、wrapper1がwrapper2のscrollLeftを呼び出し、wrapper2がwrapper1のscrollLeftを呼び出し、これを無限に繰り返すため、無限ループの問題が発生します。または、むしろ:ユーザーの継続的なスクロールがwrapperxのスクロールの呼び出しと競合し、イベントの競合が発生し、最終結果がスクロールバーでジャンプしなくなります。

これが誰かを助けてくれることを願っています!


素晴らしい説明!実際、それは無限ループを行っていました
アーメド・アブド

うん。サポートありがとうございます!参考になります。
Giang D.MAI、

3

スクローラーのリンクは機能しましたが、書かれているように、明るいスクロールバーの部分をクリックして押したままにすると(スクローラーをドラッグするときではなく)、ループが作成され、ほとんどのブラウザーでスクロールが遅くなります。

私はそれをフラグで修正しました:

$(function() {
    x = 1;
    $(".wrapper1").scroll(function() {
        if (x == 1) {
            x = 0;
            $(".wrapper2")
                .scrollLeft($(".wrapper1").scrollLeft());
        } else {
            x = 1;
        }
    });


    $(".wrapper2").scroll(function() {
        if (x == 1) {
            x = 0;
            $(".wrapper1")
                .scrollLeft($(".wrapper2").scrollLeft());
        } else {
            x = 1;
        }
    });
});

これは、ここでも提案された回答で私が抱えていた問題を解決します。ただし、これは問題をわずかに軽減するだけで、スクロールする距離が十分に長い場合は、段階的/低速のスクロールが発生する可能性があります。
ダン寺院

条件付き/フラグを使用すると、このソリューションは適切に機能し、テストはブラウザーでJavaScriptが適用されていなくても予想される動作と一致します。
userabuser

3

@HoldOffHungerと@bobinceの回答に基づくJavaScriptのみのソリューション

<div id="doublescroll">

function DoubleScroll(element) {
            var scrollbar= document.createElement('div');
            scrollbar.appendChild(document.createElement('div'));
            scrollbar.style.overflow= 'auto';
            scrollbar.style.overflowY= 'hidden';
            scrollbar.firstChild.style.width= element.scrollWidth+'px';
            scrollbar.firstChild.style.paddingTop= '1px';
            scrollbar.firstChild.appendChild(document.createTextNode('\xA0'));
            var running = false;
            scrollbar.onscroll= function() {
                if(running) {
                    running = false;
                    return;
                }
                running = true;
                element.scrollLeft= scrollbar.scrollLeft;
            };
            element.onscroll= function() {
                if(running) {
                    running = false;
                    return;
                }
                running = true;
                scrollbar.scrollLeft= element.scrollLeft;
            };
            element.parentNode.insertBefore(scrollbar, element);
        }

    DoubleScroll(document.getElementById('doublescroll'));

3

@StanleyHソリューションに基づいて、私はAngularJSディレクティブjsFiddleのデモを作成しました

使いやすい:

<div data-double-scroll-bar-horizontal> {{content}} or static content </div>

AngularJS開発者向け


31
「jQueryは不要です。」ええ、単なるフレームワーク全体です。大したことはありません。
PitaJ 2015

2

私の知る限り、これはHTMLとCSSでは不可能です。


よくこれは私が考えたものである、実際に..しかし、誰もがこれとこれを行うための最善の方法..行っている場合、私は知らたい
psoares

HTMLとCSSの場合、最善の方法はありません。それは単に不可能です。この種の機能を使用するには、JavaScriptなどの他の手法を使用する必要があります。
Justus Romijn

1
探し始めるためのヒントを教えてください。
ソア

2
これは質問に対する答えを提供しません。批評したり、著者に説明を要求するには、投稿の下にコメントを残してください。
SSA、2014

2
@SSAそれは質問に答えます。質問は「これはHTMLとCSSでのみ可能ですか?」その答えは「ノー」です。
punkrockbuddyholly

2

バニラJavascript / Angularでは、次のようにできます。

scroll() {
    let scroller = document.querySelector('.above-scroller');
    let table = document.querySelector('.table');
    table.scrollTo(scroller.scrollLeft,0);
  }

HTML:

<div class="above-scroller" (scroll)="scroll()">
  <div class="scroller"></div>
</div>
<div class="table" >
  <table></table>
</div>

CSS:

.above-scroller  {
   overflow-x: scroll;
   overflow-y:hidden;
   height: 20px;
   width: 1200px
 }

.scroller {
  width:4500px;
  height: 20px;
}

.table {
  width:100%;
  height: 100%;
  overflow: auto;
}

1

StanleyHの答えを拡張して、必要な最小値を見つけようとすると、以下が実装されたものです。

JavaScript(のような場所から1回呼び出されます$(document).ready()):

function doubleScroll(){
        $(".topScrollVisible").scroll(function(){
            $(".tableWrapper")
                .scrollLeft($(".topScrollVisible").scrollLeft());
        });
        $(".tableWrapper").scroll(function(){
            $(".topScrollVisible")
                .scrollLeft($(".tableWrapper").scrollLeft());
        });
}

HTML(幅によってスクロールバーの長さが変わることに注意してください):

<div class="topScrollVisible" style="overflow-x:scroll">
    <div class="topScrollTableLength" style="width:1520px; height:20px">
    </div>
</div>
<div class="tableWrapper" style="overflow:auto; height:100%;">
    <table id="myTable" style="width:1470px" class="myTableClass">
...
    </table>

それでおしまい。


1

@simoの回答を実装して、すべてのangular / nativeJsファンに

HTML(変更なし)

<div class="top-scroll-wrapper">
    <div class="top-scroll"></div>
</div>

CSS(変更なし、幅:90%が私のデザインです)

.top-scroll-wrapper { width: 90%;height: 20px;margin: auto;padding: 0 16px;overflow-x: auto;overflow-y: hidden;}
.top-scroll { height: 20px; }

JS(のようなonload)またはngAfterViewChecked(すべてasはのTypeScript

let $topscroll = document.querySelector(".top-scroll") as HTMLElement
let $topscrollWrapper = document.querySelector(".top-scroll-wrapper") as HTMLElement
let $table = document.querySelectorAll('mat-card')[3] as HTMLElement

$topscroll.style.width = totalWidth + 'px'
$topscrollWrapper.onscroll = e => $table.scroll((e.target as HTMLElement).scrollLeft, 0)
$table.onscroll = e => $topscrollWrapper.scroll((e.target as HTMLElement).scrollLeft, 0)

0

iscroll.jsをwebkitブラウザーまたはモバイルブラウザーで使用している場合は、次の方法を試してください。

$('#pageWrapper>div:last-child').css('top', "0px");

0

これを実現するためのAngularJsディレクティブ:これを使用するには、要素にcssクラスdouble-hscrollを追加します。これにはjQueryとAngularJが必要です。

import angular from 'angular';

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $compile) {
  $scope.name = 'Dual wielded horizontal scroller';
});

app.directive('doubleHscroll', function($compile) {
  return {
restrict: 'C',
link: function(scope, elem, attr){

  var elemWidth = parseInt(elem[0].clientWidth);

  elem.wrap(`<div id='wrapscroll' style='width:${elemWidth}px;overflow:scroll'></div>`); 
  //note the top scroll contains an empty space as a 'trick' 
  $('#wrapscroll').before(`<div id='topscroll' style='height:20px; overflow:scroll;width:${elemWidth}px'><div style='min-width:${elemWidth}px'> </div></div>`);

  $(function(){
    $('#topscroll').scroll(function(){
      $("#wrapscroll").scrollLeft($("#topscroll").scrollLeft());
    });
    $('#wrapscroll').scroll(function() {
      $("#topscroll").scrollLeft($("#wrapscroll").scrollLeft());
    });

  });  

}

  };


});

0

これがVueJSの例です

index.page

<template>
  <div>
    <div ref="topScroll" class="top-scroll" @scroll.passive="handleScroll">
      <div
        :style="{
          width: `${contentWidth}px`,
          height: '12px'
        }"
      />
    </div>
    <div ref="content" class="content" @scroll.passive="handleScroll">
      <div
        :style="{
          width: `${contentWidth}px`
        }"
      >
        Lorem ipsum dolor sit amet, ipsum dictum vulputate molestie id magna,
        nunc laoreet maecenas, molestie ipsum donec lectus ut et sit, aut ut ut
        viverra vivamus mollis in, integer diam purus penatibus. Augue consequat
        quis phasellus non, congue tristique ac arcu cras ligula congue, elit
        hendrerit lectus faucibus arcu ligula a, id hendrerit dolor nec nec
        placerat. Vel ornare tincidunt tincidunt, erat amet mollis quisque, odio
        cursus gravida libero aliquam duis, dolor sed nulla dignissim praesent
        erat, voluptatem pede aliquam. Ut et tellus mi fermentum varius, feugiat
        nullam nunc ultrices, ullamcorper pede, nunc vestibulum, scelerisque
        nunc lectus integer. Nec id scelerisque vestibulum, elit sit, cursus
        neque varius. Fusce in, nunc donec, volutpat mauris wisi sem, non
        sapien. Pellentesque nisl, lectus eros hendrerit dui. In metus aptent
        consectetuer, sociosqu massa mus fermentum mauris dis, donec erat nunc
        orci.
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      contentWidth: 1000
    }
  },
  methods: {
    handleScroll(event) {
      if (event.target._prevClass === 'content') {
        this.$refs.topScroll.scrollLeft = this.$refs.content.scrollLeft
      } else {
        this.$refs.content.scrollLeft = this.$refs.topScroll.scrollLeft
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.top-scroll,
.content {
  overflow: auto;
  max-width: 100%;
}
.top-scroll {
  margin-top: 50px;
}
</style>

height: 12px.. メモを12pxにしたので、Macユーザーにも気付かれます。しかし、ウィンドウの場合、0.1pxで十分です


-1

スクロール方向に問題があります:rtl。プラグインはそれを正しくサポートしていないようです。これがフィドルです:フィドル

Chromeでは正常に動作しますが、他のすべての一般的なブラウザでは、上部のスクロールバーの方向は左のままです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.