What is the best way to incorporate annotations onto a website without impacting the overall design and layout?

I'm currently working on a personal project that is similar to markup.io where users can load any website and add annotations. I am struggling to implement an annotation feature that functions like the one in markup.io:

  • Does not disrupt the styling or layout of the annotated website
  • Maintains its correct position when scrolling or resizing the window

Based on my observations, it seems like they insert an absolutely positioned div inside the clicked element. According to what I have read in the documentation, that div would align itself according to the nearest positioned ancestor. How can one accurately calculate the top and left values to position the annotation where the user clicks? Is there a more efficient method to achieve this?

I am using React for this project.

Methods I've attempted:

  1. Appended the following snippet of HTML to the clicked element:
<div style="width:0px; height:0px; position:relative;">
<div style="width:50px;height:50px;position:absolute; ">this is the annotation </div> 
</div>

Issue: This disrupted the page layout due to the relatively positioned div affecting the document flow.

  1. Created a fixed overlay covering the entire page, obtained the CSS selector of the clicked element, and drew the annotation on the overlay at the x,y coordinates of the element.

Issue: Whenever the user scrolled or resized the window, the annotation had to be redrawn based on the new position of the element. This caused performance problems with 100+ annotations as getBoundingClientRect was used to fetch the new position, leading to reflows and impacting the website's overall performance.

I hope someone can offer guidance on how to overcome these obstacles!

Answer №1

Here's the main concept:

  1. Determine the parent of the clicked element
  2. Check if the parent is positioned (not static)
  3. If the parent is static, find the closest positioned element
  4. Set the new badge/annotation position relative to the mouse and parent element
  5. Adjust for width and height to center the annotation perfectly
// If using an iframe, access the content with iframe.contentWindow.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: Locate the nearest positioned element as the target append location
                  while (
                    computedStyle.position === 'static' &&
                    parent.parentElement !== null
                  ) {
                    parent = parent.parentElement;
                    computedStyle = window.getComputedStyle(parent);
                  }

                  // Customize the annotation style
                  const badge = document.createElement('div');

                  const { top, left } = parent.getBoundingClientRect();

                  badge.style.position = 'absolute';

                  // Set badge position based on mouse coordinates
                  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);
                }
              );

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

Javascript function encountering difficulty accessing the 'this' variable

I am embarking on a new HTML5 game project, my very first one. Right now, I am working on creating a function that holds variables. While I cannot recall its exact name, I remember the process from a tutorial. In my attempt to set up some of these variable ...

I want to create a form with two dropdown menus placed side by side within a parent DIV, and I want them to collectively occupy the entire width using Bootstrap

Currently, I am working on a search form using Bootstrap. Everything is going well, but I am facing an issue where two multi-option elements need to be placed side by side and together occupy 100% of the width within their containing DIV. Just for clarity ...

The alignment of the Unicode character is off and is not centered within the button

Upon implementing a unicode character as a button, I've observed that the alignment of the character is not centered properly (both horizontally and vertically) within the button. It's puzzling why this misalignment occurs even after setting padd ...

Customize WordPress zerif-lite theme with CSS to decrease page width temporarily

Is there a way to decrease the width of a specific page on my website without modifying the current theme that I am using (zerif-lite)? I want to accomplish this task by adding custom CSS to styles.css. However, I am facing difficulties as I only want to a ...

When attempting to render HTML containing multiple CSS classes within a JSON request parameter, the styles are not being applied as expected

In my API, I'm dealing with a JSON request parameter that includes an HTML string. This HTML string references CSS styles from a separate .css file. However, when an HTML element has two CSS classes assigned to it, neither of the classes' styles ...

responding to a forum comment in jquery by either replying or quoting

I'm attempting to develop a forum "quote" feature, similar to reply options on many forums. However, I am struggling with selecting the appropriate items from my comment and dealing with dynamically generated IDs. Here is the HTML of my comment: & ...

What is the best way to extract the value from a React date picker every time the dates are modified?

Currently, I am utilizing a React library known as react-date-picker and my goal is to retrieve the date every time it is modified. Below is the default code given by the library for selecting the date from a dropdown: import React, { Component } from "r ...

Unable to update the color of material icon using document.getElementById(item) method

if (document.getElementById(item).style.color == "grey") { document.getElementById(item).style.color = "red"; } <i class="material-icons" [ngStyle]="post.isLiked != null ? {'color': 'red'}: {'color': 'grey'}" id ...

How to pass parameters while updating parent values in VueJS using emit?

Explaining my dilemma with uploading images: In my form, users can upload images using the following code snippet: <input id="visualisation_upload" @change="onThumbnailChanged" name="visualisation_upload" accept="imag ...

Issue with using async await in map function: async function may not complete before moving on to the next item in the

Currently, I have an array that needs to be mapped. Inside the mapping function, there is an asynchronous function being called, which conducts an asynchronous request and returns a promise using request-promise. My intention was for the first item in the ...

Sliding content with the grace of a visual journey

I'm currently working on a content slider that is very similar to this one. My goal is to make it rotate automatically, but I've been struggling to get it to work. I've attempted various methods, including triggering a click event on the lin ...

What is the best way to access the rendered child components within a parent component?

I am seeking a way to retrieve only the visible child components within a parent component. Below is my unsuccessful pseudo-code attempt: parent.component.html <parent (click)="changeVisibility()"> <child *ngIf="visible1"></child> ...

What is the method for sending XML data without labels in the POST body using an HTML form?

Here is the current request model I am using with AJAX XMLHTTP: POST someURL/someURL/someURL HTTP/1.1 Host: xxx.yyy.com Connection: close Content-Length: 221 Origin: https://xxx.yyy.com X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (X11; Linu ...

Having trouble passing an object with useHistory() in a React.JS application?

I've been attempting to pass an object as an argument using useHistory(), but for some reason, it doesn't seem to be working. The goal is to click on one of the boxes as shown in the screenshot below, which should then display the corresponding r ...

How can you create a sticky navigation bar specifically designed for horizontal scrolling on a website?

I am facing a challenge with a large table that extends beyond the screen, requiring both horizontal and vertical scrolling. My goal is to create a sticky navbar that remains at the top when I scroll horizontally, but hides when I scroll vertically, only t ...

Incorporate dynamic rules into a CSS stylesheet

I am trying to dynamically add a rule to my CSS for each element. Each rule should have a different background-image and name. However, I seem to be encountering an issue where the dynamically added div is not linking to the dynamically added CSS rule. I&a ...

Develop a custom WordPress meta box for managing the color scheme of individual posts and pages

Currently, I am in the process of learning how to create a custom WordPress meta box with a select tag for controlling the color scheme of individual posts/pages. My goal is to implement a system where I can use if statements to load an additional CSS file ...

Modify th:hover in CSS to alter the background color

I currently have a table structured as follows: <table class="cedvel"> <caption> count: <%:Html.Encode(TempData["RowsCount"])%></caption> <thead> <tr&g ...

Moving the legend around in vue-chartJS

As someone just starting out with Vue-ChartJs, I've become quite intrigued by this: https://i.sstatic.net/j1S0z.png I'm wondering how to move the legend to the bottom of the graph. Can anyone help me with that? ...

Issues with Persistent Navbar Stickiness

I'm encountering an issue with the sticky navbar on my website. I implemented the code for this navbar from a tutorial at w3schools. However, the problem is that the sticky effect on the navigation menu doesn't seem to work correctly. The menu j ...