我在页面上有一个非常大的表格
,因此我决定在表格底部放置一个水平滚动条。但是我希望这个滚动条也出现在表格顶部。
模板中的内容如下:
<div style="overflow:auto; width:100%; height:130%">
<table id="data" style="width:100%">...</table>
</div>
这个能在HTML和CSS中实现吗?
我在页面上有一个非常大的表格
,因此我决定在表格底部放置一个水平滚动条。但是我希望这个滚动条也出现在表格顶部。
模板中的内容如下:
<div style="overflow:auto; width:100%; height:130%">
<table id="data" style="width:100%">...</table>
</div>
这个能在HTML和CSS中实现吗?
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());
});
});
有一种方法可以实现这一点,我没有看到任何人在这里提到过。
通过将父容器旋转 180度,再将子容器 再次旋转180度 ,滚动条将显示在顶部。
.parent {
transform: rotateX(180deg);
overflow-x: auto;
}
.child {
transform: rotateX(180deg);
}
请参考w3c存储库中的问题。
transform: rotateX(180deg);
- 在这里查看fiddle:https://jsfiddle.net/5Diraptor/yoq2k3m6/11/ - AutoBakerjQuery:
$(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>
因为您可能不需要JQuery,这里有一个基于@ StanleyH答案的工作原生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>
经过测试:4个版本的Firefox(100%受影响),4个版本的Chrome(50%受影响)。
这里是我的jsfiddle。您可以通过拥有一个只允许一个onScroll()事件触发的开/关(true/false)变量来解决这个问题:
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的滚动调用发生冲突,导致事件冲突,最终结果是滚动条不会跳动。
希望这能帮助其他人!
首先,非常好的回答,@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做得很棒,伙计。 - Clain Dsilva<div id="data">
...
</div>
function doubleScroll(element) {
const 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"));
let running = false;
// Keep scrollbar in sync when element size changes
new ResizeObserver(() => {
scrollbar.firstChild.style.width = element.scrollWidth + "px";
}).observe(element);
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("data"));
scrollbar.firstChild.style.paddingTop = "1px"
之后添加scrollbar.firstChild.style.lineHeight = "0px";
。 - kbulgrienReact+TypeScript 将rap-2-h的代码迁移到TypeScript。
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { ReactNode } from 'react';
import { useRef } from 'react';
const useStyles = makeStyles((theme) => ({
wrapper1: {
width: '300px',
height: '20px',
overflowX: 'scroll',
overflowY: 'hidden',
border: 'none 0px black',
},
wrapper2: {
width: '300px',
height: '100px',
overflowX: 'scroll',
overflowY: 'hidden',
border: 'none 0px black',
},
div1: {
width: '1000px',
height: '20px',
},
div2: {
width: '1000px',
height: '100px',
backgroundColor: '#88FF88',
overflow: 'auto',
}
}));
export default function TopBottomScrollBars() {
const classes = useStyles();
const wrapRef1 = useRef<HTMLDivElement>(null);
const wrapRef2 = useRef<HTMLDivElement>(null);
const handleScroll: React.EventHandler<React.UIEvent<ReactNode>> = (event: React.UIEvent<React.ReactNode> ) => {
const targetDiv: HTMLDivElement = event.target as HTMLDivElement;
if(targetDiv === wrapRef1.current && wrapRef2.current) {
wrapRef2.current.scrollLeft = targetDiv.scrollLeft;
}
else if(targetDiv === wrapRef2.current && wrapRef1.current) {
wrapRef1.current.scrollLeft = targetDiv.scrollLeft;
}
};
return (
<div>
<div ref={wrapRef1} className={classes.wrapper1} onScroll={handleScroll} >
<div id="div1" className={classes.div1}>
</div>
</div>
<div ref={wrapRef2} className={classes.wrapper2} onScroll={handleScroll}>
<div id="div2" className={classes.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>
</div>
);
}
基于@StanleyH的解决方案,我创建了一个AngularJS指令,在jsFiddle上有演示。
使用简单:
<div data-double-scroll-bar-horizontal> {{content}} or static content </div>
针对AngularJS开发者