diff --git a/css/frontend_editing.css b/css/frontend_editing.css
index f27f8add82c9734b58feebd51ea24fec2da7a6e3..ce063cdfc0c7d504eda1fa62dc5b0caf73cbf34a 100644
--- a/css/frontend_editing.css
+++ b/css/frontend_editing.css
@@ -154,6 +154,8 @@ body:not(.frontend-editing--hidden) .frontend-editing:has(.add-paragraphs.hover-
 
 .common-actions-container.place-fixed {
   position: fixed;
+  top: auto;
+  bottom: 10px;
 }
 
 .title-edit-container,
diff --git a/js/editing_actions.js b/js/editing_actions.js
index 1f746c9195dab12158f473c70bfdbacd24f7c074..cd1b10d368bb7b75a438aa081c6f1c19cb99acbc 100644
--- a/js/editing_actions.js
+++ b/js/editing_actions.js
@@ -1,38 +1,98 @@
-/**
- * @file
- * Keeps editing actions in viewport.
- */
 (function (Drupal) {
+  // Prevents the need to query the DOM multiple times
+  const actionsContainerMap = new Map();
 
-  const floatingLinks = function () {
-    const clientHeight = document.documentElement.clientHeight;
-    document.querySelectorAll(".frontend-editing").forEach((element) => {
-      const { top, bottom, left } = element.getBoundingClientRect()
-      const actions = element.querySelector('.common-actions-container')
+  const getActionsContainer = (element) => {
+    if (!actionsContainerMap.has(element)) {
+      const actions = element.querySelector('.common-actions-container');
+      actionsContainerMap.set(element, actions);
+    }
+    return actionsContainerMap.get(element);
+  };
+
+  const updatePositionReset = (element) => {
+    const actions = getActionsContainer(element);
+
+    actions.removeAttribute('style');
+    actions.classList.remove('place-bottom');
+    actions.classList.remove('place-fixed');
+  }
+
+  const updatePositionBottom = (element, rect) => {
+    const { bottom } = rect;
+
+    // Apply bottom position if element bottom is inside the viewport
+    if (bottom <= window.innerHeight && bottom >= 0) {
+      const actions = getActionsContainer(element);
+
+      updatePositionReset(element);
+      actions.classList.add('place-bottom');
+    }
+  }
 
-      // Reset
-      actions.removeAttribute('style');
-      actions.classList.remove('place-bottom');
-      actions.classList.remove('place-fixed');
+  const updatePositionFixed = (element, rect) => {
+    const { left, bottom, top } = rect;
 
-      // Top intersecting sections
-      if (top < 0 && bottom > 0 && bottom < clientHeight) {
-        actions.classList.add('place-bottom');
+    // Apply fixed position if element top and bottom are outside the viewport
+    if (top <= 0 && bottom >= window.innerHeight) {
+      const actions = getActionsContainer(element);
+
+      updatePositionReset(element);
+      actions.classList.add('place-fixed');
+      actions.style.left = left + 'px'; 
+    }
+  }
+
+  // Observer for the top of the element
+  const topObserver = new IntersectionObserver((entries) => {
+    entries.forEach(entry => {
+      const element = entry.target;
+      const rect = element.getBoundingClientRect();
+
+      if (entry.isIntersecting) {
+        // Top left viewport
+        updatePositionFixed(element, rect);
+      } else {
+        // Top entered viewport
+        updatePositionReset(element);
       }
+    });
+  }, {
+    root: null,
+    threshold: 0,
+    rootMargin: '0px 0px -100% 0px'
+  });
+
+  // Observer for the bottom of the element
+  const bottomObserver = new IntersectionObserver((entries) => {
+    entries.forEach(entry => {
+      const element = entry.target;
+      const rect = element.getBoundingClientRect();
 
-      // Top + bottom intersecting sections
-      if (top < 0 && bottom > clientHeight) {
-        actions.classList.add('place-fixed');
-        actions.style.top = clientHeight - actions.offsetHeight - 10 + 'px'
-        actions.style.left = left + 'px'
+      if (entry.isIntersecting) {
+        // Bottom left viewport
+        updatePositionFixed(element, rect);
+      } else {
+        // Bottom entered viewport
+        updatePositionBottom(element, rect);
       }
-    })
-  }
+    });
+  }, {
+    root: null,
+    threshold: 0,
+    rootMargin: '-100% 0px 0px 0px'
+  });
 
   Drupal.behaviors.editingActionsPosition = {
-    attach(context, settings) {
-      window.addEventListener('scroll', Drupal.debounce(floatingLinks, 250, false));
+    attach(context) {
+      context.querySelectorAll('.frontend-editing').forEach((element) => {
+        // Only observe if element is larger than the viewport
+        if (element.offsetHeight > window.innerHeight) {
+          topObserver.observe(element);
+          bottomObserver.observe(element);
+        }
+      });
     }
-  }
+  };
 
 })(Drupal);