table
我的页面很大。因此,我决定在表格底部放置一个水平滚动条。但我希望此滚动条也位于表的顶部。
我在模板中的内容是这样的:
<div style="overflow:auto; width:100%; height:130%">
<table id="data" style="width:100%">...</table>
</div>
仅在HTML和CSS中可以这样做吗?
table
我的页面很大。因此,我决定在表格底部放置一个水平滚动条。但我希望此滚动条也位于表的顶部。
我在模板中的内容是这样的:
<div style="overflow:auto; width:100%; height:130%">
<table id="data" style="width:100%">...</table>
</div>
仅在HTML和CSS中可以这样做吗?
Answers:
要在元素顶部模拟第二个水平滚动条,请在div
具有水平滚动的元素上方放置一个“虚拟” ,刚好足以容纳滚动条。然后为虚拟元素和真实元素附加“ scroll”事件的处理程序,以在移动任一滚动条时使另一个元素同步。虚拟元素看起来像真实元素上方的第二个水平滚动条。
有关实时示例,请参见此小提琴
这是代码:
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());
});
});
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>
首先,很好的答案,@ StanleyH。如果有人想知道如何制作具有动态宽度的双滚动容器:
.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>
$('.div1').width( $('.div1')[0].scrollWidth)
获得的内容,当你没有特别使用如表容器有用的真正动宽度。@simo很棒的努力伙伴。
因为您可能不需要JQuery,所以这里是基于@StanleyH答案的有效Vanilla JS版本:
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的回答很好,但是有一个不幸的错误:单击滚动条的阴影区域不再跳转到您单击的选择。取而代之的是,滚动条的位置增加了一个很小且令人讨厌的增量。
经过测试:4个版本的Firefox(影响100%),4个版本的Chrome(影响50%)。
这是我的jsfiddle。您可以通过具有on / off(true / false)变量来解决此问题,该变量一次只允许一个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调用wrapper2的scrollLeft,而wrapper2调用wrapper1的scrollLeft,并无限地重复此操作,因此,我们遇到了无限循环问题。或者更确切地说:用户的继续滚动与wrapperx的滚动调用发生冲突,发生事件冲突,并且最终结果是滚动条中没有跳跃。
希望这可以帮助其他人!
链接滚动条是可行的,但是在编写方式上,它会创建一个循环,如果您单击较浅的滚动条的一部分并按住它(而不是拖动滚动条时),则会使大多数浏览器的滚动速度变慢。
我用一个标志修复它:
$(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;
}
});
});
基于@HoldOffHunger和@bobince答案的纯JavaScript解决方案
<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'));
基于@StanleyH解决方案,我创建了一个AngularJS指令,演示上的jsfiddle。
易于使用:
<div data-double-scroll-bar-horizontal> {{content}} or static content </div>
对于AngularJS开发人员
据我所知,HTML和CSS不可能做到这一点。
在vanilla 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;
}
扩展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>
而已。
给所有有角度/本地人的粉丝,实现@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)
一个用于实现此目的的AngularJs指令:要使用它,请将CSS类double-hscroll添加到您的元素中。为此,您将需要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());
});
});
}
};
});
这是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
.. 上注意一下,我将其设置为12px,因此Mac用户也会注意到它。但是使用Windows,0.1像素就足够了