CSS customized scroll bar in div

后端 未结 19 1445
夕颜
夕颜 2020-11-21 11:05

How can I customize a scroll bar via CSS (Cascading Style Sheets) for one div and not the whole page?

19条回答
  •  青春惊慌失措
    2020-11-21 11:37

    Like many people, I was looking for something that was:

    • Consistently styled and functional across most modern browsers
    • Not some ridiculous 3000-line bloated jQuery extension cr*p

    ...But alas - nothing!

    Well if a job's worth doing... I was able to get something up and running in about 30 mins. Disclaimer: there's quite a few known (and probably a few as yet unknown) problems with it, but it makes me wonder what on Earth the other 2920 lines of JS are there for in many offerings!

    (window => {
    
      let initCoords;
    
      const coords_update = e => {
        if (initCoords) {
          const elem = initCoords.bar.closest('.scrollr');
          const eSuffix = initCoords.axis.toUpperCase();
          const sSuffix = initCoords.axis == 'x' ? 'Left' : 'Top';
          const dSuffix = initCoords.axis == 'x' ? 'Width' : 'Height';
          const max = elem['scroll' + dSuffix] - elem['client' + dSuffix];
          const room = elem['client' + dSuffix] - initCoords.bar['client' + dSuffix];
          const delta = e['page' + eSuffix] - initCoords.abs;
          const abs = initCoords.p0 + delta;
          elem['scroll' + sSuffix] = max * abs / room;
        }
      };
    
      const scrollr_resize = elem => {
        const xBar = elem.querySelector('.track.x .bar');
        const yBar = elem.querySelector('.track.y .bar');
        const xRel = elem.clientWidth / elem.scrollWidth;
        const yRel = elem.clientHeight / elem.scrollHeight;
        xBar.style.width = (100 * xRel).toFixed(2) + '%';
        yBar.style.height = (100 * yRel).toFixed(2) + '%';
      };
    
      const scrollr_init = elem => {
        const xTrack = document.createElement('span');
        const yTrack = document.createElement('span');
        const xBar = document.createElement('span');
        const yBar = document.createElement('span');
        xTrack.className = 'track x';
        yTrack.className = 'track y';
        xBar.className = 'bar';
        yBar.className = 'bar';
        xTrack.appendChild(xBar);
        yTrack.appendChild(yBar);
        elem.appendChild(xTrack);
        elem.appendChild(yTrack);
        elem.addEventListener('wheel', scrollr_OnWheel);
        elem.addEventListener('scroll', scrollr_OnScroll);
        xTrack.addEventListener('wheel', xTrack_OnWheel);
        xTrack.addEventListener('click', xTrack_OnClick);
        xTrack.addEventListener('mouseover', () => xTrack.classList.add('active'));
        xTrack.addEventListener('mouseout', () => {
          if (!initCoords) xTrack.classList.remove('active');
        });
        yTrack.addEventListener('click', yTrack_OnClick);
        yTrack.addEventListener('mouseover', () => yTrack.classList.add('active'));
        yTrack.addEventListener('mouseout', () => {
          if (!initCoords) yTrack.classList.remove('active');
        });
        xBar.addEventListener('click', bar_OnClick);
        xBar.addEventListener('mousedown', xBar_OnMouseDown);
        yBar.addEventListener('click', bar_OnClick);
        yBar.addEventListener('mousedown', yBar_OnMouseDown);
    
        scrollr_resize(elem);
      };
    
      window.addEventListener('load', e => {
        const scrollrz = Array.from(document.querySelectorAll('.scrollr'));
        scrollrz.forEach(scrollr_init);
      });
    
      window.addEventListener('resize', e => {
        const scrollrz = Array.from(document.querySelectorAll('.scrollr'));
        scrollrz.forEach(scrollr_resize);
      });
    
      window.addEventListener('mousemove', coords_update);
      window.addEventListener('mouseup', e => {
        initCoords = null;
        Array.from(document.querySelectorAll('.track.active'))
          .forEach(elem => elem.classList.remove('active'));
      });
    
      function xBar_OnMouseDown(e) {
        const p0 = this.offsetLeft;
        initCoords = {
          axis: 'x',
          abs: e.pageX,
          bar: this,
          p0
        };
      }
    
      function yBar_OnMouseDown(e) {
        const p0 = this.offsetTop;
        initCoords = {
          axis: 'y',
          abs: e.pageY,
          bar: this,
          p0
        };
      }
    
      function bar_OnClick(e) {
        e.stopPropagation();
      }
    
      function xTrack_OnClick(e) {
        const elem = this.closest('.scrollr');
        const xBar = this.querySelector('.bar');
        let unit = elem.clientWidth - 30;
        if (e.offsetX <= xBar.offsetLeft) unit *= -1;
        elem.scrollLeft += unit;
      }
    
      function yTrack_OnClick(e) {
        const elem = this.closest('.scrollr');
        const yBar = this.querySelector('.bar');
        let unit = elem.clientHeight - 30;
        if (e.offsetY <= yBar.offsetTop) unit *= -1;
        elem.scrollTop += unit;
      }
    
      function xTrack_OnWheel(e) {
        e.stopPropagation();
        const elem = this.closest('.scrollr');
        const left0 = elem.scrollLeft;
        const delta = e.deltaY !== 0 ? e.deltaY : e.deltaX;
        elem.scrollLeft += delta;
        const moved = left0 !== elem.scrollLeft;
        if (moved) e.preventDefault();
      }
    
      function scrollr_OnWheel(e) {
        const left0 = this.scrollLeft;
        const top0 = this.scrollTop;
        this.scrollLeft += e.deltaX;
        this.scrollTop += e.deltaY;
        const moved = left0 !== this.scrollLeft || top0 !== this.scrollTop;
        if (moved) e.preventDefault();
      }
    
      function scrollr_OnScroll(e) {
        const xTrack = this.querySelector('.track.x');
        const yTrack = this.querySelector('.track.y');
        const xBar = xTrack.querySelector('.bar');
        const yBar = yTrack.querySelector('.bar');
    
        const xMax = this.scrollWidth - this.clientWidth;
        const yMax = this.scrollHeight - this.clientHeight;
        const xFrac = this.scrollLeft / xMax;
        const yFrac = this.scrollTop / yMax;
        const xAbs = xFrac * (this.clientWidth - xBar.clientWidth);
        const yAbs = yFrac * (this.clientHeight - yBar.clientHeight);
    
        xTrack.style.left = this.scrollLeft + 'px';
        xTrack.style.bottom = -this.scrollTop + 'px';
        xBar.style.left = xAbs + 'px';
    
        yTrack.style.top = this.scrollTop + 'px';
        yTrack.style.right = -this.scrollLeft + 'px';
        yBar.style.top = yAbs + 'px';
      };
    
    })(window);
    .scrollr {
      overflow: hidden;
      position: relative;
    }
    
    .track {
      position: absolute;
      cursor: pointer;
      transition: background-color .3s;
      user-select: none;
    }
    
    .track.x {
      left: 0;
      bottom: 0;
      width: 100%;
      height: 10px;
    }
    
    .track.y {
      top: 0;
      right: 0;
      height: 100%;
      width: 10px;
    }
    
    .bar {
      position: absolute;
      background-color: yellow;
      transition: background-color .3s, opacity .3s, width .3s, height .3s, margin .3s;
      display: block;
      width: 100%;
      height: 100%;
      opacity: .7;
    }
    
    .track.x .bar {
      min-width: 25px;
      height: 3px;
      margin: 5px 0 2px 0;
    }
    
    .track.y .bar {
      min-height: 25px;
      width: 3px;
      margin: 0 2px 0 5px;
    }
    
    .track.active {
      background-color: #ccc;
    }
    
    .track.active .bar {
      background-color: #999;
      margin: 0;
      opacity: 1;
    }
    
    .track.x.active .bar {
      height: 10px;
    }
    
    .track.y.active .bar {
      width: 10px;
    }
    
    
    /* Custom client stuff */
    
    .content {
      background: red;
    }
    
    .content p {
      width: 450px;
      margin: 0;
    }
    
    .scrollr {
      max-width: 350px;
      max-height: 150px;
    }

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc diam magna, molestie sit amet auctor nec, dictum quis mi. Duis pellentesque lacinia pretium. Donec pulvinar, risus sit amet dapibus mattis, eros urna bibendum elit, vel mollis sapien arcu vitae mi. Fusce vulputate vestibulum metus dapibus eleifend. Quisque ut dictum orci. Nunc bibendum, sapien ac condimentum placerat, arcu orci mollis nunc, vitae sollicitudin arcu nulla quis enim. Praesent non tellus vitae quam tempor maximus vel sed dolor. Donec id ante ultricies, iaculis sem ut, sollicitudin enim. Quisque id mauris est. Maecenas viverra urna vitae velit semper, vel ultricies augue feugiat. Pellentesque in libero porttitor, lacinia metus in, maximus nisi. Phasellus commodo ligula vel arcu iaculis hendrerit vitae vel diam. Sed sed lorem maximus, vestibulum leo ut, posuere libero. Donec arcu dui, euismod id aliquet sed, porttitor vitae elit.

    Sed aliquam eget justo sit amet dictum. Suspendisse potenti. In placerat orci quis vehicula vehicula. Proin tempor laoreet suscipit. Proin non nulla lacinia est ullamcorper maximus et a sem. Nulla at lacus rhoncus, malesuada ante in, imperdiet sem. Mauris convallis tristique metus in iaculis. Nulla laoreet ligula non interdum tincidunt. Morbi sed venenatis arcu, sed gravida est. Fusce malesuada ullamcorper lacus, in vulputate risus finibus non.

    Suspendisse sapien leo, auctor non ex vitae, volutpat laoreet tortor. Suspendisse sodales libero velit, sed pulvinar lectus feugiat vel. Sed erat eros, porttitor id enim nec, ornare hendrerit nibh. Phasellus at nisi lectus. Cras semper lobortis condimentum. Etiam nunc felis, vehicula vitae tincidunt pellentesque, pretium sit amet dui. Duis aliquet ultrices lacus eget efficitur. Ut imperdiet velit sed enim laoreet, sed semper libero hendrerit. Donec malesuada auctor sollicitudin.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc diam magna, molestie sit amet auctor nec, dictum quis mi. Duis pellentesque lacinia pretium. Donec pulvinar, risus sit amet dapibus mattis, eros urna bibendum elit, vel mollis sapien arcu vitae mi. Fusce vulputate vestibulum metus dapibus eleifend. Quisque ut dictum orci. Nunc bibendum, sapien ac condimentum placerat, arcu orci mollis nunc, vitae sollicitudin arcu nulla quis enim. Praesent non tellus vitae quam tempor maximus vel sed dolor. Donec id ante ultricies, iaculis sem ut, sollicitudin enim. Quisque id mauris est. Maecenas viverra urna vitae velit semper, vel ultricies augue feugiat. Pellentesque in libero porttitor, lacinia metus in, maximus nisi. Phasellus commodo ligula vel arcu iaculis hendrerit vitae vel diam. Sed sed lorem maximus, vestibulum leo ut, posuere libero. Donec arcu dui, euismod id aliquet sed, porttitor vitae elit.

    Sed aliquam eget justo sit amet dictum. Suspendisse potenti. In placerat orci quis vehicula vehicula. Proin tempor laoreet suscipit. Proin non nulla lacinia est ullamcorper maximus et a sem. Nulla at lacus rhoncus, malesuada ante in, imperdiet sem. Mauris convallis tristique metus in iaculis. Nulla laoreet ligula non interdum tincidunt. Morbi sed venenatis arcu, sed gravida est. Fusce malesuada ullamcorper lacus, in vulputate risus finibus non.

    Suspendisse sapien leo, auctor non ex vitae, volutpat laoreet tortor. Suspendisse sodales libero velit, sed pulvinar lectus feugiat vel. Sed erat eros, porttitor id enim nec, ornare hendrerit nibh. Phasellus at nisi lectus. Cras semper lobortis condimentum. Etiam nunc felis, vehicula vitae tincidunt pellentesque, pretium sit amet dui. Duis aliquet ultrices lacus eget efficitur. Ut imperdiet velit sed enim laoreet, sed semper libero hendrerit. Donec malesuada auctor sollicitudin.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc diam magna, molestie sit amet auctor nec, dictum quis mi. Duis pellentesque lacinia pretium. Donec pulvinar, risus sit amet dapibus mattis, eros urna bibendum elit, vel mollis sapien arcu vitae mi. Fusce vulputate vestibulum metus dapibus eleifend. Quisque ut dictum orci. Nunc bibendum, sapien ac condimentum placerat, arcu orci mollis nunc, vitae sollicitudin arcu nulla quis enim. Praesent non tellus vitae quam tempor maximus vel sed dolor. Donec id ante ultricies, iaculis sem ut, sollicitudin enim. Quisque id mauris est. Maecenas viverra urna vitae velit semper, vel ultricies augue feugiat. Pellentesque in libero porttitor, lacinia metus in, maximus nisi. Phasellus commodo ligula vel arcu iaculis hendrerit vitae vel diam. Sed sed lorem maximus, vestibulum leo ut, posuere libero. Donec arcu dui, euismod id aliquet sed, porttitor vitae elit.

    Sed aliquam eget justo sit amet dictum. Suspendisse potenti. In placerat orci quis vehicula vehicula. Proin tempor laoreet suscipit. Proin non nulla lacinia est ullamcorper maximus et a sem. Nulla at lacus rhoncus, malesuada ante in, imperdiet sem. Mauris convallis tristique metus in iaculis. Nulla laoreet ligula non interdum tincidunt. Morbi sed venenatis arcu, sed gravida est. Fusce malesuada ullamcorper lacus, in vulputate risus finibus non.

    Suspendisse sapien leo, auctor non ex vitae, volutpat laoreet tortor. Suspendisse sodales libero velit, sed pulvinar lectus feugiat vel. Sed erat eros, porttitor id enim nec, ornare hendrerit nibh. Phasellus at nisi lectus. Cras semper lobortis condimentum. Etiam nunc felis, vehicula vitae tincidunt pellentesque, pretium sit amet dui. Duis aliquet ultrices lacus eget efficitur. Ut imperdiet velit sed enim laoreet, sed semper libero hendrerit. Donec malesuada auctor sollicitudin.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc diam magna, molestie sit amet auctor nec, dictum quis mi. Duis pellentesque lacinia pretium. Donec pulvinar, risus sit amet dapibus mattis, eros urna bibendum elit, vel mollis sapien arcu vitae mi. Fusce vulputate vestibulum metus dapibus eleifend. Quisque ut dictum orci. Nunc bibendum, sapien ac condimentum placerat, arcu orci mollis nunc, vitae sollicitudin arcu nulla quis enim. Praesent non tellus vitae quam tempor maximus vel sed dolor. Donec id ante ultricies, iaculis sem ut, sollicitudin enim. Quisque id mauris est. Maecenas viverra urna vitae velit semper, vel ultricies augue feugiat. Pellentesque in libero porttitor, lacinia metus in, maximus nisi. Phasellus commodo ligula vel arcu iaculis hendrerit vitae vel diam. Sed sed lorem maximus, vestibulum leo ut, posuere libero. Donec arcu dui, euismod id aliquet sed, porttitor vitae elit.

    Sed aliquam eget justo sit amet dictum. Suspendisse potenti. In placerat orci quis vehicula vehicula. Proin tempor laoreet suscipit. Proin non nulla lacinia est ullamcorper maximus et a sem. Nulla at lacus rhoncus, malesuada ante in, imperdiet sem. Mauris convallis tristique metus in iaculis. Nulla laoreet ligula non interdum tincidunt. Morbi sed venenatis arcu, sed gravida est. Fusce malesuada ullamcorper lacus, in vulputate risus finibus non.

    Suspendisse sapien leo, auctor non ex vitae, volutpat laoreet tortor. Suspendisse sodales libero velit, sed pulvinar lectus feugiat vel. Sed erat eros, porttitor id enim nec, ornare hendrerit nibh. Phasellus at nisi lectus. Cras semper lobortis condimentum. Etiam nunc felis, vehicula vitae tincidunt pellentesque, pretium sit amet dui. Duis aliquet ultrices lacus eget efficitur. Ut imperdiet velit sed enim laoreet, sed semper libero hendrerit. Donec malesuada auctor sollicitudin.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc diam magna, molestie sit amet auctor nec, dictum quis mi. Duis pellentesque lacinia pretium. Donec pulvinar, risus sit amet dapibus mattis, eros urna bibendum elit, vel mollis sapien arcu vitae mi. Fusce vulputate vestibulum metus dapibus eleifend. Quisque ut dictum orci. Nunc bibendum, sapien ac condimentum placerat, arcu orci mollis nunc, vitae sollicitudin arcu nulla quis enim. Praesent non tellus vitae quam tempor maximus vel sed dolor. Donec id ante ultricies, iaculis sem ut, sollicitudin enim. Quisque id mauris est. Maecenas viverra urna vitae velit semper, vel ultricies augue feugiat. Pellentesque in libero porttitor, lacinia metus in, maximus nisi. Phasellus commodo ligula vel arcu iaculis hendrerit vitae vel diam. Sed sed lorem maximus, vestibulum leo ut, posuere libero. Donec arcu dui, euismod id aliquet sed, porttitor vitae elit.

    Sed aliquam eget justo sit amet dictum. Suspendisse potenti. In placerat orci quis vehicula vehicula. Proin tempor laoreet suscipit. Proin non nulla lacinia est ullamcorper maximus et a sem. Nulla at lacus rhoncus, malesuada ante in, imperdiet sem. Mauris convallis tristique metus in iaculis. Nulla laoreet ligula non interdum tincidunt. Morbi sed venenatis arcu, sed gravida est. Fusce malesuada ullamcorper lacus, in vulputate risus finibus non.

    Suspendisse sapien leo, auctor non ex vitae, volutpat laoreet tortor. Suspendisse sodales libero velit, sed pulvinar lectus feugiat vel. Sed erat eros, porttitor id enim nec, ornare hendrerit nibh. Phasellus at nisi lectus. Cras semper lobortis condimentum. Etiam nunc felis, vehicula vitae tincidunt pellentesque, pretium sit amet dui. Duis aliquet ultrices lacus eget efficitur. Ut imperdiet velit sed enim laoreet, sed semper libero hendrerit. Donec malesuada auctor sollicitudin.

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc diam magna, molestie sit amet auctor nec, dictum quis mi. Duis pellentesque lacinia pretium. Donec pulvinar, risus sit amet dapibus mattis, eros urna bibendum elit, vel mollis sapien arcu vitae mi. Fusce vulputate vestibulum metus dapibus eleifend. Quisque ut dictum orci. Nunc bibendum, sapien ac condimentum placerat, arcu orci mollis nunc, vitae sollicitudin arcu nulla quis enim. Praesent non tellus vitae quam tempor maximus vel sed dolor. Donec id ante ultricies, iaculis sem ut, sollicitudin enim. Quisque id mauris est. Maecenas viverra urna vitae velit semper, vel ultricies augue feugiat. Pellentesque in libero porttitor, lacinia metus in, maximus nisi. Phasellus commodo ligula vel arcu iaculis hendrerit vitae vel diam. Sed sed lorem maximus, vestibulum leo ut, posuere libero. Donec arcu dui, euismod id aliquet sed, porttitor vitae elit.

    Sed aliquam eget justo sit amet dictum. Suspendisse potenti. In placerat orci quis vehicula vehicula. Proin tempor laoreet suscipit. Proin non nulla lacinia est ullamcorper maximus et a sem. Nulla at lacus rhoncus, malesuada ante in, imperdiet sem. Mauris convallis tristique metus in iaculis. Nulla laoreet ligula non interdum tincidunt. Morbi sed venenatis arcu, sed gravida est. Fusce malesuada ullamcorper lacus, in vulputate risus finibus non.

    Suspendisse sapien leo, auctor non ex vitae, volutpat laoreet tortor. Suspendisse sodales libero velit, sed pulvinar lectus feugiat vel. Sed erat eros, porttitor id enim nec, ornare hendrerit nibh. Phasellus at nisi lectus. Cras semper lobortis condimentum. Etiam nunc felis, vehicula vitae tincidunt pellentesque, pretium sit amet dui. Duis aliquet ultrices lacus eget efficitur. Ut imperdiet velit sed enim laoreet, sed semper libero hendrerit. Donec malesuada auctor sollicitudin.

提交回复
热议问题