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?
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());
});
});
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>
Tout d’abord, bonne réponse, @StanleyH. Si quelqu'un se demande comment créer le conteneur à double défilement avec une largeur dynamique:
.wrapper1, .wrapper2 { width: 100%; overflow-x: scroll; overflow-y: hidden; }
.wrapper1 { height: 20px; }
.div1 { height: 20px; }
.div2 { overflow: none; }
$(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());
});
<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>
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>
Vous pouvez utiliser un plugin jQuery qui fera le travail pour vous:
Le plugin gérera toute la logique pour vous.
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!
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;
}
});
});
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.
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.
Autant que je sache, ce n'est pas possible avec HTML et CSS.
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;
}
Si vous utilisez iscroll.js sur un navigateur Web ou un navigateur mobile, vous pouvez essayer:
$('#pageWrapper>div:last-child').css('top', "0px");
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'));
à 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)