skip to Main Content

Context

I’m trying to get the offset left value (in pixels) of a multiline text div in display: inline

The problem

To achieve this i’m currently using the element.offsetLeft value. But this value give me the offsetLeft value of the first line of my multiline div. But what i want is the offsetleft value of the entire div. What i mean is that the first line can start at any left value based on where the previous inline div text ends.

The question

Is there any way to get that offsetLeft value ? (I can’t use boundingBoxes methodes because i’m not working in the window landmark i will not extend myself on why but consider that i can’t use boundingBoxes functions.).

Exemple

enter image description here

In this picture you can see a wrap div in grey which is in display: block. Classic. Then you can see two display: inline div containing the same text. Each can be differanciated because of the color of the text.

And the problem is that when i use element.offsetLeft on the "red div" i get the offset left of the first line that nearly start in the middle of the wrap div when i want the offsetLeft of the entire inline div which can be see on the second line of the red text (which is 0 in this exemple).

Thank for the time spent to answer and do not hesitate to ask for precisions even if the probleme is pretty straight forward.

Edit 1

So to give a bit more context. I’m working since 3 years on a new Ui UX Design software. That means that this software has a 2D view in which you can "move a virtual camera" managed with basic translate3D and scale transforms. Every elements can be rotated in its parent and i actually handle the exact coordinates of each element with DOMMatrix multiplications. So in fact the grey div i showed in my exemple can be 1 or 10 degres deep in the element arborescence or even more and the "root div" which can be the entry point of the "canva" can be scaled.

The transformation accumulation make it really complicated to use native boundingBoxes functions that why i said what i said (… " i can’t use boudingBoxes functions" ) and it also isn’t straight forward in a process where everything in calculated using DOMMatrix.

Everything really is complicated that why my question is that simple. The probleme exactly is what i ask for, no need to more context because an answer to "how to get the left offset value of an inline div containing multiline string in a display:block div" as all i need.

2

Answers


  1. offsetLeft is relative to the first positioned (not static) ancestor container.

    you can create an invisible dummy element that is added to the document at the same hierarchical level as your multiline text. You would ensure that this element has the same styles applied as your text container (except for text content, of course), and then measure its offsetLeft to get the position of the multiline container relative to its positioned ancestor.

    <style>
      .wrapper {
        display: block;
        background-color: #eee; 
        padding: 10px;
        width: 300px;
        font-size: 16px;
        font-family: Arial, sans-serif;
      }
      
      .inline-text {
        display: inline;
        color: #000;
      }
    
      .inline-text.red {
        display: inline;
        color: #f00;
      }
      
      .dummy {
        visibility: hidden;
        display: inline;
      }
    </style>
    </head>
    <body>
    
    <div class="wrapper">
      <div id="normal-text" class="inline-text">
        Text qui peut varier mais c'est juste un test en fait voila.
      </div>
      <div id="red-text" class="inline-text red">
        Text qui peut varier mais c'est juste un test en fait voila.
      </div>
    </div>
    
    <script>
      function calculateOffsetLeft(element) {
        var dummyElement = document.createElement('div');
        dummyElement.classList.add('dummy');
        
        element.parentNode.insertBefore(dummyElement, element);
        
        var offsetLeftValue = dummyElement.offsetLeft;
        dummyElement.parentNode.removeChild(dummyElement);
        
        return offsetLeftValue;
      }
    
      window.onload = function() {
        var normalTextElement = document.getElementById('normal-text');
        var redTextElement = document.getElementById('red-text');
    
        var normalOffsetLeft = calculateOffsetLeft(normalTextElement);
        var redOffsetLeft = calculateOffsetLeft(redTextElement);
    
        console.log('Normal Text Offset Left:', normalOffsetLeft);
        console.log('Red Text Offset Left:', redOffsetLeft);
        
        // Display the offsetLeft values on the page for demonstration purposes.
        var normalResultDiv = document.createElement('div');
        var redResultDiv = document.createElement('div');
        
        normalResultDiv.textContent = 'Normal Text Offset Left: ' + normalOffsetLeft + 'px';
        redResultDiv.textContent = 'Red Text Offset Left: ' + redOffsetLeft + 'px';
        
        document.body.appendChild(normalResultDiv);
        document.body.appendChild(redResultDiv);
      };
    </script>
    
    </body>
    </html>
    Login or Signup to reply.
  2. You are looking to get the offset of the bounding rectangle of the element. You can access it via the getBoundingClientRect method, however that is relative to the viewport not to the offsetParent element like offsetLeft. You can however simply subtract their respective .left values, and also take int account scroll offsets, to get the desired value:

    function boundingOffsetLeft(element) {
      const {
        offsetParent
      } = element;
      let offset = element.getBoundingClientRect().left;
      if (offsetParent) {
        offset -= offsetParent.getBoundingClientRect().left;
      }
      while (element = element.parentElement) {
        offset += element.scrollLeft;
        if (element === offsetParent) break;
      }
      return offset;
    }
    
    const normalText = document.getElementById('normal');
    const redText = document.getElementById('red');
    const scrollArea = document.getElementById('scroll');
    
    const normalResult = document.body.appendChild(document.createElement('p'));
    const redResult = document.body.appendChild(document.createElement('div'));
    
    scrollArea.onscroll = () => {
      normalResult.textContent = `Normal: ${boundingOffsetLeft(normalText)}px`;
      redResult.textContent = `Red: ${boundingOffsetLeft(redText)}px`;
    };
    scrollArea.onscroll();
    #scroll {
      margin: 2em;
      padding: 2em;
      background: #aaa;
      width: 200px;
      overflow-x: scroll;
    }
    
    .wrapper {
      display: block;
      background-color: #eee;
      padding: 10px;
      width: 300px;
      font-size: 16px;
    }
    
    #red {
      color: #f00;
    }
    <div id="scroll">
      <div class="outer">
        <div class="wrapper">
          <span id="normal">Text qui peut varier mais c'est juste un test en fait voila.</span>
          <span id="red">Text qui peut varier mais c'est juste un test en fait voila.</span>
        </div>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search