horizontale Bildlaufleiste oben und unten in der Tabelle


159

Ich habe eine sehr große tableauf meiner Seite. Also habe ich beschlossen, eine horizontale Bildlaufleiste am unteren Rand der Tabelle zu platzieren. Aber ich möchte, dass diese Bildlaufleiste auch ganz oben auf dem Tisch steht.

Was ich in der Vorlage habe, ist Folgendes:

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

Ist dies nur in HTML und CSS möglich?


1
stackoverflow.com/questions/2274627/… Ich fand diese Lösung nützlich.
VARSHA DAS

Antworten:


234

Um eine zweite horizontale Bildlaufleiste über einem Element zu simulieren, platzieren Sie einen "Dummy" divüber dem Element mit horizontalem Bildlauf, der gerade hoch genug für eine Bildlaufleiste ist. Fügen Sie dann Handler des Ereignisses "scroll" für das Dummy-Element und das reale Element hinzu, um das andere Element zu synchronisieren, wenn eine der Bildlaufleisten verschoben wird. Das Dummy-Element sieht aus wie eine zweite horizontale Bildlaufleiste über dem realen Element.

Ein Live-Beispiel finden Sie in dieser Geige

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

wirklich tolle Antwort! Vielen Dank! :) Also habe ich versucht, Ihr Beispiel zu verwenden, aber die Leiste oben funktioniert nicht, und als ich versuchte, die Breite zu erhöhen, verschwindet die Bildlaufleiste. Irgendeine Idee warum?
Psoares

1
Hast du es zum Laufen gebracht? Weitere Informationen zu jQuery finden Sie unter api.jquery.com/scrollLeft. (Sie können dies natürlich auch ohne jQuery tun, indem Sie Onscroll-Handler direkt anhängen.) Für Benutzer ohne JS können Sie das Dummy-Div dem JS von JS hinzufügen .
StanleyH

1
Ja, ich habe es zum Laufen gebracht. Ich habe nur <script type = "text / javascript" src = "path"> </ script> zu <head> hinzugefügt. Also musste ich jedes Mal, wenn ich jquery hinzufüge, die hinzufügen, die @fudgey hinzufügt? Entschuldigung, Javascript und JQuery sind für mich immer noch ein bisschen chinesisch
psoares

4
@ StanleyH: Wie stelle ich das div so ein, dass es automatisch die Breite der darin enthaltenen Tabelle annimmt? Ich möchte die Breite von div2 nicht manuell angeben, sondern automatisch die Breite der darin enthaltenen Tabelle übernehmen.
sqlchild

3
@CodyGuldner: Wie stelle ich das div so ein, dass es automatisch die Breite der darin enthaltenen Tabelle annimmt? Ich möchte die Breite von div2 nicht manuell angeben, sondern automatisch die Breite der darin enthaltenen Tabelle übernehmen.
sqlchild

38

Versuchen Sie es mit dem jquery.doubleScrollPlugin :

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
Unter github.com/avianey/jqDoubleScroll finden Sie eine Version von Pawels fantastischem Plugin, für das kein jQueryUI erforderlich ist.
fatal_error

1
Link führt zu einem nicht gewarteten GitHub mit defekten Links in read me. Habe das eigentliche js nicht ausprobiert.
Paul Gorbas

19

Zuallererst eine großartige Antwort, @StanleyH. Wenn sich jemand fragt, wie der Double-Scroll-Container mit dynamischer Breite erstellt werden soll:

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>

Demo

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


3
Verwenden Sie $('.div1').width( $('.div1')[0].scrollWidth)diese Option , um die tatsächliche Bildlaufbreite des Inhalts abzurufen. Dies ist nützlich, wenn Sie keinen Container wie eine Tabelle verwenden. @ Simo Super Anstrengung Kumpel.
Clain Dsilva

Zur Verdeutlichung musste ich auch den Code in scrollWidth ändern, damit mein eigener Code funktioniert, bei dem die Breite des Inhalts innerhalb des div "div2" aufgrund des dort befindlichen serverseitigen dynamischen Inhalts variabel war.
AdamJones

15

Ohne JQuery (2017)

Da Sie JQuery möglicherweise nicht benötigen, finden Sie hier eine funktionierende Vanilla JS-Version, die auf der Antwort von @StanleyH basiert:

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>


Dies ist eigentlich nicht
reaktionsschnell

Ja! Es hat die gleichen Einschränkungen wie die ursprüngliche Antwort von @ StanleyH
Rap-2-h

11

Sie können ein jQuery-Plugin verwenden, das die Aufgabe für Sie erledigt:

Das Plugin übernimmt die gesamte Logik für Sie.


2
Obwohl dieses Plugin dasselbe tut wie das Plugin suwala / jquery.doubleScroll, bietet es mehr Optionen wie die Neuberechnung der Breite von window.resize
Ivan Hušnjak

1
Hängt auch nicht von der jquery-Benutzeroberfläche ab.
Tribe84

1
Ich würde dieses Plugin empfehlen, es sieht aus wie eine verbesserte Version von suwala / jquery.doubleScroll und funktioniert für mich
Russell England

Zuerst danke für das tolle Plugin! Ich habe jedoch ein Problem mit der Bildlaufrichtung: rtl. Es scheint, dass es es nicht richtig unterstützt. Wenn einer von euch Javascripts-Gurus weiß, wie man es hier behebt, ist dies die Geige: jsfiddle.net/qsn7tupc/3 Beachten Sie, dass es in Chrome funktioniert, aber in keinem anderen Browser.
Vlado

10

Die Antwort von StanleyH war ausgezeichnet, hatte aber einen unglücklichen Fehler: Durch Klicken auf den schattierten Bereich der Bildlaufleiste wird nicht mehr zu der Auswahl gesprungen, auf die Sie klicken. Stattdessen erhalten Sie ein sehr kleines und etwas nerviges Inkrement an der Position der Bildlaufleiste.

Getestet: 4 Versionen von Firefox (100% betroffen), 4 Versionen von Chrome (50% betroffen).

Hier ist meine jsfiddle . Sie können dies umgehen, indem Sie eine Ein / Aus-Variable (true / false) verwenden, mit der jeweils nur ein onScroll () -Ereignis ausgelöst werden kann:

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

Problemverhalten mit akzeptierter Antwort:

Eigentlich gewünschtes Verhalten:

Warum passiert das? Wenn Sie den Code durchgehen, werden Sie feststellen, dass wrapper1 scrollLeft von wrapper2 aufruft und wrapper2 scrollLeft von wrapper1 aufruft, und dies unendlich wiederholen. Wir haben also ein Endlosschleifenproblem. Oder besser gesagt: Das fortgesetzte Scrollen des Benutzers steht in Konflikt mit dem Aufruf des Scrollers durch wrapperx, es tritt ein Ereigniskonflikt auf und das Endergebnis ist kein Springen in die Bildlaufleisten.

Hoffe das hilft jemand anderem!


tolle Erklärung! in der Tat machte es eine Endlosschleife
Ahmed Aboud

Ja. Vielen dank für Ihre Hilfe! Es ist hilfreich für mich.
Giang D.MAI

3

Das Verknüpfen der Scroller hat funktioniert, aber in der Art und Weise, wie es geschrieben wurde, wird eine Schleife erstellt, die das Scrollen in den meisten Browsern verlangsamt, wenn Sie auf den Teil der helleren Bildlaufleiste klicken und ihn gedrückt halten (nicht beim Ziehen des Scrollers).

Ich habe es mit einer Flagge behoben:

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

Dies löst ein Problem, das ich auch hier mit den vorgeschlagenen Antworten hatte. Dies verringert das Problem jedoch nur geringfügig. Möglicherweise wird immer noch schrittweise / langsam gescrollt, wenn der Abstand, den Sie scrollen möchten, groß genug ist.
Dan Temple

Mit der Bedingung / Flag funktioniert diese Lösung gut und die Tests entsprechen dem Verhalten, das Sie erwarten würden, ohne dass JavaScript im Browser angewendet wird.
Userabuser

3

Eine reine Javascript-Lösung, die auf den Antworten von @HoldOffHunger und @bobince basiert

<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

Basierend auf der @ StanleyH-Lösung habe ich eine AngularJS-Direktive erstellt , eine Demo für jsFiddle .

Einfach zu verwenden:

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

Für AngularJS-Entwickler


31
"Keine jQuery erforderlich." Ja, nur ein ganzer Rahmen. Kein Problem.
PitaJ

2

Soweit mir bekannt ist, ist dies mit HTML und CSS nicht möglich.


Nun, das ist eigentlich das, was ich dachte. Aber ich würde gerne wissen, ob jemand dies getan hat und der beste Weg, dies zu tun.
psoares

Für HTML und CSS gibt es keinen besten Weg. Es ist einfach nicht möglich. Sie müssen andere Techniken wie Javascript verwenden, um diese Art von Funktionalität zu erhalten.
Justus Romijn

1
Können Sie einige Tipps geben, nach denen Sie suchen sollten?
Psoares

2
Dies gibt keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlassen Sie einen Kommentar unter seinem Beitrag.
SSA

2
@SSA beantwortet die Frage. Die Frage war "Ist dies nur in HTML und CSS möglich?" und die Antwort darauf ist "nein".
Punkrockbuddyholly

2

In Vanilla Javascript / Angular können Sie dies folgendermaßen tun:

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

Um die Antwort von StanleyH zu erweitern und zu versuchen, das erforderliche Minimum zu finden, habe ich Folgendes implementiert:

JavaScript (einmal von irgendwo wie aufgerufen $(document).ready()):

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

HTML (beachten Sie, dass die Breite die Länge der Bildlaufleiste ändert):

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

Das ist es.


1

an alle Angular / NativeJs-Fans, die die Antwort von @ simo implementieren

HTML (keine Änderung)

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

CSS (keine Änderung, Breite: 90% ist mein Wunsch)

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

JS (wie onload) oder ngAfterViewChecked(alle assind für 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

Wenn Sie iscroll.js im Webkit-Browser oder im mobilen Browser verwenden, können Sie Folgendes versuchen:

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

0

Eine AngularJs-Direktive, um dies zu erreichen: Um sie zu verwenden, fügen Sie Ihrem Element die CSS-Klasse double-hscroll hinzu. Dazu benötigen Sie jQuery und 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

Hier ist ein Beispiel für 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>

TAKE Hinweis auf die height: 12px.. Ich habe es 12px so wird es auch auf Mac - Benutzer bemerkt werden. Aber mit Windows ist 0.1px gut genug


-1

Es gibt ein Problem mit der Bildlaufrichtung: rtl. Es scheint, dass das Plugin es nicht richtig unterstützt. Hier ist die Geige: Geige

Beachten Sie, dass es in Chrome korrekt funktioniert, aber in allen anderen gängigen Browsern bleibt die Richtung der oberen Bildlaufleiste links.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.