skip to Main Content

After reordering dynamically the elements of a flexbox, is it possible to target the first and last displayed elements?

I’m reordering some elements in the flexbox based on a dynamically provided class. So there are .item-s .item.to-back-s. I want to turn off the right border for the last .item that is not a .item.to-back and also for the last .item.to-back.

How may I approach this?

Minimal Reproducible Example:

.flex{
 display: flex;
}

.item {
  border: 1px solid grey;
  padding: 0.25em;
}


.to-back {
  order: 2;
}
<div class="flex">
 <div class="item">1</div>
 <div class="item">2</div>
 <div class="item to-back">3</div>
 <div class="item">4</div>
 <div class="item to-back">5</div>
 <div class="item">6</div>
<div>

I tried:

.item:not(.to-back):first-child {
  border-right: none;
}

2

Answers


  1. If your elements are static you can add a class to each one: item-1, item-2, .., item-n. If your elements are dynamically created you can add the class as they are being created.

    Making sure that the class name has the same prefix every time and is unique to the elements that are being reordered, you can utilize the querySelectorAll method to select them, based on their prefix. For example:

    const elements = document.querySelectorAll(`[class^="item-"]`);
    

    The above selector allows you to select all the elements the class of which starts with the string "item-". Once the elements have been selected, if they are being dynamically created, you can define a new variable to extract the number of elements contained within the selector, the value of which is practically the last element you are looking for. For example:

    const lastElement = elements.length;
    

    Then you can iterate through the elements that were returned by the selector and target the first and last element. For example:

    elements.forEach(element => {
      if (element.classList.contains("item-1") ||
        element.classList.contains(`item-${lastElement}`)) {
        // do something with the first or last element
        console.log(element);
      }
    });
    

    Alternatively, you can directly iterate through your selector’s elements using only the loop’s index:

    elements.forEach((element, index) => {
      if (index === 0 || index === elements.length - 1) {
        // do something with the first or last element
        console.log(element);
      }
    });
    

    Either way would work. Finding a way to query the DOM for the elements that are being reordered, then iterating through the list to target the desired elements will most likely do what you are after. Let me know.

    UPDATE: Based on what you shared, I am updating the iteration in the lines below to help you get what you are after.

    // assuming the item className is unique to those elements only
    const elements = document.querySelectorAll(".item");
    
    elements.forEach((element, index) => {
      // the following statement checks for both the first and last elements
      if (index === 0 || index === elements.length - 1) {
        // the following statement only targets the elements that do not contain the .to-back class
        if (!element.classList.contains(".to-back")) {
          element.style.borderRight = "none;";
        }
    
        // the following statement only targets the elements that contain the .to-back class
        if (element.classList.contains(".to-back")) {
          element.style.borderRight = "none;";
        }
      }
    });
    

    You can alter the initial if statement within the forEach loop to individually check for the first and last elements by breaking the statement into two separate statements. I can see that someone already posted an answer utilizing css rules. That would also work.

    Login or Signup to reply.
  2. You can now do this with nth-child(n of x) selector

    .item {
      height: 50px;
      width: 50px;
      border: 5px solid lightblue;
      background: green;
    }
    
    .wrap {
      display: flex;
      gap: .5em;
    }
    
    
    /* re-order to end */
    
    .to-back {
      background: gold;
      order: 2;
    }
    
    
    /* last item with second class */
    
    :nth-last-child(1 of .to-back) {
      border-right-color: red;
    }
    
    
    /* last item without second class*/
    
    .item:nth-last-child(1 of :not(.to-back)) {
      background: #000;
    }
    <div class="wrap">
      <div class="item"></div>
      <div class="item to-back"></div>
      <div class="item to-back"></div>
      <div class="item to-back"></div>
      <div class="item"></div>
      <div class="item"></div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search