web-dev-qa-db-fra.com

barre de défilement horizontale en haut et en bas du tableau

J'ai un très gros table sur ma page. J'ai donc décidé de placer une barre de défilement horizontale au bas du tableau. Mais je voudrais que cette barre de défilement soit également au sommet de la table.

Voici ce que j'ai dans le modèle:

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

Est-ce possible de faire en HTML et CSS seulement?

138
psoares

Pour simuler une deuxième barre de défilement horizontale au-dessus d'un élément, placez un "mannequin" div au-dessus de l'élément doté du défilement horizontal, juste assez haut pour une barre de défilement. Attachez ensuite les gestionnaires de l'événement "scroll" pour l'élément factice et l'élément réel, afin de synchroniser l'autre élément lorsque l'une des barres de défilement est déplacée. L'élément factice ressemblera à une deuxième barre de défilement horizontale au-dessus de l'élément réel.

Pour un exemple en direct , voir ce violon

Voici le code :

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());
  });
});
212
StanleyH

Essayez d’utiliser le plugin 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>
35
pawel.suwala

Tout d’abord, bonne réponse, @StanleyH. Si quelqu'un se demande comment créer le conteneur à double défilement avec une largeur dynamique:

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>

démo

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

18
simo

Sans JQuery (2017)

Comme vous n’avez peut-être pas besoin de JQuery, voici une version fonctionnelle de Vanilla JS basée sur la réponse @StanleyH:

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>
11
rap-2-h

Vous pouvez utiliser un plugin jQuery qui fera le travail pour vous:

Le plugin gérera toute la logique pour vous.

10
avianey

La réponse de StanleyH était excellente, mais elle comportait un problème regrettable: cliquer sur la zone ombrée de la barre de défilement ne permet plus d'accéder à la sélection sur laquelle vous cliquez. Au lieu de cela, vous obtenez un incrément très petit et quelque peu gênant dans la position de la barre de défilement.

Testé: 4 versions de Firefox (affecté à 100%), 4 versions de Chrome (affecté à 50%).

Voici mon jsfiddle . Vous pouvez contourner ce problème en créant une variable on/off (true/false) qui ne permet de déclencher qu'un seul événement onScroll () à la fois:

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());
});

Problème avec la réponse acceptée:

Comportement réellement souhaité:

Alors, pourquoi cela se produit-il? Si vous parcourez le code, vous verrez que wrapper1 appelle scrollLeft de wrapper2 et que wrapper2 appelle scrollLeft de wrapper1, et le répète à l'infini. nous avons un problème de boucle infinie. Ou plutôt: le défilement continu de l'utilisateur est en conflit avec l'appel du défilement de wrapperx, un conflit d'événement se produit et le résultat final ne saute pas dans les barres de défilement.

J'espère que cela aide quelqu'un d'autre à sortir!

3
HoldOffHunger

Lier les défilement a fonctionné, mais sa rédaction crée une boucle qui ralentit le défilement dans la plupart des navigateurs si vous cliquez sur la partie de la barre de défilement plus claire et que vous la maintenez (pas lorsque vous faites glisser le défilement).

Je l'ai corrigé avec un drapeau:

$(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;
        }
    });
});
3
Yossi Vainshtein

Sur la base de la solution @StanleyH, j'ai créé un directive AngularJS , une démo sur jsFiddle .

Facile à utiliser:

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

Pas de jQuery requis.

3
przno

En développant la réponse de StanleyH, et en essayant de trouver le minimum requis, voici ce que j'ai mis en œuvre:

JavaScript (appelé une fois quelque part comme $(document).ready()):

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

HTML (notez que les largeurs changeront la longueur de la barre de défilement):

<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>

C'est ça.

1
MattC

Autant que je sache, ce n'est pas possible avec HTML et CSS.

1
punkrockbuddyholly

Dans Vanilla Javascript/Angular, vous pouvez le faire comme ceci:

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
Jakub Bares

Si vous utilisez iscroll.js sur un navigateur Web ou un navigateur mobile, vous pouvez essayer:

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

une solution javascript uniquement basée sur les réponses @HoldOffHunger et @bobince

<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'));
0
Ahmed Aboud

à tous les fans d'angular/nativeJs, implémentant la réponse de @ simo

HTML (pas de changement)

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

CSS (pas de changement, largeur: 90% est ma conception)

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

JS (comme onload) ou ngAfterViewChecked (tous les as sont pour 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
bresleveloper