diff --git a/css/builder.css b/css/builder.css
index 9b5ef3fe4236a95de03deb9484d157dec5fe9d06..f6d0260066fa702abc2fed43fe7e9ec0a0d049d4 100644
--- a/css/builder.css
+++ b/css/builder.css
@@ -12,7 +12,7 @@
   --lp-btn-bg-color: #0550E6;
   --lp-btn-fg-color: #fff;
 
-  --lp-controls-sticky-top: 170px;
+  --lp-controls-sticky-top: 70px;
 }
 
 .lp-builder {
@@ -111,15 +111,13 @@
   border: 1px dotted #ccc;
   font-size: small;
 }
-.lpb-controls__wrapper {
-  position: absolute;
-}
 .lpb-controls {
-  position: sticky;
+  position: absolute;
   z-index: 80;
-  top: var(--lp-controls-sticky-top);
+  top: 0;
   margin: 0 auto;
-  transform: translateY(calc(-100% - 15px));
+  left: 50%;
+  transform: translate(-50%, calc(-100% - 15px));
   display: flex;
   padding: 2px 2px 2px 15px;
   opacity: 0;
@@ -134,6 +132,15 @@
     letter-spacing: 2px;
     font-weight: bold;
   }
+  &.is-fixed {
+    position: fixed;
+    top: var(--lp-controls-sticky-top);
+    left: var(--lp-controls-sticky-left, 50%);
+    transform: translate(-50%, 0);
+  }
+  &.is-scrolled-past {
+    opacity: 0 !important;
+  }
 }
 .lpb-controls:hover,
 .lpb-controls:focus-within {
diff --git a/js/builder.js b/js/builder.js
index 8e01e2b5c20a5630698ad188551e2239677f7a37..9a9c0ac089f437e00379e0a1e29f3c2cc67e5f53 100644
--- a/js/builder.js
+++ b/js/builder.js
@@ -1,6 +1,9 @@
 (($, Drupal, drupalSettings, debounce, Sortable, once) => {
   const idAttr = 'data-lpb-id';
 
+  // The current active component, or NULL.
+  let activeComponent = null;
+
   /**
    * Helper function to select all elements matching a selector.
    *
@@ -72,6 +75,50 @@
     });
   }
 
+  /**
+   * Sets position for the active component's controls.
+   */
+  const setControlsPosition = debounce(() => {
+    if (!activeComponent) {
+      return;
+    }
+    const controls = select('.lpb-controls', activeComponent);
+    const componentRect = activeComponent.getBoundingClientRect();
+    const controlsRect = controls.getBoundingClientRect();
+    const controlsLeft = componentRect.left + componentRect.width / 2;
+    activeComponent.style.setProperty(
+      '--lp-controls-sticky-left',
+      `${controlsLeft}px`,
+    );
+    if (!controls.getAttribute('data-offset-y')) {
+      controls.setAttribute(
+        'data-offset-y',
+        componentRect.top - controlsRect.top,
+      );
+      controls.setAttribute(
+        'data-threshold-y',
+        parseInt(
+          getComputedStyle(controls).getPropertyValue(
+            '--lp-controls-sticky-top',
+          ),
+          10,
+        ),
+      );
+    }
+    const offsetY = parseInt(controls.getAttribute('data-offset-y'), 10);
+    const top = componentRect.top - offsetY;
+    if (top < controls.getAttribute('data-threshold-y')) {
+      controls.classList.add('is-fixed');
+    } else {
+      controls.classList.remove('is-fixed');
+    }
+    if (controlsRect.bottom + offsetY > componentRect.bottom) {
+      controls.classList.add('is-scrolled-past');
+    } else {
+      controls.classList.remove('is-scrolled-past');
+    }
+  }, 25);
+
   /**
    * Removes focus data attributes from all components.
    */
@@ -85,6 +132,7 @@
     selectAll('.is-navigating').forEach((element) =>
       element.classList.remove('is-navigating'),
     );
+    activeComponent = null;
     setUiElementVisibility();
   }
 
@@ -94,11 +142,13 @@
    * @param {HTMLElement} element The component to focus.
    */
   function selectComponent(element) {
+    activeComponent = element;
     select('.lpb-hover-label')?.remove();
     // Add the data-active attribute to the element.
     element.setAttribute('data-active', 'true');
     element.setAttribute('data-active-within', 'true');
     setUiElementVisibility();
+    setControlsPosition();
     // Add the data-active-within attribute to all parent elements.
     let parent = element.parentNode.closest('.js-lpb-component');
     while (parent) {
@@ -134,7 +184,7 @@
     // Add hover to the element.
     if (element && !element.getAttribute('data-active')) {
       element.setAttribute('data-hover', 'true');
-      const hoverLabel = select('.lpb-controls-label')?.textContent;
+      const hoverLabel = select('.lpb-controls-label', element)?.textContent;
       if (hoverLabel) {
         const hoverLabelElement =
           select('.lpb-hover-label') ||
@@ -861,6 +911,11 @@
    */
   listen(window, 'scroll', () => {
     document.querySelector('.lpb-hover-label')?.remove();
+    setControlsPosition();
+  });
+
+  listen(window, 'resize', () => {
+    setControlsPosition();
   });
 
   /**