【问题标题】:How can I create a simple page vertical scroll bar without using jQuery?如何在不使用 jQuery 的情况下创建简单的页面垂直滚动条?
【发布时间】:2015-02-04 00:51:41
【问题描述】:

我查看了所有滚动条代码,但还没有找到一个不使用 jQuery 或有点复杂的库的简单代码。

有没有人只使用 Javascript 创建了自己的简单滚动条?我正在寻找的是如何做到这一点的一个例子。特别是我有一个简单的引导网页:

<body>
   <header> ....</header>
   <main> ......</main>
</body>

我想要做的是能够在&lt;main&gt; 区域的右侧出现一个小的页面滚动条,如果那里的内容大于单个页面的容量。出于造型目的,我希望这个 not 成为浏览器默认滚动条。

这是我正在寻找的一个例子,但是这个确实使用了 jQuery,所以我不能在我的网站上使用它:

http://manos.malihu.gr/repository/custom-scrollbar/demo/examples/complete_examples.html

我正在寻找一种在现代浏览器 IE9 及更高版本中使用 Javascript 的方法。因为我认为这对许多人来说很有用,所以我为此开放了 200 的赏金,希望有人可以提供一个很好的可拖动页面滚动条示例,该滚动条在页面内容区域上方时也会响应鼠标滚轮。

只是一个更新。我不是为此寻找移动解决方案。我只是在寻找可以在 PC / Mac 浏览器中运行的解决方案。该站点未设置或不适合手机。可以在 iPad/平板电脑上使用,但对于这些需求,我希望能够让滚动条默认使用普通的平板电脑滚动方法。

【问题讨论】:

  • 某些浏览器允许您设置原生滚动条的样式。我不建议使用自定义滚动条,因为如果您的 JS 代码出现问题,用户将无法滚动。
  • noraesae/perfect-scrollbar 适合你吗? DEMO。它指定“perfect-scrollbar 是简约但完美的(对我而言,也许对大多数开发人员而言)滚动条插件,可与 jQuery 或 vanilla JavaScript 一起使用
  • 你可以用js制作你自己的滚动条,使用事件并手动设置元素位置和滚动内容,这不会那么难,但我想一定有更好的解决方案。
  • 扩展@Oriol 的观点,我认为图书馆倾向于不再包含这种东西 - 要么采取一种立场,“偏离原生 UI 并不是好的 UX 设计控制”,或者简单地说,维护跨浏览器绝对是一种痛苦——尤其是在交互手势不同(捏合/缩放等)的移动设备上。
  • 我不确定完美滚动条,因为当我转到页面时,标题是:完美滚动条 - 微小但完美的 jQuery 滚动条插件。

标签: javascript html css mouse dom-events


【解决方案1】:

令人惊讶的是,没有使用原生 JavaScript 的出色、简单的解决方案。我做了一个纯 JS 轻量级、最小化的跨浏览器解决方案。 根据自己的需要和审美来调整

*2019 年更新
W3C 有一个在标准轨道上的工作文档,以通过 css 规范开箱即用地改进这一点。尽管有限制,但如果您想使用最先进的 css,您现在可以通过 scrollbar-colorscrollbar-width 设置滚动条的样式。更多信息请查看https://drafts.csswg.org/css-scrollbars/

示例:
这是fiddleCodePen

HTML

<body>
    <div id="main" class="scrollable">
        <div class="content-wrapper">
            <div class="content">
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Incidunt accusamus maxime voluptatem quasi. Recusandae optio nobis ratione iste consectetur consequatur cupiditate saepe laborum natus neque a provident eum explicabo delectus qui accusantium nostrum reiciendis soluta hic ut at sed laboriosam possimus repudiandae deserunt velit rerum. Aliquam ratione itaque corrupti aperiam quisquam unde aspernatur odio id repellendus corporis eaque expedita in ab minus possimus! Quo tempore consequatur repellat consectetur nemo molestiae perferendis ipsum esse nesciunt blanditiis nobis dicta? Laudantium quaerat inventore deleniti exercitationem explicabo quos pariatur sunt earum labore sed eius blanditiis architecto consequuntur ad consectetur unde sapiente nisi. Sunt eos.</p>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Incidunt accusamus maxime voluptatem quasi. Recusandae optio nobis ratione iste consectetur consequatur cupiditate saepe laborum natus neque a provident eum explicabo delectus qui accusantium nostrum reiciendis soluta hic ut at sed laboriosam possimus repudiandae deserunt velit rerum. Aliquam ratione itaque corrupti aperiam quisquam unde aspernatur odio id repellendus corporis eaque expedita in ab minus possimus! Quo tempore consequatur repellat consectetur nemo molestiae perferendis ipsum esse nesciunt blanditiis nobis dicta? Laudantium quaerat inventore deleniti exercitationem explicabo quos pariatur sunt earum labore sed eius blanditiis architecto consequuntur ad consectetur unde sapiente nisi. Sunt eos.</p>
            </div>
        </div>
    </div>
    <div>Not special and not contained within scrolling</div>
</body>

CSS

.scrollable {
    padding: 0% 10%;
    position: relative;
    border: 1px solid gray;
    overflow: hidden;
    height: 400px;
}

.scrollable.showScroll::after {
    position: absolute;
    content: '';
    top: 5%;
    right: 7px;
    height: 90%;
    width: 3px;
    background: rgba(224, 224, 255, .3);
}

.scrollable .content-wrapper {
    width: 100%;
    height: 100%;
    padding-right: 50%;
    overflow-y: scroll;
}
.scroller {
    z-index: 5;
    cursor: pointer;
    position: absolute;
    width: 10px;
    border-radius: 5px;
    background: rgb(111, 111, 190);
    top: 0px;
    right: 3px;
    -webkit-transition: top .08s;
    -moz-transition: top .08s;
    -ms-transition: top .08s;
    -o-transition: top .08s;
    transition: top .08s;
}
.content {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

JS

(function () {

var scrollContainer = document.querySelector('.scrollable'),
    scrollContentWrapper = document.querySelector('.scrollable .content-wrapper'),
    scrollContent = document.querySelector('.scrollable .content'),
    contentPosition = 0,
    scrollerBeingDragged = false,
    scroller,
    topPosition,
    scrollerHeight;

function calculateScrollerHeight() {
    // *Calculation of how tall scroller should be
    var visibleRatio = scrollContainer.offsetHeight / scrollContentWrapper.scrollHeight;
    return visibleRatio * scrollContainer.offsetHeight;
}

function moveScroller(evt) {
    // Move Scroll bar to top offset
    var scrollPercentage = evt.target.scrollTop / scrollContentWrapper.scrollHeight;
    topPosition = scrollPercentage * (scrollContainer.offsetHeight - 5); // 5px arbitrary offset so scroll bar doesn't move too far beyond content wrapper bounding box
    scroller.style.top = topPosition + 'px';
}

function startDrag(evt) {
    normalizedPosition = evt.pageY;
    contentPosition = scrollContentWrapper.scrollTop;
    scrollerBeingDragged = true;
}

function stopDrag(evt) {
    scrollerBeingDragged = false;
}

function scrollBarScroll(evt) {
    if (scrollerBeingDragged === true) {
        var mouseDifferential = evt.pageY - normalizedPosition;
        var scrollEquivalent = mouseDifferential * (scrollContentWrapper.scrollHeight / scrollContainer.offsetHeight);
        scrollContentWrapper.scrollTop = contentPosition + scrollEquivalent;
    }
}

function createScroller() {
    // *Creates scroller element and appends to '.scrollable' div
    // create scroller element
    scroller = document.createElement("div");
    scroller.className = 'scroller';

    // determine how big scroller should be based on content
    scrollerHeight = calculateScrollerHeight();

    if (scrollerHeight / scrollContainer.offsetHeight < 1){
        // *If there is a need to have scroll bar based on content size
        scroller.style.height = scrollerHeight + 'px';

        // append scroller to scrollContainer div
        scrollContainer.appendChild(scroller);

        // show scroll path divot
        scrollContainer.className += ' showScroll';

        // attach related draggable listeners
        scroller.addEventListener('mousedown', startDrag);
        window.addEventListener('mouseup', stopDrag);
        window.addEventListener('mousemove', scrollBarScroll)
    }

}

createScroller();


// *** Listeners ***
scrollContentWrapper.addEventListener('scroll', moveScroller);
}());

这个概念很简单。我们有一个带有“可滚动”类的主 div。 JavaScript 识别此元素并附加一个滚动 div,您可以使用 CSS 设置自己的样式。通过嵌套 content-wrapper 子 div,我们可以有效地将原生滚动条推到父 div 之外,同时仍然控制填充。

这是一个图表:

我们需要保持原生滚动能力的原因是因为 JavaScript 滚动事件只在溢出设置为滚动的元素上触发。见MDN reference on scroll。好处是如果 JS 被禁用,我们仍然可以优雅地回退到没有滚动条的滚动。


注意
您应该注意,在某些情况下,您必须调整版本以重新计算滚动条大小:
1.) 调整屏幕大小或
2.) 如果追加更多内容。

其次,如果您有多个“可滚动”元素,则必须进行修改。在这种情况下,您将需要遍历这些元素以附加滚动 div 并监听滚动事件。

【讨论】:

  • AdamSchuld - 非常感谢您花时间帮助我解决我的问题。我在 IE 和 Chrome 中尝试了小提琴,但我看不到滚动条出现。有时间可以看看这个。也许我缺少一些东西。我注意到你有一个工作网站。也许可以向该站点添加示例页面以显示滚动。就像designgumption.com/scroll.html 这只是一个想法,因为有时我发现很难在他们使用的小窗口中看到小提琴的结果。再次感谢
  • 在 Codepen (codepen.io/ElGrecode/pen/LEmbBE) 中我取出了华丽的动画效果,可能是 css 属性导致了问题。除了 IE,这是跨浏览器测试的。
  • 谢谢。我再次查看了您的 jsfiddle 实现,当我移动鼠标滚轮或光标然后再次消失时,它确实有效。这让我很困惑,因为我一直期待看到 scollbar。所以我认为你的codepen版本更好。当我查看 codepen 时,我看到他们使用的滚动条非常好。您是否认为您可以添加到您的实现中,以便用户也可以像使用 codepen 中的滚动条一样拖动滚动条?
  • 其实只需要鼠标拖动即可。我想为触摸提供一个替代实现(不是这个问题的一部分),这可能只是使用传统的滚动。对于您当前的实现,我认为拖动非常重要。谢谢
  • 更新了可拖动的滚动条。对解决方案非常满意。稍微润色一下,这可能是事实上的非 jquery 滚动条
【解决方案2】:

我知道这个问题已经有了答案,但是一旦 OP 想要一个简单的原生 javascript 解决方案,它适用于现代浏览器 - 我认为更多的人可能也需要它,我会迟到了这里回答这个问题,因为我开发了一个very simple and lightweight library in pure vanilla JSDEMO),压缩和缩小后只有1KB。

它使用原生滚动,因此它适用于所有现代浏览器(Firefox、Chrome、Opera、Safari、Edge)以及 IE10 和 IE11。您也可以通过包含一个 classList polyfill 在 IE9 中使用它。

支持所有 Android、iOS 和 Windows Phone 浏览器。

在此处查看更详细的答案:Custom scrollbars

或阅读SimpleScrollbar's Github README page中的完整教程。

【讨论】:

    【解决方案3】:

    有一个很棒的baron.js library。它可以是 jQuery 的用户,也可以是没有它的用​​户。这个想法与@AdamSchuld 在他的回答中描述的完全一样。

    它的优点:

    • 不替换本机系统滚动机制(当您希望滚动条看起来自定义但保存原始平台或设备行为时,这一点很重要)。

    • 具有完整 CSS 支持的可自定义滚动条设计。

    • 对 jQuery 没有强依赖。

    • 插件系统(可修复页眉、粘性页脚、自动测试等)

    • 可以在隐藏块上启动

    这里是simple demo of it

    【讨论】:

      猜你喜欢
      • 2019-12-09
      • 2020-11-26
      • 2016-04-16
      • 2018-12-16
      • 2014-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多