我不相信你会找到一种使用纯 HTML 和 CSS 的方法——这对于自定义核心功能来说太过分了,所以一点 JavaScript 就可以解决问题(我也使用 jQuery 让它稍微简单一些)。
在我的测试中,我使用 <label> 而不是 <div> 来包装复选框,但同样的想法也适用于 div。我只是更喜欢标签,所以如果 JavaScript 没有加载,复选框仍然是可点击的。
<div class="fake-select">
<label for="fs1"><input type="checkbox" id="fs1" name="fs1" />Fake 1</label>
<label for="fs2"><input type="checkbox" id="fs2" name="fs2" />Fake 2</label>
[ ... ]
</div>
基本上,您需要跟踪用户的按键和“活动”输入。查找向上/向下箭头键并根据它更改活动输入(滚动到它,为样式添加类名)。我还允许空格键选中/取消选中当前活动的框。
var fs = $(".fake-select"),
items = fs.find('input'),
divs = fs.find('label'),
active = 0;
// Hook keypresses
fs.keydown( function(e){
reCalculate(e);
rePosition();
return false;
});
// Click event for manual changes
items.unbind('click').click(function(e){
var thisInput = $(this),
thisLabel = $(this).parent();
window.active = thisLabel.index();
thisLabel.removeClass("checked");
if (thisInput.is(":checked"))
thisLabel.addClass("checked");
rePosition();
});
// Set new active element based on keypress
// Trigger click event if user hits space bar
function reCalculate(e){
var max = items.length -1,
cur = window.active,
charCode = (typeof e.which == "number" && e.which) ? e.which : e.keyCode;
if (charCode == 38) { // move up
cur--;
cur = (cur <= 0) ? 0 : cur;
}
if (charCode == 40) { // move down
cur++;
cur = (cur >= max) ? max : cur;
}
if (charCode == 32) { // space bar
items.eq(cur).focus().trigger('click');
}
window.active = cur;
}
// Add active class, call scroll function
function rePosition(){
divs.removeClass('active').eq(window.active).addClass('active');
scrollInView();
}
// Scroll the list so the active element is in view
function scrollInView(){
var target = divs.eq(window.active);
if (target.length) {
var top = fs.scrollTop() + target.position().top - fs.height()/2 + target.height()/2
fs.stop().animate({scrollTop: top}, 400);
}
return false;
}
jsFiddle 示例:http://jsfiddle.net/daCrosby/kqecngv0/13/