我认为这确实是某种类型的错误,与选择元素的宽度与元素的滚动高度有关。
您拥有的选项越多,它就可以越广泛并且仍然可以正常工作。如果我有一个带有 39 个选项的选择标签,那么最大值似乎在 510px 左右,然后才搞砸。
平均而言,一个选择可以处理的最大宽度似乎是每个选项大约 13 像素。所以如果你有一个有 13 个选项的选择器,那么最大值约为 169px (13 * 13)
当您滚动到第二个选项时,scrollTop 为 14 像素,滚动到第三个选项时为 28 像素。因此,您滚动到的每个元素都是 14 像素。因此,只要宽度小于 scrollHeight 减去一定数量的像素,它就可以工作......如果您使用每个选项 13 个像素,它似乎工作正常。
所以,你有2个选择。
- 确保您选择的宽度小于 13 * 选项数
或者
- 使用 javascript 来获得你想要的行为......我想出了一个有效的JsFiddle。对于那些喜欢使用 jQuery 的人,试试这个JsFiddle
您只需要监听 keydown 事件并调整滚动,以便所选元素在被选中之前处于视图中。
此外,为了使 scrollByLines(numberOfLines) 方法在滚动元素上起作用,它必须具有以下样式:
overflow-y: scroll;
这是一个有效的快速 HTML 文档
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
// This happens on document load
function myOnLoad() {
// Get the selector element
var mySelector = document.getElementById('mySelector');
// If the selector is doomed to glitch out on us because it's wider than the max allowed width, we need to fix it
if (mySelector.offsetWidth > 13 * mySelector.options.length) {
// Figure out the pixels for a single scroll line
mySelector.scrollByLines(1);
var scrollLineHeight = mySelector.scrollTop;
// Scroll back to the top
mySelector.scrollTop = 0;
// Add a keydown event listener so that we can scroll programatically before it messes up
mySelector.addEventListener('keydown', function (e) {
// Only listen to up and down arrows
if (e.keyCode !== 38 && e.keyCode !== 40) {
return;
}
// Figure out where the selector is scrolled to
var scrollTop = this.scrollTop;
var scrolledToLine = parseInt(scrollTop / scrollLineHeight);
// If we hit the up arrow and the selected index is equal to the scrolled line, simply move us up by one
if (e.keyCode === 38 && this.selectedIndex === scrolledToLine) {
this.scrollByLines(-1);
}
// If we hit the down arrow and the selected index is equal to the scrolled line + the number of visible lines - 1, move us down by one
if (e.keyCode === 40 && this.selectedIndex === scrolledToLine + (this.size - 1)) {
this.scrollByLines(1);
}
});
}
}
</script>
</head>
<body onload="myOnLoad();">
<select size="5" name="selectMultiple" multiple="multiple" style="width:100%; overflow-y: scroll;" id="mySelector">
<option value="0">line 0</option>
<option value="1">line 1</option>
<option value="2">line 2</option>
<option value="3">line 3</option>
<option value="4">line 4</option>
<option value="5">line 5</option>
<option value="6">line 6</option>
<option value="7">line 7</option>
<option value="8">line 8</option>
<option value="9">line 9</option>
<option value="10">line 10</option>
<option value="11">line 11</option>
<option value="12">line 12</option>
</select>
</body>
</html>
这是 jQuery 版本:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
$( document ).ready(function() {
// Get the selector element
var mySelectorObj = $('#mySelector');
var mySelector = mySelectorObj[0];
// If the selector is doomed to glitch out on us because it's wider than the max allowed width, we need to fix it
if (mySelector.offsetWidth > 13 * mySelector.options.length) {
// Figure out the pixels for a single scroll line
mySelector.scrollByLines(1);
var scrollLineHeight = mySelector.scrollTop;
// Scroll back to the top
mySelector.scrollTop = 0;
// Add a keydown event listener so that we can scroll programatically before it messes up
mySelectorObj.on('keydown', function(e) {
// Only listen to up and down arrows
if (e.keyCode !== 38 && e.keyCode !== 40) {
return;
}
// Figure out where the selector is scrolled to
var scrollTop = this.scrollTop;
var scrolledToLine = parseInt(scrollTop / scrollLineHeight);
// If we hit the up arrow and the selected index is equal to the scrolled line, simply move us up by one
if (e.keyCode === 38 && this.selectedIndex === scrolledToLine) {
this.scrollByLines(-1);
}
// If we hit the down arrow and the selected index is equal to the scrolled line + the number of visible lines - 1, move us down by one
if (e.keyCode === 40 && this.selectedIndex === scrolledToLine + (this.size - 1)) {
this.scrollByLines(1);
}
});
}
});
</script>
</head>
<body>
<select size="5" name="selectMultiple" multiple="multiple" style="width:100%; overflow-y: scroll;" id="mySelector">
<option value="0">line 0</option>
<option value="1">line 1</option>
<option value="2">line 2</option>
<option value="3">line 3</option>
<option value="4">line 4</option>
<option value="5">line 5</option>
<option value="6">line 6</option>
<option value="7">line 7</option>
<option value="8">line 8</option>
<option value="9">line 9</option>
<option value="10">line 10</option>
<option value="11">line 11</option>
<option value="12">line 12</option>
</select>
</body>
</html>