barra di scorrimento orizzontale nella parte superiore e inferiore della tabella


159

Ne ho una molto grande tablesulla mia pagina. Così ho deciso di mettere una barra di scorrimento orizzontale nella parte inferiore del tavolo. Ma vorrei che questa barra di scorrimento fosse anche in cima al tavolo.

Quello che ho nel modello è questo:

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

È possibile farlo solo in HTML e CSS?


1
stackoverflow.com/questions/2274627/… Ho trovato utile questa soluzione.
VARSHA DAS,

Risposte:


234

Per simulare una seconda barra di scorrimento orizzontale sopra un elemento, metti un "manichino" divsopra l'elemento con scorrimento orizzontale, appena abbastanza alto per una barra di scorrimento. Quindi collegare i gestori dell'evento "scroll" per l'elemento fittizio e l'elemento reale, per sincronizzare l'altro elemento quando viene spostata una delle barre di scorrimento. L'elemento fittizio apparirà come una seconda barra di scorrimento orizzontale sopra l'elemento reale.

Per un esempio dal vivo , vedi questo violino

Ecco il codice :

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

risposta davvero fantastica! molte grazie! :) quindi ho provato a usare il tuo esempio, ma la barra in alto non funziona e quando ho provato ad aumentare la larghezza, la barra di scorrimento scompare. qualche idea del perché?
psoares,

1
L'hai fatto funzionare? Per ulteriori informazioni su jQuery, consultare api.jquery.com/scrollLeft (Naturalmente, è possibile farlo senza jQuery collegando direttamente i gestori onscroll.) Per un degrado gradevole per gli utenti senza JS, è possibile aggiungere il div fittizio al DOM di JS .
StanleyH,

1
Sì, l'ho fatto funzionare, avevo solo aggiunto <script type = "text / javascript" src = "path"> </script> a <head>. Quindi ogni volta che aggiungo jquery ho dovuto aggiungere quello che @fudgey aggiunge? Siamo spiacenti, javascript e jquery sono ancora un po 'cinesi per me
psoares il

4
@StanleyH: come impostare il div per prendere automaticamente la larghezza del tavolo al suo interno? non voglio specificare manualmente la larghezza di div2, ma voglio che prenda automaticamente la larghezza della tabella che contiene.
sqlchild,

3
@CodyGuldner: come impostare il div per prendere automaticamente la larghezza della tabella al suo interno? non voglio specificare manualmente la larghezza di div2, ma voglio che prenda automaticamente la larghezza della tabella che contiene.
sqlchild,

38

Prova a utilizzare il jquery.doubleScrollplug-in :

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
Vedi github.com/avianey/jqDoubleScroll per una versione del fantastico plugin di Pawel che non richiede jQueryUI.
fatal_error,

1
Il collegamento porta a un GitHub non gestito con collegamenti interrotti in lettura. Non ho provato il vero js.
Paul Gorbas,

19

Prima di tutto, ottima risposta, @StanleyH. Se qualcuno si chiede come realizzare il contenitore a doppio scorrimento con larghezza dinamica:

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>

dimostrazione

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


3
Utilizzare $('.div1').width( $('.div1')[0].scrollWidth)per ottenere la larghezza di scorrimento reale del contenuto, utile quando non si utilizza specificamente un contenitore come la tabella. @simo Compagno di grande sforzo.
Clain Dsilva,

Per chiarire, ho anche dovuto modificare il codice in scrollWidth affinché il mio codice funzionasse dove la larghezza del contenuto all'interno del div "div2" era variabile a causa del contenuto dinamico sul lato server situato lì.
AdamJones,

15

Without JQuery (2017)

Poiché potrebbe non essere necessario JQuery, ecco una versione funzionante di Vanilla JS basata sulla risposta di @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>


questo in realtà non è reattivo / dinamico nel caso in cui tu non conosca la tua larghezza
elad silver

sì! ha gli stessi avvertimenti della risposta originale di @StanleyH
rap-2-h

11

Puoi usare un plugin jQuery che farà il lavoro per te:

Il plugin gestirà tutta la logica per te.


2
Sebbene questo plugin faccia la stessa cosa del plugin suwala / jquery.doubleScroll, ha più opzioni come il ricalcolo della larghezza su window.resize
Ivan Hušnjak,

1
Inoltre, non dipende dall'interfaccia utente di jquery.
tribe84,

1
Consiglierei questo plugin, sembra una versione migliorata di suwala / jquery.doubleScroll e funziona per me
Russell Inghilterra

Innanzitutto grazie per l'ottimo plugin! Tuttavia ho un problema con la direzione di scorrimento: RTL. Sembra che non lo supporti correttamente. Se qualcuno di voi guru di javascripts sa come risolverlo, ecco il violino: jsfiddle.net/qsn7tupc/3 Nota che funziona in Chrome ma in nessun altro browser.
Vlado,

10

La risposta di StanleyH è stata eccellente, ma ha avuto uno sfortunato bug: fare clic sull'area ombreggiata della barra di scorrimento non passa più alla selezione selezionata. Invece, quello che ottieni è un incremento molto piccolo e un po 'fastidioso nella posizione della barra di scorrimento.

Testato: 4 versioni di Firefox (interessate al 100%), 4 versioni di Chrome (interessate al 50%).

Ecco il mio jsfiddle . Puoi aggirare questo problema avendo un var on / off (true / false) che consente l'attivazione di un solo evento onScroll () alla volta:

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

Comportamento del problema con risposta accettata:

Comportamento effettivamente desiderato:

Quindi, solo perché succede? Se esegui il codice, vedrai che wrapper1 chiama scrollLeft di wrapper2 e wrapper2 chiama scrollLeft di wrapper1 e lo ripeti all'infinito, quindi abbiamo un problema di loop infinito. O meglio: lo scorrimento continuo dell'utente è in conflitto con la chiamata dello scrolling di wrapperx, si verifica un conflitto di eventi e il risultato finale non salta nelle barre di scorrimento.

Spero che questo aiuti qualcun altro!


ottima spiegazione! infatti stava facendo un ciclo infinito
Ahmed Aboud il

Si. Grazie mille per il vostro sostegno! È utile per me
Giang D.MAI,

3

Il collegamento degli scroller ha funzionato, ma nel modo in cui è scritto crea un loop che rallenta lo scorrimento nella maggior parte dei browser se fai clic sulla parte della barra di scorrimento più leggera e tieni premuto (non quando trascini lo scroller).

L'ho corretto con una bandiera:

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

Questo risolve un problema che stavo riscontrando anche qui con le risposte suggerite. Tuttavia, ciò mitiga solo leggermente il problema, potrebbe esserci ancora uno scorrimento graduale / lento se la distanza che si desidera scorrere è abbastanza grande per esso.
Dan Temple

Con il condizionale / flag questa soluzione funziona bene e i test corrispondono al comportamento che ci si aspetterebbe senza l'applicazione di JavaScript nel browser.
userabuser

3

una soluzione solo javascript basata sulle risposte @HoldOffHunger e @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'));

3

Sulla base della soluzione @StanleyH ho creato una direttiva AngularJS , demo su jsFiddle .

Facile da usare:

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

Per gli sviluppatori AngularJS


31
"Nessun jQuery richiesto." Sì, solo un intero quadro. Nessun problema.
PitaJ,

2

Per quanto ne so, questo non è possibile con HTML e CSS.


bene questo è quello che pensavo .. Ma vorrei sapere se qualcuno ha fatto questo e il modo migliore per farlo ..
psoares

Per HTML e CSS, non esiste un modo migliore. Semplicemente non è possibile. È necessario utilizzare altre tecniche, come JavaScript, per ottenere questo tipo di funzionalità.
Justus Romijn,

1
puoi dare qualche consiglio per iniziare a cercare?
psoares,

2
Questo non fornisce una risposta alla domanda. Per criticare o richiedere chiarimenti a un autore, lascia un commento sotto il suo post.
SSA

2
@SSA risponde alla domanda. La domanda era "È possibile farlo solo in HTML e CSS?" e la risposta è "no".
punkrockbuddyholly,

2

In vanilla Javascript / Angolare puoi farlo in questo modo:

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

Espandendo la risposta di StanleyH e cercando di trovare il minimo richiesto, ecco cosa ho implementato:

JavaScript (chiamato una volta da qualche parte come $(document).ready()):

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

HTML (nota che le larghezze cambieranno la lunghezza della barra di scorrimento):

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

Questo è tutto.


1

a tutti i fan di angular / nativeJs, implementando la risposta di @ simo

HTML (nessuna modifica)

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

CSS (nessuna modifica, larghezza: il 90% è il mio desing)

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

JS (come onload) o ngAfterViewChecked(tutti assono per 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

Se stai utilizzando iscroll.js sul browser webkit o sul browser mobile, puoi provare:

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

0

Una direttiva AngularJs per raggiungere questo obiettivo: per usarlo, aggiungi classe css double-hscroll al tuo elemento. Per questo avrai bisogno di jQuery e AngularJs.

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

Ecco un esempio per 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>

PRENDI NOTA sul height: 12px.. L'ho fatto 12px in modo che possa essere notato anche su utenti Mac. Ma con Windows, 0.1px è abbastanza buono


-1

Si è verificato un problema con la direzione di scorrimento: rtl. Sembra che il plugin non lo supporti correttamente. Ecco il violino: violino

Nota che funziona correttamente in Chrome, ma in tutti gli altri browser popolari la direzione della barra di scorrimento superiore rimane a sinistra.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.