Can markers be positioned on top of scroll bars?

Looking for a way to display small markers on the scrollbar of an overflow: scroll element, similar to features found in IDEs and text editors like this one: https://github.com/surdu/scroll-marker.

I've considered using a pointer-events: none overlay on the scrollable element with absolute-positioned elements, but aligning them correctly could be tricky due to variations in scrollbar dimensions across platforms and browsers. This approach also seems somewhat hacky.

Any suggestions?

Answer №1

Here is the solution to the challenge presented. While it may not be flawless, I believe it can provide some guidance moving forward.
Let me explain the approach taken:

A container with fixed dimensions contains two elements: .inner-container for text and .scroll-marker to display marks over the scrollbar.

The text is wrapped in <p> tags, and specific portions are highlighted using <span> tags with classes like .red, .yellow, or .blue based on color coding. These markers are dynamically created within a loop and appended to the .scroll-marker element with absolute positioning. A calculation is performed to ensure accurate scroll positioning.

var container = document.querySelector('.container');
var containerInner = document.querySelector('.container-inner');

var containerHeight = container.offsetHeight;
var containerScrollHeight = containerInner.scrollHeight;

var scrollMarker = document.querySelector('.scroll-marker');

var colorfulStuff = document.querySelectorAll('.container-inner span'); // colorful spans from text

colorfulStuff.forEach(function (span) { // loop to create each marker

    var spanTop = span.offsetTop;
    var spanBottom = spanTop + span.offsetHeight;

    var markerTop = Math.ceil(spanTop * containerHeight / containerScrollHeight);
    var markerBottom = Math.ceil(spanBottom * containerHeight / containerScrollHeight);

    if (span.className === "red") { // choose the correct color
        var markerColor = '#f65e5a';
    } else if (span.className === "yellow") {
        var markerColor = '#fec740';
    } else if (span.className === "blue") {
        var markerColor = '#2985d0';
    }

    var markerElement = document.createElement("span"); // create the marker, set color and position and put it there
    markerElement.style.backgroundColor = markerColor;
    markerElement.style.top = markerTop + "px"
    markerElement.style.height = (markerBottom - markerTop) + "px"
    scrollMarker.appendChild(markerElement);

})
.container {
    background: #2d3744;
    border-radius: 4px;
    position: relative;
    margin: 30px auto;
    height: 320px;
    width: 300px;
    box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, 0.65);
}

.container-inner {
    padding: 20px 30px;
    height: calc(100% - 40px);
    overflow-y: auto;
    overflow-x: hidden;
}

p {
    color: white;
    margin: 12px 0;
    font-size: 18px;
    font-family: sans-serif;
    letter-spacing: 0.44px;
}

.red {
    color: #f65e5a;
}

.yellow {
    color: #fec740;
}

.blue {
    color: #2985d0;
}

.scroll-marker {
    position: absolute;
    height: 100%;
    width: 12px;
    pointer-events: none;
    top: 0;
    right: 0;
}

.scroll-marker span {
    /* markers */
    position: absolute;
    width: 100%;
}

/* scrollbar style */

.container-inner::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
    background-color: #2d3744;
}

.container-inner::-webkit-scrollbar {
    width: 12px;
    background-color: #2d3744;
}

.container-inner::-webkit-scrollbar-thumb {
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
    background-color: #4c5f74;
}
<div class="container">
  <div class="container-inner">
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore asperiores <span class="yellow">provident magnam impedit deleniti modi, culpa perspiciatis ex illum iusto vel nulla expedita itaque temporibus</span> voluptate non magni. Voluptatem, itaque.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore asperiores provident <span class="blue">magnam impedit deleniti modi</span>, culpa perspiciatis ex illum iusto vel nulla expedita itaque temporibus voluptate non magni. Voluptatem, itaque.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. <span class="yellow">Inventore asperiores provident</span> magnam impedit deleniti modi, culpa perspiciatis ex illum iusto vel nulla expedita itaque temporibus voluptate non magni. Voluptatem, itaque.</p>
    <p><span class="red">Lorem ipsum</span> dolor sit amet consectetur adipisicing elit. Inventore asperiores provident magnam impedit deleniti modi, culpa <span class="red">perspiciatis ex illum iusto vel nulla expedita itaque temporibus voluptate non magni.</span> Voluptatem, itaque.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore asperiores provident magnam impedit deleniti modi, culpa perspiciatis ex illum iusto vel nulla expedita itaque temporibus voluptate non magni. Voluptatem, itaque.</p>
    <p><span class="yellow">Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore asperiores provident magnam impedit deleniti modi, culpa perspiciatis ex illum iusto vel nulla expedita itaque temporibus</span> voluptate non magni. Voluptatem, itaque.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore asperiores provident magnam impedit deleniti modi, culpa perspiciatis ex illum iusto vel nulla expedita itaque temporibus voluptate non magni. <span class="blue">Voluptatem, itaque.</span></p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore asperiores provident magnam impedit deleniti modi, culpa perspiciatis ex illum iusto vel nulla expedita itaque temporibus voluptate non magni. Voluptatem, itaque.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore asperiores provident magnam impedit deleniti modi, culpa perspiciatis ex illum iusto vel nulla expedita itaque temporibus voluptate non magni. Voluptatem, itaque.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore asperiores <span class="yellow">provident magnam</span> impedit deleniti modi, culpa <span class="blue">perspiciatis ex illum iusto vel nulla expedita itaque</span> temporibus voluptate non magni. Voluptatem, itaque.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore asperiores provident magnam impedit deleniti modi, culpa perspiciatis <span class="red">ex illum</span> iusto vel nulla expedita itaque temporibus voluptate non magni. Voluptatem, itaque.</p>
  </div>
  <div class="scroll-marker"></div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error occurred when trying to import an external module using an invalid hook call

I am creating a package named "Formcomponent" using React and React Bootstrap. This code is from index.tsx /** * Renders a component for a form. */ import React from "react"; import Form from "react-bootstrap/Form"; /** * List of props * @returns */ ...

Can text automatically adjust its size based on the browser's dimensions using CSS?

Can text automatically resize as the browser size decreases for liquid-based design using percentages? While images and divs can rescale, text scaling in percentages seems impossible! When set in percentages, it only changes the unified em setting for tha ...

What could be the reason for the malfunctioning of the header() function in PHP

Currently, I'm utilizing AJAX to facilitate user registration for a service. Here's the code snippet for the submit button: <input type="button" id="register" name="register" class="btn btn-success" onclick="registration();" value="Register"/ ...

Stop flex child from shrinking in size

I have a form row with two inputs. There is a requirement to show ⚠️ (warning emoji) next to the second input in the row, based on the input number. However, because of how flexbox behaves, the input size gets reduced... How can I maintain the input s ...

Import data from JSON using JavaScript

I have a collection of txt files that contain custom content. The file names are stored in a JSON array. { txtFiles: ['./file1.txt', './file2.txt', './file3.txt'] } I am looking to use the require function in JavaScript t ...

What makes Django forms the better choice over HTML forms?

Greetings! As a beginner in the world of Django, I am currently struggling to grasp the concept of Django forms. I find myself questioning the utility of Django forms when we already have the option to use HTML forms. Can someone please clarify this for ...

Differences between $.ajaxPrefilter() and $.ajaxSetup() in jQuery Ajax

During my exploration of ajax in jQuery, I encountered two terms: $.ajaxPrefilter() and $.ajaxSetup(). It seems that both of these terms are related to making modifications to AJAX operations before they are executed or called by $.ajax(). Could someone p ...

Guide to running a NextJS app alongside an Express server backend on the same localhost port

I'm working on hosting my NextJS app, which is built with React, on the same localhost port as my express api-server backend. Within my express server API settings, I have configured my API server to listen on: http://localhost:3000/graphql How can ...

The parameters in VueJS are malfunctioning on this webpage

I created my vue in an external file and included it at the bottom of my webpage, but I am encountering issues with its functionality. One specific problem arises when using v-model, resulting in a template error displayed on the page: Error compiling t ...

Oops: Looks like there is already a request for 'PUBLIC_requestAccounts' pending from http://localhost:3000. Just hold tight for now

There comes a moment when an unexpected error arises and fails to establish a connection with your wallet. if (window.ethereum) { console.log("11") const connect = async () => { const account = await window.ethereum.request({ ...

CSS Code Failing to Adjust Inner Components Width in Variable Table

I'm facing an issue while trying to create an excel-style table using HTML and CSS. The problem arises when I attempt to have a varying number of columns in different rows, as the table exceeds the border limit and expands on its own. My goal is to re ...

Vuejs is throwing an uncaught promise error due to a SyntaxError because it encountered an unexpected "<" token at the beginning of a JSON object

I am currently attempting to generate a treemap visualization utilizing data sourced from a .json file. My approach involves employing d3 and Vue to assist in the implementation process. However, upon attempting to import my data via the d3.json() method ...

Creating an HTML Canvas effect where images are placed onto another image

Looking to create a similar effect as seen on this website () On this site, users can upload their images (4000 * 400) and have the option to add Mickey Mouse ears over their image before saving it. The Mickey Mouse ear is resizable from all four sides f ...

is it possible to adjust the height of a tableRow in mui?

I recently created a table component using Mui. I've been attempting to adjust the height of the tableRows, but so far I haven't had any success. Below is my code snippet: import React, { memo } from "react"; import { ActionItemType, ...

Design: A stationary text box positioned on the left side alongside a selection of scrollable MDL cards on the right

I'm currently experiencing a challenge with adjusting the text on two specific pages. On one side, there is a box with text, while on the other are two MDL cards displaying dialogues. The trouble arises when I try to set a fixed position for the text ...

Having trouble getting Calendly Webhooks to function in a node.js environment with ngrok?

Hello everyone, this is my first time seeking help on Stack Overflow so please bear with me if there are any flaws in my question. I recently started using the Calendly Teams version and decided to implement the Webhooks feature on a Node.js web applicati ...

Tips for minimizing Angular $digest-cycle invocations

Issue In my application, I have noticed that some callbacks are being called excessively during the $digest cycle. This high frequency of calls is causing performance concerns as these callbacks are triggered way more times than expected, sometimes even e ...

Transform the date to match the user's preferred timezone abbreviation

I am currently utilizing the momentJS library for timezone conversion logic within my JavaScript code. I retrieve the User Preference Timezone abbreviation from a web service response, but when attempting to convert the date using the Timezone abbreviation ...

What causes the statement to be executed before the database transaction?

How can I ensure that the state domains are set only after all DB transactions are completed in my code? Please provide guidance on how to perform this operation correctly. I am using the following method to update the new domains array: setFavorites() { ...

In React Js, the state is being updated correctly when console logging, however, the user interface is not reflecting

Recently, I encountered an issue with updating the UI after clearing the input states in my object. Despite setting the input values to empty strings upon clicking the clear all button, the UI does not reflect these changes as expected. The initial state ...