Wrapping elements with wrappers causes an incorrect offsetTop value to be retrieved

Previously, I used this approach for the target element and not the wrapper. However, it seems to be ineffective in this specific example. Upon running the code, some strange behaviors become apparent. The offsetTops of the sections are at 0 even before the wrappers are added to them. Another peculiar observation is that the wrappers seem to reach the very bottom, indicated by their offsetTops being calculated as body's offsetHeight minus the wrapper's offsetHeight. Could the issue be related to calling the function inside window.onload? I am puzzled as to what may be causing this. In each instance of logging to the console, the closest relatively positioned parent element appears to be the body. All elements have a display other than none. Can someone kindly shed light on what exactly is happening here? Also, please refrain from suggesting the use of getBoundingClientRect() as it does not apply in this context.

window.onload = function () {
  const sections = document.querySelectorAll("section");
  let eT = [];
  for (let i = 0, len = sections.length; i < len; i++) {
      const el = sections[i];
      console.log(el.offsetTop, el.offsetParent);
      if (el.parentNode.className !== "wrapper") {
          const wrapper = document.createElement("div");
          wrapper.className = "wrapper";
          el.parentNode.appendChild(wrapper);
          wrapper.appendChild(el);
          wrapper.style.height = el.offsetHeight + "px";
          wrapper.style.position = "relative";
      }
      const elCont = document.querySelectorAll(".wrapper")[i];
      let elClone = elCont;
      eT[i] = 0;
      do {
          eT[i] += elClone.offsetTop;
          elClone = elClone.offsetParent;
      }
      while (elClone !== document.body);
      console.log(eT[i], elCont.offsetHeight, document.body.offsetHeight);
  }
}
section{
  width: 100vw;
  height: 1000px;
  position: relative;
  border: 1px solid;
}
body{
  position: relative;
}
<body>
<section></section>
<section></section>
<section></section>
<section></section>
</body>

UPDATE I attempted using onscroll and everything functioned correctly. However, the underlying reasons for these anomalies remain unclear.

The load event occurs at the conclusion of the document loading process. At this stage, all objects in the document are present in the DOM, and all images, scripts, links, and sub-frames have completed loading. link

Hence, the behavior remains perplexing. Previously, I had also employed this function on load, where it worked without issues. Adding wrappers to the elements and retrieving their offsetTops seemed to trigger these unexpected occurrences. Furthermore, even when attempting the same process without wrappers, it failed to work. There were no alterations made to my previous working code, except for the introduction of the wrappers concept.

Answer №1

It seems to be a simple implementation issue, and the behavior is as expected. To understand better, let's walk through the explanation below:

/**
 * Let's analyze one iteration
 * For simplicity, let's name our sections S1, S2, S3, S4
 * Current DOM: body<S1 S2 S3 S4>
 */

// el = S1
if (el.parentNode.className !== "wrapper") {
    const wrapper = document.createElement("div");
    wrapper.className = "wrapper";
    el.parentNode.appendChild(wrapper);
    // Now wrapper is the last child of body with 4 sections above it
    // DOM: body<S1 S2 S3 S4 W>
    wrapper.appendChild(el);
    // el has been moved inside wrapper and removed from its original position
    // DOM: body<S2 S3 S4 W<S1>>
    wrapper.style.height = el.offsetHeight + "px";
    wrapper.style.position = "relative";
}

After adding each wrapper:

  1. There are 3 sections before the wrapper, so offsetTop is 3006 (1002 * 3)
  2. Since the topmost element is moved in each iteration, the next element becomes the new topmost element, resulting in an offsetTop of 0 for the next element.

This pattern repeats for all iterations, explaining why all sections have an offsetTop of 0 and all wrappers have an offsetTop of 3006.

And that concludes the explanation.

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

Contrast between using "export { something }" and "export something" in JavaScript modules

Can you explain the difference between the following code snippets: import something from "../something"; export { something }; vs import something from "../something"; export something; I noticed in the react-is package from react, there is an export ...

Methods to verify if an array contains a particular string within a PUG template

I'm currently working with NodeJS using Express and the PUG view engine. My goal is to determine whether an array includes a specific string. I've experimented with JavaScript's built-in methods like: array.includes(str) array.indexOf(str) ...

Looking for a node.js asset manager for converting coffeescript, jade, and stylus files to JS and CSS?

I specialize in using coffeescript, jade, and stylus for my projects. My task involves creating two separate "one page apps" where I need to include all assets within the initial payload. My goal is to consolidate, compile, and merge all coffeescript fil ...

Exchanging properties of jQuery selected elements

Context I am currently developing a web application using .NET 2.0 that utilizes standard WebControls. While the eventual plan is to migrate to version 4.x, I have an immediate need to modify its mobile behavior by incorporating HTML5 form input types for ...

Unable to implement the `omega/theme.css` file within the angular.json configuration

"styles": [ "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "node_modules/bootstrap/dist/css/bootstrap.min.css", "src/styles.css", "node_modules/primeicons/primeicons.css", ...

AngularJS: Issues with data retrieval in parallel in $http get requests within a $.each loop

Attempting to fetch data for multiple IDs is the goal: (Simplified version, aiming to clarify) Controller: var idList = [39,40,41]; $.each(idList, function(key, value){ var dataObject = { type: "test", id: value }; var getData = DataFactor ...

What is the process by which Elastic Beanstalk executes Node.js application code?

While my application runs smoothly on localhost, encountering no issues, deploying it to other platforms such as AWS or MCS presents a challenge. Specifically, the problem lies in recognizing the file paths required by the consign library to load the route ...

Switch out the current R shiny htmlwidget data for updated data

Recently, I encountered an issue with a htmlwidget in one of my R shiny applications. Each time the widget render function was called multiple times, it failed to replace the existing data with new data. This bug caused the old data to linger and the new d ...

"Picture positioned on the edge of the container, just on one

Using Bootstrap 4, I was able to create a container with a div positioned outside of the container on the right side. Now I am wondering if it is possible to achieve the same effect with a picture div. I managed to do so by using a pseudo-element :after an ...

The conversion of XML to HTML using setQuery(QString) in QXmlQuery is unsuccessful

Whenever I use the method setQuery(QUrl(file.xsl)), it functions properly. However, if I first load the file into a QString and then invoke setQuery(theString), the subsequent evaluateTo() operation fails (resulting in a boolean exception and empty result) ...

Troubleshooting ES Lint Issue: Passing Parameters to a Vue Method

I'm encountering an ES Lint Parsing Error in my Vue page due to a syntax issue. The problem seems to be arising from a parameter in my method that contains a dot symbol. Error - Syntax Error: Unexpected token (1:1628) <div class="text-sm ...

Expand the column to occupy the remaining height of the row

I've been on the hunt for a solution to this issue, but I haven't had any luck finding one. Various flexbox properties like flex-grow: 1; and align-self: stretch; have been attempted, but none seem to achieve the desired outcome. The goal is to ...

Transferring JSON data through AJAX to a PHP backend

I have been working on a solution to convert a CSV file into JSON and then send it to BigCommerce using their REST API. Initially, I planned to use Javascript for the entire process, and everything was successful until I encountered issues with CORS when t ...

Tips for styling a mat-checkbox correctly

I'm working on customizing the appearance of a mat-checkbox (material2) to meet the following specifications: Always display a black border (#000000), regardless of whether the checkbox is checked or not When the checkbox is checked, show a white ti ...

What is the best way to combine an Angular project with an existing Node.js project?

I've successfully deployed my Angular project on Heroku and my Node.js API REST on Heroku as well. However, they are separate projects with different URLs but function together. Is there a way to combine them on the server and have just one URL? Curr ...

The DiscordAPIError occurred due to the incorrect placement of required options in the form body. In order to resolve this issue, ensure that required

Hey everyone! So, I've been trying to solve an issue I encountered after posting my initial question without receiving any answers. I've searched extensively online, formatted the code, but unfortunately, I still haven't been able to find a ...

Display item upon hovering and for an extended period upon clicking using jQuery

I am looking to create a functionality where hovering over an area displays item 2 for a certain duration, which is currently working fine with the existing code. However, I also want it to remain visible for a longer period if clicked, but this does not ...

What is the method to ensure that flexbox takes into account padding when making calculations?

There are two sets of rows displayed below. The first row contains two items with a flex value of 1 and one item with a flex value of 2. The second row contains two items with a flex value of 1. As per the specification, 1A + 1B = 2A However, when ...

What is the best way to activate a function within an npm package in a Vue application?

I'm just starting out with Vuejs and I've recently installed the vue-countup-v2 npm package. I successfully imported it into my Vue component and noticed that it works perfectly when the page loads. However, I am interested in triggering the Coun ...

What is the best way to align the logo image in the center of the header vertically?

I am trying to vertically center my logo, but I have not been successful with using margin: auto or margin: center. Here is what I have tried so far: ・text-align: center; ・margin: auto; ・margin: center: ・navbar-brand-center The logo currently app ...