горизонтальна смуга прокрутки вгорі та внизу таблиці


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

Відповіді:


234

Щоб імітувати другу горизонтальну смугу прокрутки поверх елемента, поставте "манекен" divнад елементом, який має горизонтальну прокрутку, досить високу для смуги прокрутки. Потім приєднайте обробники події "прокрутки" для елемента манекена та реального елемента, щоб отримати інший елемент синхронізовано при переміщенні будь-якої смуги прокрутки. Елемент манекена буде схожий на другу горизонтальну смугу прокрутки над реальним елементом.

Для живого прикладу дивіться цю загадку

Ось код :

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 (Звичайно, ви можете це зробити без jQuery, приєднавши безпосередньо обробники onscroll.) Для витонченої деградації для користувачів, що не мають JS, ви можете додати фіктивний DIV до DOM від JS .
СтенліH

1
так, я працював, мені потрібно було лише додати <script type = "text / javascript" src = "path"> </script> до <head>. Отже, кожного разу, коли я додаю jquery, мені потрібно було додавати той, який додає @fudgey? Вибачте, javascript та jquery все ще є для мене китайською мовою
psoares

4
@StanleyH: як встановити div, щоб автоматично приймати ширину таблиці всередині нього? я не хочу вказувати ширину div2 вручну, але хочу, щоб вона автоматично приймала ширину таблиці, яку вона містить.
sqlchild

3
@CodyGuldner: як встановити div, щоб автоматично приймати ширину таблиці всередині нього? я не хочу вказувати ширину div2 вручну, але хочу, щоб вона автоматично приймала ширину таблиці, яку вона містить.
sqlchild

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
Дивіться сторінку github.com/avianey/jqDoubleScroll для версії дивовижного плагіна Pawel, який не потребує jQueryUI.
fatal_error

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 Чудові зусилля.
Клін Дільва

Для уточнення мені також довелося змінити код на scrollWidth, щоб мій власний код працював там, де ширина вмісту в розділі "div2" була змінною завдяки динамічному контенту на стороні сервера, який знаходиться там.
AdamJones

15

Без JQuery (2017)

Оскільки вам може не знадобитися JQuery, ось працююча версія Vanilla JS на основі відповіді @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>


це насправді не чутливо / динамічно у випадку, якщо ви не знаєте своєї ширини
срібло з радості

так! він має ті самі застереження, що й оригінальна відповідь від @StanleyH
реп-2-год

11

Ви можете використовувати плагін jQuery, який зробить роботу за вас:

Плагін буде обробляти всю логіку для вас.


2
Хоча цей плагін робить те саме, що і плагін suwala / jquery.doubleScroll, у нього є більше варіантів, як перерахунок ширини на window.resize
Іван Хушняк,

1
Також не залежить від інтерфейсу jquery.
плем'я84

1
Я б рекомендував цей плагін, він схожий на покращену версію suwala / jquery.doubleScroll і працює для мене
Russell England

Спочатку дякую за чудовий плагін! Однак у мене є проблема із напрямком прокрутки: rtl. Здається, це не правильно підтримує. Якщо хтось із вас гуру Java-скриптів знає, як це виправити, це скрипка: jsfiddle.net/qsn7tupc/3 Зауважте, що вона працює в Chrome, але не в іншому браузері.
Владо

10

Відповідь StanleyH була чудовою, але вона мала один нещасний помилку: натискання затіненої області прокрутки більше не переходить до вибраного вами виділення. Натомість те, що ви отримуєте, - це дуже невеликий і дещо дратівливий приріст у положенні прокрутки.

Тестовано: 4 версії Firefox (100% постраждалих), 4 версії Chrome (50%).

Ось моя jsfiddle . Ви можете подолати це за допомогою наявності ввімкнення / вимкнення (true / false) var, який дозволяє одночасно запускати лише одну подію onScroll ():

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 викликає scrollLeft, а wrapper2 викликає 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

рішення тільки для JavaScript, яке базується на відповідях @HoldOffHunger та @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

На основі рішення @StanleyH я створив директиву AngularJS , демонстрацію на jsFiddle .

Простий у використанні:

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

Для розробників AngularJS


31
"Не потрібно jQuery." Так, лише цілі рамки. Немає великого.
PitaJ

2

Наскільки мені відомо, це неможливо з HTML та CSS.


ну це насправді те, що я думав .. Але я хотів би знати, чи хтось зробив це, і найкращий спосіб це зробити ..
psoares

Для HTML та CSS немає найкращого способу. Це просто неможливо. Для отримання подібного функціоналу вам потрібно використовувати інші методи, наприклад, JavaScript.
Юстус Ромінь

1
ви можете дати кілька порад, щоб почати шукати?
псоарес

2
Це не дає відповіді на запитання. Щоб критикувати або вимагати роз'яснення у автора, залиште коментар під їх публікацією.
SSA

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 (називається один раз звідкись схожого $(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

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 у веб-браузері чи мобільному браузері, ви можете спробувати:

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

0

Директива AngularJs для досягнення цього: Щоб використовувати його, додайте до свого елемента double-hscroll класу css. Для цього вам знадобляться jQuery та 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

Ось приклад для 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.. Я зробив це 12 пікселів, тому це буде помічено і для користувачів Mac. Але без вікон, 0,1 пікселів досить добре


-1

Виникла проблема із напрямком прокрутки: rtl. Здається, плагін не підтримує його правильно. Ось скрипка: скрипка

Зауважте, що він працює правильно в Chrome, але у всіх інших популярних браузерах верхній напрямок смуги прокрутки залишається лівим.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.