Move Elements Based on Viewport

Posted on Mar 06, 2026

by Jimmy


A performant way to move elements around based on screen size.

JavaScript
        
            export default function initMoveElements() {

    /**
     * Config format:
     *   element: string (selector for element to move),
     *   target: string (selector for where to move element),
     *   breakpoint: number (window width to trigger move),
     *   position: 'append' | 'prepend' (where to place element in target),
     *   restoreTarget: string (optional selector for where to move element back to when above breakpoint, defaults to original parent),
     *   restoreBefore: string (optional selector for element to insert before when restoring, defaults to appending to end of restoreTarget)
     */
    const moveConfigs = [
        {
            element: '.header__meta',
            target: '.mobile-navigation',
            breakpoint: 800,
            position: 'prepend',
            restoreTarget: '.header__navigation',
            restoreBefore: '.header__search-toggle',
        },
        {
            element: '.example',
            target: '.example-target',
            breakpoint: 800,
            position: 'append'
        }
    ];

    const responsiveMovers = moveConfigs
        .map((config) => createResponsiveMover(config))
        .filter(Boolean);

    if (!responsiveMovers.length) {
        return;
    }

    const applyAllMoves = () => {
        responsiveMovers.forEach((mover) => {
            mover.apply();
        });
    };

    if (window.__moveElementsResizeHandler) {
        window.removeEventListener('resize', window.__moveElementsResizeHandler);
    }

    let isTicking = false;

    window.__moveElementsResizeHandler = () => {
        if (isTicking) {
            return;
        }

        isTicking = true;
        window.requestAnimationFrame(() => {
            applyAllMoves();
            isTicking = false;
        });
    };

    window.addEventListener('resize', window.__moveElementsResizeHandler);
    applyAllMoves();
}

function createResponsiveMover({
    element,
    target,
    breakpoint,
    position = 'append',
    restoreTarget,
    restoreBefore,
}) {
    const movableElement = document.querySelector(element);
    const targetContainer = document.querySelector(target);

    if (!movableElement || !targetContainer) {
        return null;
    }

    const originalParent = restoreTarget
        ? document.querySelector(restoreTarget)
        : movableElement.parentElement;

    const originalNextSibling = restoreBefore
        ? document.querySelector(restoreBefore)
        : movableElement.nextElementSibling;

    if (!originalParent) {
        return null;
    }

    return {
        apply() {
            if (window.innerWidth <= breakpoint) {
                moveToTarget(movableElement, targetContainer, position);
                return;
            }

            restoreToOriginalPosition(movableElement, originalParent, originalNextSibling);
        },
    };
}

function moveToTarget(element, targetContainer, position) {
    if (targetContainer.contains(element)) {
        return;
    }

    if (position === 'prepend') {
        targetContainer.prepend(element);
        return;
    }

    targetContainer.appendChild(element);
}

function restoreToOriginalPosition(element, originalParent, originalNextSibling) {
    if (element.parentElement === originalParent) {
        return;
    }

    if (originalNextSibling && originalParent.contains(originalNextSibling)) {
        originalParent.insertBefore(element, originalNextSibling);
        return;
    }

    originalParent.appendChild(element);
}        
    

I know this code looks scary, but the only thing that needs to be edited is the moveConfigs array. Simply add the elements that need to move and you’re good to go. Save this in a moveElement.js file or something and don’t forget to include it in your main.js file and initiate it after the DOM is loaded.


Back to Snippets