The behavior of jQuery's position().top is consistent with offset().top when used within a fixed parent element

I attempted to create a scroll bar that adjusts its position based on the top value of a fixed div rather than the window.

According to jQuery documentation, the .position() function returns the element's current position relative to its offset parent.

The .position() method allows us to retrieve the current position of an element (specifically its margin box) relative to the offset parent

The .offset() method is described as follows:

Get the current coordinates of the first element, or set the coordinates of every element, in the set of matched elements, relative to the document.

Based on this information, it appears that .position() should be relative to the parent while .offset() is always relative to the document.

I am trying to highlight my menu buttons based on the current scrolled position in a fixed div, not the window. However, the values I get from .position().top never seem to align with the fixed div's .scrollTop()

Here is a fiddle demonstrating the issue. When I adjust things to work based on the window, everything functions correctly. But as soon as I try to make it relative to the parent div, it behaves erratically.

Check out the JSFiddle here!

For easier reference, here is the code:

Any assistance or insights would be greatly appreciated!

HTML

<div class="wrapper">
    <div class="menu-left">
        <div class="menu-item" data-target="sec1">
            Section 1
        </div>
        <div class="menu-item" data-target="sec2">
            Section 2
        </div>
        <div class="menu-item" data-target="sec3">
            Section 3
        </div>
        <div class="menu-item" data-target="sec4">
            Section 4
        </div>
    </div>

    <div class="page-content">
        <h2 class="header" id="sec1">Section 1</h2>
        <div class="text-block">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor

        </div>

        <h2 class="header" id="sec2">Section 2</h2>
        <div class="text-block">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor

        </div>

        <h2 class="header" id="sec3">Section 3</h2>
        <div class="text-block">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor

        </div>

        <h2 class="header" id="sec4">Section 4</h2>
        <div class="text-block">

            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
        </div>
   </div>
 </div>

CSS

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}

.wrapper {
  padding-left: 240px;
  display: block;
}

.menu-left {
  background-color: #CCC !important;
  height: 100%;
  display: block;
  width: 240px;
  margin-left: -240px;
  position: fixed;
  z-index: 1000;
}

.page-content {
  background-color: #666;
  height: 100%;
  width: 100%;
  position: fixed;
  padding: 10px;
  overflow: scroll;
}

.menu-item {
  border-bottom: 1px solid #000;
  padding: 10px;
}

.menu-item:first-child {
  border-top: 1px solid #000;
}

.text-block {
  border: 1px solid #000;
  width: 600px;
  display: block;
  padding: 10px;
}

.menu-item:hover,
.active {
  background: #666;
  color: #fff;
}

JavaScript

container = $(".page-content");

$(".menu-item").click(function(e) {
  data_target = $(e.target).attr("data-target");
  container.animate({
    scrollTop: $("#" + data_target).offset().top - container.offset().top + container.scrollTop()
  }, 2000);
});

$('.menu-item').on('click', function(event) {
  $('.menu-item').removeClass('active');
  $(this).addClass('active');
});

container.on('scroll', function() {
//$(window).on('scroll', function() {
  $('.header').each(function() {

    if(container.scrollTop() >= $(this).offset().top) {
    //if(container.scrollTop() >= $(this).position().top) {
    //if ($(window).scrollTop() >= $(this).offset().top) {
      var id = $(this).attr('id');
      $('.menu-item').removeClass('active');
      $('div[data-target=' + id + ']').addClass('active');
    }
  });
});

Answer №1

It appears that the main issue lies in acquiring the offsets of the header within the .on('scroll') event, coupled with the container's scrollTop(). This causes both values to be "refreshed" every time you scroll. To resolve this, it would be advisable to save the initial offsets upon the document load and then proceed with scrolling.

Furthermore, since you are already applying addClass/removeClass based on the scrollTop position, there is no need to re-add them when 'clicking.' This may explain the erratic behavior you're experiencing.

I have prepared a pen to illustrate the concept

var headerIds = [];
var headerOffset = [];

$('.header').each(function(){
  headerIds.push(this.id)
  headerOffset.push($(this).offset().top)
})

$(".menu-item").click(function(e) {
  data_target = $(e.target).attr("data-target");
  container.animate({
    scrollTop: $("#" + data_target).offset().top - container.offset().top + container.scrollTop() 
  }, 2000);
});

$(container).on("scroll", function(e) {
  headerIds.forEach(function(el, i){
    if ($(container).scrollTop() > (headerOffset[i]-20)) {
      $('.menu-item').removeClass('active');
      $('.menu-item:nth-of-type(' + (i + 1) + ')').addClass('active');
      var id = $(this).attr('id');
    }
  });
});

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

React Material UI - DataGrid Continuously Distracting Focus Away from Input Field

I'm currently facing an issue with my React web app using Material-UI. The problem arises when I try to type in the search input field, but the focus keeps getting stolen by the Material-UI DataGrid whenever I click on it. Oddly enough, this only occu ...

Guide to implementing Angular Material Slider with FormControl in Angular

I am looking to integrate Angular Material Slider with a FormControl in a FormGroup. I have a list of predefined values, each corresponding to a slider. The list is an array containing objects with unique IDs and titles: const itemList = [{id: 'anyId ...

Showing nested routes component information - Angular

I am working on a project that includes the following components: TodosComponent (path: './todos/'): displaying <p>TODO WORKS</p> AddTodosComponent (path: './todos/add'): showing <p>ADD TODO WORKS</p> DeleteTo ...

display/hide a div within a separate container

Greetings, I am seeking assistance in understanding why the second tab button is not functioning properly. I am attempting to create a layout with a wrapper div, a left side div containing label buttons, and a right side div for displaying content. When I ...

Show unauthorized page upon user's 'cancel' action (HTML/PHP)

As I continue to delve into the realms of html and php, I find myself facing a dilemma. I've created a simple webpage with basic authentication for users to access it. However, when a user clicks on the cancel button instead of entering their credenti ...

Integrate incoming websocket information with state management in React

I am facing a challenge in creating a timeseries plot with data obtained from a websocket connection. The issue arises when new values overwrite the previously stored value in the state variable. const [chartData, setChartData] = React.useState(null) Cu ...

What are the steps to create a dynamic grid interface using Bootstrap 5?

I attempted to use the code below but it did not work: <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.2/css/bootstrap.min.css" rel="stylesheet"/> <div class="container-fluid"> <div class="row"> <div c ...

The impact of adjusting the article's margin-top on the margin-top of

I want these two divs to have different positioning. The sidebar should remain fixed at the top. Why is the sidebar aligned with the article div instead of sticking to the top? body{ margin: 0; padding: 0; } div#sidebar{ background-color: yel ...

How do I find out the properties of individual components in Material UI?

Learning material ui has been a challenge for me as I struggle to figure out the properties available for each component. For instance, in a tutorial on YouTube, they used the AppBar component like this: <AppBar title="Enter user details" /> But ho ...

AngularJS iu.mask is a powerful tool for validating user input, especially when

Currently, I am learning Angular and have created an input field with type 'text' to display a date in the format "99/99/9999" using ui.mask. I have also implemented validation in the module to prevent submission (unblocking button) if the entere ...

Comparison of WebAPI Response Codes: Understanding the Difference Between 401 and

As a part of my learning project, I am developing a WebAPI and striving to implement best practices. The initial focus is on creating an authentication API that accepts an authentication object in JSON format: { username: myusername, password: mypa ...

The use of jQuery within the HTML tag allows for the execution of the function "myfunction()" when the mouse hovers

Is it feasible to implement a jQuery mouseover within an HTML tag? for(x=1; isset($_COOKIE["link$x"]); $x++) echo <div id="'.$x.'" onLoad="myfunction('.$x.')"> } Can we modify the example above to use "mouseenter" instead of ...

How can we use regular expressions in JavaScript?

Could someone please assist me with writing regular expressions in JavaScript? I need a simple example including details and source code. My current setup involves using ASP.NET and C# language. ...

Using Node.js and Multer to update a file uploaded to MongoDB

I have a website that allows users to upload files, but I also want them to be able to edit those files. This would involve the user pressing "edit" and replacing the existing file in the database with a new one. Normally, you can use findByIdAndUpdate for ...

Unable to establish a connection between two localhost servers

I'm encountering an issue with my API and React application setup. The API is running on localhost:3001, while the React app is on localhost:3000. Despite being able to make requests using Postman, I keep getting blocked by CORS policy when trying to ...

What is the best way to retrieve the ID of a post request using React's axios hook?

My goal is to make a post request to create an app, and then establish its links. To achieve this, I need to obtain the id of the newly created items in order to create the links. Is there a way to retrieve the id of the item created through the post reque ...

Tips for automatically injecting class text in Angular using dependency injection

Is there a method to automatically add a class when the user selects, for example, a list in the text editor? I would like to inject a class into the ul tag before saving it to the database. ...

What is the role of z-index in relation to floating elements?

Why is it impossible to assign a z-index to a floated image and what are the reasons behind this limitation? ...

Error: The operation cannot be performed as the specified function is invalid

Currently working on some jasmine testing in JS. I've created a testing function that looks good so far (only running the first test at the moment). describe('Anagram', function() { it('no matches',function() { var subject ...

Handling and iterating through unfamiliar objects in AngularJS

I've been exploring the concept of generics in ASP.NET MVC for a while now, and it got me thinking about how generics are used in other languages like AngularJS. Let's say I have 2 endpoints to work with: www.listofstudents.com/all and www.list ...