我正在尝试模仿Chrome中的CTRL + F功能,突出显示滚动条中页面上的匹配项,但是对于表单中的某些字段。使用页面偏移和百分比,我有一些颜色块,对应于页面上这些字段的相对位置。
在我的原型中,颜色块位于滚动条的左侧。理想情况下,它们位于滚动条的下方,滚动条的轨道将是透明的,因此看起来它们是滚动条轨道的一部分。
是否可以将默认滚动条设置为允许在其下方显示溢出内容(或允许页面内容覆盖它)?我知道如果我只是滚动自己的卷轴就可以实现这一点,但是如果可能的话,我想使用浏览器提供的默认卷轴。
It's clearest if you just look at this Prototype.
CSS:
::-webkit-scrollbar {
width: 14px;
height: 18px;
background-color:transparent;
}
::-webkit-scrollbar-track,
::-webkit-scrollbar-track-piece {
background:none;
}
::-webkit-scrollbar-thumb {
height: 6px;
border: 4px solid rgba(0, 0, 0, 0);
background-clip: padding-box;
-webkit-border-radius: 7px;
background-color: #333
}
::-webkit-scrollbar-button {
width: 0;
height: 0;
display: none;
}
::-webkit-scrollbar-corner {
background-color: transparent;
}
答案 0 :(得分:2)
我想过在轨道栏上渲染匹配项与之前的浏览器类似。通过linear-gradient
使用::-webkit-scrollbar-track
背景,这个想法很简单。但是我没有尝试实现这一点。在看完你的问题后,我已经尝试过了,看起来并不那么容易。
您可以使用linear-gradient
背景确定,但如果尝试渲染多于1个匹配(一行),有时无法渲染(特别是当窗口的大小发生变化时) )并且线条不能平滑。比如这似乎没关系:
//render 2 lines, one is at 50px and the other is at 100px
background: linear-gradient(transparent 50px, red 50px, red 51px, transparent 51px,
transparent 100px, red 100px, red 101px, transparent 101px);
但它并不稳定,正如我所说,当你尝试调整窗口大小时,在某种程度上,某些线路不会被渲染(至少我试过Opera)。当窗户的高度很大时,线条甚至变得模糊(不锋利)和更厚。我不太明白这一点,因为颜色停止是固定设置的(px
,而不是%
)。当行数较大时,这个问题更加严重。你有linear-gradient
有许多相应的色块。这似乎是解决问题的一种巧妙方法。仅仅因为不受欢迎的问题,我们无法使用这种方法。
新方法:所以我尝试使用多背景功能。每个背景只渲染1行,background-size
对于所有背景都相同,高度约为2px
,background-position
应该不同。以下是使用此方法的等效代码(对于上面的清洁代码):
background: linear-gradient(red, red), linear-gradient(red, red);
background-repeat: no-repeat;
background-size: 100% 2px;
background-position: 0 50px, 0 100px;
新方法当然要求浏览器必须支持多背景功能(看起来就像IE8一样 - 不支持这个很酷的功能)。
这几乎是你解决这个问题所需要的。现在我们需要找到如何使用脚本应用该样式。我们不能通过脚本选择伪元素(或类似的东西)。我们可以使用window.getComputedStyle()
方法获取伪元素的只读样式。但是我们总是有办法直接修改CSS。这是在document.styleSheets
和cssRules
的帮助下使用纯JS。它们允许我们插入/删除/修改规则。
看起来很棒。但还有另一个问题。使用该方法更改样式时,样式未正确应用(至少它发生在::-webkit-scrollbar-track
,它可能不会发生在其他元素上)。仅当您将鼠标移到滚动条上时,才会应用新样式。我通过将overflow
document.documentElement
html
设置为hidden
来找到使无效滚动条的简单方法将其设置回auto
。这很有效。
以下是代码:
var requiredTb = $(".required input");
var invalids = requiredTb;
var offsets = [];
//init offsets to highlight on the trackbar later
requiredTb.each(function() {
offsets.push(($(this).offset().top)/document.body.scrollHeight * 100);
});
//find the rule styling the -webkit-scrollbar-track
//we added in the CSS stylesheet, this is done just 1 time
var sheets = document.styleSheets;
var trackRule;
for(var i = 0; i < sheets.length; i++){
var rules = sheets[i].cssRules || sheets[i].rules;
for(var j = 0; j < rules.length; j++){
var rule = rules[j];
if(rule.selectorText == "::-webkit-scrollbar-track:vertical"){
trackRule = rule; break;
}
}
}
//define an invalidate() method, we need to use this method
//to refresh the scrollbars, otherwise the newly applied style is not affected
window.invalidate = function(){
$(document.documentElement).css('overflow','hidden');
setTimeout(function(e){
$(document.documentElement).css('overflow','auto');
},1);
};
//this is the main function to set style for the scrollbar track.
function setTrackHighlights(positions, color){
positions.sort();//ensure that the input array should be ascendingly sorted.
trackRule.style.cssText = "";
var gradient = "background: ", backPos = "background-position: ";
var winHeight = $(window).height();
$.each(positions, function(i,pos){
gradient += "linear-gradient(" + color + ", " + color + "),";
backPos += "0 " + pos + "%,"
});
gradient = gradient.substr(0,gradient.length-1) + ";";
backPos = backPos.substr(0,backPos.length -1) + ";";
trackRule.style.cssText += gradient + backPos + "background-repeat:no-repeat; background-size:100% 2px";
invalidate();
}
//initially set the highlights on the trackbar
setTrackHighlights(offsets,'red');
//handle the oninput event to update the highlights accordingly
requiredTb.on('input', function(e){
var required = $(this).closest('.required');
var refreshHighlights = false;
if(this.value && !required.is('.ok')) {
required.addClass('ok');
refreshHighlights = true;
invalids = invalids.not(this);
}
if(!this.value && required.is('.ok')) {
required.removeClass('ok');
refreshHighlights = true;
invalids = invalids.add(this);
}
if(refreshHighlights){
offsets.splice(0);
invalids.each(function() {
offsets.push(($(this).offset().top)/document.body.scrollHeight * 100);
});
setTrackHighlights(offsets,'red');
}
});
你必须在CSS代码中添加一个空的::-webkit-scrollbar-track:vertical
规则(我们只需要处理垂直滚动条),它应该在最后添加,以覆盖之前的任何类似规则。实际上,我们可以使用insertRule()
方法(可以通过cssRules
属性访问的CSSRuleList)来添加新规则,而不是循环遍历styleSheets
,并通过{{1 (每个工作表)找到空规则cssRules
。
我在这里发布的代码可以改进,例如你可以添加另一个方法::-webkit-scrollbar-track:vertical
以允许添加更多行(而不是每次我们需要添加/删除1行时渲染所有行)。 ..
请注意,通过使用术语 行 ,我的意思是轨迹栏上匹配的呈现表示。