Search code examples
javascripthtmlgetboundingclientrect

JavaScript: Position DIV Centered Above Text Selection?


I am trying to position a <div> above a users text selection that will act as a toolbar similar to Mediums.

enter image description here

While I have successfully gotten the <div> to be positioned next to the selection, I cannot seem to get it to correctly center relative to the selection:

    $(function() {
      // Setup the Event Listener
      $('.article').on('mouseup', function() {
        // Selection Related Variables
        let selection = window.getSelection(),
        getRange      = selection.getRangeAt(0),
        selectionRect = getRange.getBoundingClientRect();

        // Set the Toolbar Position
        $('.toolbar').css({
          top: selectionRect.top - 42 + 'px',
          left: selectionRect.left + 'px'
        });
      });
    });

I can determine the selection's center point by subtracting the selections left offset from the viewport by its width as such:

 selectionRect.left - selectionRect.width

However, I am not sure how to use that to set the position of my toolbar to be centered relative to the selection rectangle?

I tried subtracting the toolbars left offset from the width of the selection divided by 2 but that doesn't align to the center perfectly either.

JSFiddle

https://jsfiddle.net/e64jLd0o/


Solution

  • One solution would be to add the following to your CSS:

    .toolbar {
      transform: translateX(-50%);
    }
    

    and update your script to offset the left position of the toolbar element like so:

    $('.toolbar').css({
      top: selectionRect.top - 42 + 'px',
      left: ( selectionRect.left + (selectionRect.width * 0.5)) + 'px'
    });
    

    Here is a working snippet:

    $(function() {
      // Setup the Event Listener
      $('.article').on('mouseup', function() {
        // Selection Related Variables
        let selection = window.getSelection(),
        getRange      = selection.getRangeAt(0),
        selectionRect = getRange.getBoundingClientRect();
         
    
        // Set the Toolbar Position
        $('.toolbar').css({
          top: selectionRect.top - 42 + 'px',
          left: ( selectionRect.left + (selectionRect.width * 0.5)) + 'px'
        });
      });
    });
    .article {
      position: relative;
      height: 300px;
      padding: 20px;
    }
    
    .toolbar {
      position: absolute;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 169px;
      padding-top: 10px;
      padding-bottom: 10px;
      background: black;
      text-align: center;
      color: white;
      border-radius: 8px;
      
      transform: translateX(-50%);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
    <!-- Editor -->
    <div class="article">
      <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tenetur dignissimos facilis id repellat sint deserunt voluptates animi eaque tempore debitis, perferendis repudiandae voluptatem. Eligendi fuga deleniti saepe quod eum voluptas.</p>
    </div>
    
    <!-- Toolbar -->
    <div class="toolbar">Toolbar</div>