Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Side content at the same Y position, but stackable

I would like to create a sidebar with comments to the main text like in Google Docs.

enter image description here

I would like the comments to be at the same Y position as text, BUT if text is too long, or there are multiple comments they should not overlap but stack one under the other.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

The best I could come up with is this:

<html>
<head>
<style>
p { max-width: 400px; position: relative; }
span { background: yellow; }
span::before {
  content: attr(data-text);
  display: block;
  position: absolute;
  left: 420px;
  width: 200px;
}
</style>
</head>
<body>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sagittis metus sit amet purus dapibus iaculis. Aenean facilisis malesuada orci, tincidunt bibendum erat. <span id="c1" data-text="Etiam commodo, purus eget gravida faucibus, ipsum mi maximus magna, eu tincidunt arcu arcu nec elit">Proin vel nisl lacinia, facilisis velit cursus, eleifend turpis. Phasellus ac imperdiet erat.</span> Donec egestas aliquam augue a mattis. <span id="c2" data-text="Cras ut nunc ac nunc pharetra gravida. Morbi pulvinar blandit justo id interdum. Sed risus orci, posuere id semper tempor, dignissim non turpis.">Pellentesque congue nunc vel scelerisque eleifend.</span> Fusce orci odio, ultricies posuere mi ac, elementum blandit dolor. Praesent non velit bibendum est feugiat egestas et nec urna. Etiam volutpat eu massa sed porttitor. Aliquam et pulvinar metus. Maecenas nec enim felis.</p>

<p>Ut mattis eros vitae risus scelerisque ornare ac tincidunt nibh. Suspendisse vitae ipsum porttitor, interdum nisl ut, sagittis arcu. In pretium, nulla vitae tincidunt vestibulum, odio neque convallis lacus, sit amet auctor leo tortor non nunc. Curabitur in dui at lorem mollis malesuada eget eget velit. <span id="c3" data-text="Ut ut viverra nisi. Integer imperdiet at nibh at bibendum. Etiam commodo, purus eget gravida faucibus, ipsum mi maximus magna.">Etiam vel neque vitae enim semper consequat</span> lacinia id urna. Nulla commodo tellus et nunc commodo, et vulputate nunc auctor. Curabitur nec gravida risus. Aliquam neque nulla, faucibus non ante sed, pharetra euismod purus. Pellentesque molestie ante in sapien varius facilisis. Fusce nec cursus diam.</p>

<p>Ut ut viverra nisi. Integer imperdiet at nibh at bibendum. Etiam commodo, purus eget gravida faucibus, ipsum mi maximus magna, eu tincidunt arcu arcu nec elit. Quisque ligula nibh, imperdiet hendrerit laoreet et, rhoncus vitae libero. Ut ornare leo sed nisl eleifend pretium non nec arcu. Aenean quis sollicitudin arcu, ac fermentum sem. Proin vitae velit a est ornare vestibulum. Vivamus finibus dui aliquam, ultricies quam eget, egestas eros. Cras ut nunc ac nunc pharetra gravida. Morbi pulvinar blandit justo id interdum. Sed risus orci, posuere id semper tempor, dignissim non turpis.</p>
</body>
</html>

which overlaps, and also this way it’s impossible to add extra elements to the sidebar content like user name or avatar so I’m looking for a better solution

>Solution :

You can use CSS Grid or Flexbox along with JavaScript to dynamically calculate the positions. The main element contains the text, and the comment-sidebar div contains the comments. Comments are absolutely positioned within the sidebar based on the Y position of the linked text. The script dynamically positions the comments according to the Y position of the highlighted text. Comments automatically stack below each other within the sidebar.

document.addEventListener("DOMContentLoaded", function() {
  const comments = document.querySelectorAll('.comment');
  let lastBottom = 0; // Keeps track of the bottom position of the last comment

  comments.forEach(comment => {
    const linkedId = comment.getAttribute('data-linked');
    const linkedElement = document.getElementById(linkedId);

    if (linkedElement) {
      const rect = linkedElement.getBoundingClientRect();
      let topPosition = rect.top + window.scrollY;

      // Ensure the current comment does not overlap with the previous one
      if (topPosition < lastBottom + 10) { // 10px gap between comments
        topPosition = lastBottom + 10;
      }

      comment.style.position = 'absolute';
      comment.style.top = `${topPosition}px`;

      // Update lastBottom to the bottom of the current comment
      lastBottom = topPosition + comment.offsetHeight;
    }
  });
});
body {
  display: flex;
}

main {
  max-width: 400px;
  position: relative;
  padding-right: 220px; /* Space for sidebar */
}

.comment-sidebar {
  width: 200px;
  position: absolute;
  left: 420px;
  top: 0;
}

.comment {
  background: #f0f0f0;
  border: 1px solid #ccc;
  margin-bottom: 10px;
  padding: 10px;
  border-radius: 5px;
}

.comment .author {
  font-weight: bold;
  margin-bottom: 5px;
}

.comment .text {
  font-size: 0.9em;
}

.highlight {
  background: yellow;
  position: relative;
}
<body>
<main>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sagittis metus sit amet purus dapibus iaculis. Aenean facilisis malesuada orci, tincidunt bibendum erat. <span id="c1" class="highlight">Proin vel nisl lacinia, facilisis velit cursus, eleifend turpis. Phasellus ac imperdiet erat.</span> Donec egestas aliquam augue a mattis. <span id="c2" class="highlight">Pellentesque congue nunc vel scelerisque eleifend.</span> Fusce orci odio, ultricies posuere mi ac, elementum blandit dolor. Praesent non velit bibendum est feugiat egestas et nec urna. Etiam volutpat eu massa sed porttitor. Aliquam et pulvinar metus. Maecenas nec enim felis.</p>

  <p>Ut mattis eros vitae risus scelerisque ornare ac tincidunt nibh. Suspendisse vitae ipsum porttitor, interdum nisl ut, sagittis arcu. In pretium, nulla vitae tincidunt vestibulum, odio neque convallis lacus, sit amet auctor leo tortor non nunc. Curabitur in dui at lorem mollis malesuada eget eget velit. <span id="c3" class="highlight">Etiam vel neque vitae enim semper consequat</span> lacinia id urna. Nulla commodo tellus et nunc commodo, et vulputate nunc auctor. Curabitur nec gravida risus. Aliquam neque nulla, faucibus non ante sed, pharetra euismod purus. Pellentesque molestie ante in sapien varius facilisis. Fusce nec cursus diam.</p>

  <p>Ut ut viverra nisi. Integer imperdiet at nibh at bibendum. Etiam commodo, purus eget gravida faucibus, ipsum mi maximus magna, eu tincidunt arcu arcu nec elit. Quisque ligula nibh, imperdiet hendrerit laoreet et, rhoncus vitae libero. Ut ornare leo sed nisl eleifend pretium non nec arcu. Aenean quis sollicitudin arcu, ac fermentum sem. Proin vitae velit a est ornare vestibulum. Vivamus finibus dui aliquam, ultricies quam eget, egestas eros. Cras ut nunc ac nunc pharetra gravida. Morbi pulvinar blandit justo id interdum. Sed risus orci, posuere id semper tempor, dignissim non turpis.</p>
</main>

<div class="comment-sidebar">
  <div class="comment" data-linked="c1">
    <div class="author">User 1</div>
    <div class="text">Etiam commodo, purus eget gravida faucibus, ipsum mi maximus magna, eu tincidunt arcu arcu nec elit</div>
  </div>
  <div class="comment" data-linked="c2">
    <div class="author">User 2</div>
    <div class="text">Cras ut nunc ac nunc pharetra gravida. Morbi pulvinar blandit justo id interdum. Sed risus orci, posuere id semper tempor, dignissim non turpis.</div>
  </div>
  <div class="comment" data-linked="c3">
    <div class="author">User 3</div>
    <div class="text">Ut ut viverra nisi. Integer imperdiet at nibh at bibendum.</div>
  </div>
</div>
</body>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading