Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

183
Visualizações
How do you add an annotation to a website without altering the layout?

I'm working on a hobby project similar to markup.io where you can load in any website and annotate it. I can't figure out how to add an annotation that behaves like it does in markup.io:

  • Doesn't interrupt the styling or layout of the website you are annotating
  • The annotation keeps the correct position when scrolling and resizing the window

From what I can see they place an absolute positioned div inside the element that you clicked on. From my understanding by reading the docs that div would position itself based on the closest positioned ancestor. How would you calculate the correct top and left values to position the annotation to where the user clicked? Is there a better way to do this?

I'm using React if that matters.

Things that I have tried:

  1. Append the following bit of html to the element that was clicked:
<div style="width:0px; height:0px; position:relative;">
<div style="width:50px;height:50px;position:absolute; ">this is the annotation </div> 
</div>

Problem: This would mess with the page layout because of the relative positioned div that is not ignored by the document flow.

  1. Create fixed overlay over the entire page. Get the css selector of the clicked element. Draw annotation on the fixed overlay at the x,y position of the element.

Problem: Whenever the user would scroll or resize the window the annotation would need to be redrawn at the new position of the element. I used getBoundintClientRect to get the new position and this would cause a reflow and caused the whole website to have severe perfomance issues when dealing with 100+ annotations.

Hopefully someone can point me in the right direction!

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

The general idea is as follows:

  1. Find the parent of the element that you clicked on
  2. Check if they are positioned (anything other than static)
  3. If it is static search for the closest element that is positioned.
  4. Set the new badge/annotation top and left position to that of the mouse minus the top and left of the element that you're going to append it to (in this case called parent).
  5. Also account for the width and height by subtracting half of each to perfectly center your annotation.
 // In my case I put the webpage in an Iframe. If this is your own page 
 // you can just use document.   
 iframe.contentWindow.document.addEventListener(
                'click',
                (e: MouseEvent) => {
// step 1: find the parent.
                  let parent = e.target.parentElement;
                  let computedStyle = window.getComputedStyle(parent);

// step 2 & 3: Look up the first positioned element and make this the
// the element that you're going to append your badge/annotation to.
                  while (
                    computedStyle.position === 'static' &&
                    parent.parentElement !== null
                  ) {
                    parent = parent.parentElement;
                    computedStyle = window.getComputedStyle(parent);
                  }

// style the annotation the way you want to
                  const badge = document.createElement('div');               

                  const { top, left } = parent.getBoundingClientRect();
                 
                  badge.style.position = 'absolute';

// step 4 and 5 get the mouse position through e.clientX and Y and 
// subtract the appropriate value like below to place it exactly at the mouse position
                  badge.style.top = `${e.clientY - top - 5}px`;
                  badge.style.left = `${e.clientX - left - 5}px`;

                  badge.style.backgroundColor = 'red';
                  badge.style.width = '10px';
                  badge.style.height = '10px';
                  badge.style.borderRadius = '50%';
                  badge.style.zIndex = '9999';
                  parent.appendChild(badge);
                }
              );
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda