Mihalma
Mihalma

Reputation: 101

How to move elements with Javascript

I am trying to move two elements on load with Javascript. My HTML looks like this:

<body>
    <div class="something">
        <nav class="navbar"></nav>
        <footer></footer>
    </div>
</body>

What am trying to achieve is HTML like this:

<body>
    <nav class="navbar"></nav>
    <div class="something"></div>
    <footer></footer>
</body>

Basically, the nav element below the opening body tag, and the footer at the end.

I did try something like this:

var a = document.getElementsByClassName("navbar");
document.body.appendChild(a);

Can anybody try to help me with this?

Upvotes: 1

Views: 6510

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074295

See comments:

// Get the `.something` element and its parent
const something = document.querySelector(".something");
const parent = something.parentElement;

// Get the `navbar` inside it and move it in front of it
const navbar = something.querySelector(".navbar");
parent.insertBefore(navbar, something);

// Get the `footer` inside it and insert it after it
const footer = something.querySelector("footer");
parent.insertBefore(footer, something.nextElementSibling);
<div class="something">
    <nav class="navbar"></nav>
    <footer></footer>
</div>

After that runs, if you right-click the output pane and look at the HTML, you'll see they're in the requested order (ignore the script that the snippet puts there).

If you have this repeated on a page, all you have to change is how you get the something elements to work on, using a loop:

for (const something of document.querySelectorAll(".something")) {
    // ...rest of the code goes here unchanged...
}

Note that that requires that the NodeList from querySelectorAll is iterable, which it is in modern environments. You can polyfill that for slightly older environments that support iteration but hadn't yet made NodeList iterable as I describe in this answer. For environments that don't support iterability, that link also shows how to polyfill forEach if NodeList doesn't have it, which you'd use like this:

document.querySelectorAll(".something").forEach(something => {
    // ...rest of the code goes here unchanged...
});

Upvotes: 2

Mark Baijens
Mark Baijens

Reputation: 13222

You can use inserBefore to do this. My answer is like T.J. Crowder answer but this will work if you have multiple instances of those elements by looping over all found instances.

document.querySelectorAll('.navbar').forEach((el) => {
  el.parentNode.parentNode.insertBefore(el, el.parentNode);
});

document.querySelectorAll('footer').forEach((el) => {
  el.parentNode.parentNode.insertBefore(el, el.parentNode.nextElementSibling);
});
<body>
    <div class="something">
        something
        <nav class="navbar">navbar</nav>
        <footer>footer</footer>
    </div>
    
    <div class="something">
        something2
        <nav class="navbar">navbar2</nav>
        <footer>footer2</footer>
    </div>
</body>

Upvotes: 0

Related Questions