Home > Software engineering >  Changing the order of a flex-container's child elements dynamically
Changing the order of a flex-container's child elements dynamically

Time:04-21

I have a navigation menu and some sections. Whenever a specific section is scrolled to, the corresponding navigation element is given the .active-class through a jQuery function I've made.

What I also want to do is "push" the active child-element of the navigation menu to the front of the menu, while "pushing" the last active element to the back of the menu. See pictures below for clarification:

What I have right now

enter image description here

What I want

As you can see, the item 2-element is the first element of the menu, while the item 1-element is the last element of the menu.

enter image description here

What I've tried

The container-element has the display: flex;-property, so naturally I tried using the order-properties on the different navigation elements in my function, but haven't had any success with it. If anyone has some tips on how to achieve this, I would be grateful as I quite frankly have no idea where to start.

Codepen: https://codepen.io/sigurdmazanti/pen/xxpBxNR

Snippet:

var nav = $(".container");
var sections = $(".section");

$(window).on("scroll", function() {
  var cur_pos = $(this).scrollTop();

  sections.each(function() {
    var top = $(this).offset().top,
      bottom = top   $(this).outerHeight();
    if (cur_pos >= top && cur_pos <= bottom) {
      nav.find(".nav").removeClass("active");
      nav.find("."   $(this)[0].id).addClass("active");
    }
  });
});
.container {
  display: flex;
  gap: 30px;
  position: sticky;
  justify-content: center;
  top: 0;
}

.container .nav {
  border: 1px solid black;
}

div.active {
  background-color: black;
  color: white;
}

.section {
  height: 350px;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
}

.section.one {
  background-color: yellow;
}

.section.two {
  background-color: red;
}

.section.three {
  background-color: green;
}

.section.four {
  background-color: blue;
}

.section.five {
  background-color: purple;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div >
  <div >item 1</div>
  <div >item 2</div>
  <div >item 3</div>
  <div >item 4</div>
  <div >item 5</div>
</div>

<div  id="one">item 1</div>
<div  id="two">item 2</div>
<div  id="three">item 3</div>
<div  id="four">item 4</div>
<div  id="five">item 5</div>

CodePudding user response:

This should work nicely for you:

.container > .nav.active {
  order: -1;
}

See it working here:

var nav = $(".container");
var sections = $(".section");

$(window).on("scroll", function() {
  var cur_pos = $(this).scrollTop();

  sections.each(function() {
    var top = $(this).offset().top,
      bottom = top   $(this).outerHeight();
    if (cur_pos >= top && cur_pos <= bottom) {
      nav.find(".nav").removeClass("active");
      nav.find("."   $(this)[0].id).addClass("active");
    }
  });
});
.container {
  display: flex;
  gap: 30px;
  position: sticky;
  justify-content: center;
  top: 0;
}

.container .nav {
  border: 1px solid black;
}

div.active {
  background-color: black;
  color: white;
}

.section {
  height: 350px;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
}

.section.one {
  background-color: yellow;
}

.section.two {
  background-color: red;
}

.section.three {
  background-color: green;
}

.section.four {
  background-color: blue;
}

.section.five {
  background-color: purple;
}

.container > .nav.active {
  order: -1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div >
  <div >item 1</div>
  <div >item 2</div>
  <div >item 3</div>
  <div >item 4</div>
  <div >item 5</div>
</div>

<div  id="one">item 1</div>
<div  id="two">item 2</div>
<div  id="three">item 3</div>
<div  id="four">item 4</div>
<div  id="five">item 5</div>

CodePudding user response:

On the phone now so hard to edit, but look at the ordering in css . Just change the order style in your script.

Its unclear if you want this to animate though.. a common trick is to copy thw full row and place it afterwards in a div with no overflow. Then on scrolling to the previous or next would quickly rest the bar to mimic endless scrolling..

var nav = $(".container");
var sections = $(".section");

$(window).on("scroll", function() {
  var cur_pos = $(this).scrollTop();

  sections.each(function() {
    var top = $(this).offset().top,
      bottom = top   $(this).outerHeight();
    if (cur_pos >= top && cur_pos <= bottom) {
      nav.find(".nav").removeClass("active");
      nav.find("."   $(this)[0].id).addClass("active");
    }
  });
});
.container {
  display: flex;
  gap: 30px;
  position: sticky;
  justify-content: center;
  top: 0;
}

.container .nav {
  border: 1px solid black;
}

div.active {
  background-color: black;
  color: white;
}

.section {
  height: 350px;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
}

.section.one {
  background-color: yellow;
}

.section.two {
  background-color: red;
}

.section.three {
  background-color: green;
}

.section.four {
  background-color: blue;
}

.section.five {
  background-color: purple;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div >
  <div style="order:3" >item 1</div>
  <div >item 2</div>
  <div style="order:1" >item 3</div>
  <div >item 4</div>
  <div >item 5</div>
</div>

<div  id="one">item 1</div>
<div  id="two">item 2</div>
<div  id="three">item 3</div>
<div  id="four">item 4</div>
<div  id="five">item 5</div>

  • Related