Eliminate the empty spaces from concealed objects in a grid

I have been working on creating a catalog for a website that showcases different items in a grid layout. Currently, I have implemented a function that allows users to hide specific items by clicking an image. However, when an item is hidden, the remaining visible items do not automatically reposition themselves within the grid.

For example, if I initially have 6 items spread over 2 rows and 3 columns as follows:

1 2 3
4 5 6

And then proceed to hide numbers divisible by 2, the grid will look like this:

1   3
  5

Is there a way to make the grid rearrange itself like this instead?

1 3 5

In my current implementation, I am using display = 'none' to hide the items.

Below is a simplified version of the code I am working with:

var ChangeLayout = function(rarity) {
  var listItemContainers = document.getElementsByClassName("itemContainer");
  var listItemContainersByRarity = document.getElementsByClassName(rarity);
  var j;
  var h;

  if (rarity == 'all') {
    for (j = 0; j < listItemContainers.length; j++) {
      document.getElementsByClassName("itemContainer")[j].style.display = 'block';
    }
  } else {
    for (j = 0; j < listItemContainers.length; j++) {
      document.getElementsByClassName("itemContainer")[j].style.display = 'none';
    }
    for (h = 0; h < listItemContainersByRarity.length; h++) {
      document.getElementsByClassName(rarity)[h].style.display = 'block';
    }
  }
}
#catalogGrid {
  display: grid;
  grid-auto-flow: row;
  grid-template-columns: repeat(3, 1fr);
  grid-column-gap: 5px;
  grid-row-gap: 5px;
}
<img id="gemStoneAll" onclick="ChangeLayout('all')" />
<img id="gemStoneUncommon" onclick="ChangeLayout('uncommon')" />
<img id="gemStoneRare" onclick="ChangeLayout('rare')" />
<img id="gemStoneVeryRare" onclick="ChangeLayout('veryrare')" />
<ul id=catalogGrid>
  <li>
    <div class="itemContainer rare">
    </div>
  </li>
  <li>
    <div class="itemContainer veryrare">
    </div>
  </li>
  <li>
    <div class="itemContainer uncommon">
    </div>
  </li>
  <li>
    <div class="itemContainer uncommon">
    </div>
  </li>
  <li>
    <div class="itemContainer rare">
    </div>
  </li>
  <li>
    <div class="itemContainer rare">
    </div>
  </li>
</ul>

View on JSFiddle

Answer №1

One way to resolve the issue of <li> elements not being shown or hidden is by applying classes to their parent <li> elements instead of their child <div> elements.

For a better solution, consider using the CSS display property value of list-item instead of block.

var ChangeLayout = function(rarity) {

  var listItemContainers = document.getElementsByClassName("itemContainer");
  var listItemContainersByRarity = document.getElementsByClassName(rarity);

  if (rarity == 'all') {
    for (var j = 0; j < listItemContainers.length; j++) {
      listItemContainers[j].style.display = 'list-item';
    }
  } else {
    for (var j = 0; j < listItemContainers.length; j++) {
      listItemContainers[j].style.display = 'none';
    }
    for (var h = 0; h < listItemContainersByRarity.length; h++) {
      listItemContainersByRarity[h].style.display = 'list-item';
    }
  }
}
#catalogGrid {
  display: grid;
  grid-auto-flow: row;
  grid-template-columns: repeat(3, 1fr);
  grid-column-gap: 5px;
  grid-row-gap: 5px;
}
<img id="gemStoneAll" src="https://picsum.photos/id/10/50/50" onclick="ChangeLayout('all')" />
<img id="gemStoneUncommon" src="https://picsum.photos/id/30/50/50" onclick="ChangeLayout('uncommon')" />
<img id="gemStoneRare" src="https://picsum.photos/id/40/50/50" onclick="ChangeLayout('rare')" />
<img id="gemStoneVeryRare" src="https://picsum.photos/id/50/50/50" onclick="ChangeLayout('veryrare')" />
<ul id=catalogGrid>
  <li class="itemContainer rare">
    <div>Rare</div>
  </li>
  <li class="itemContainer veryrare">
    <div>Very Rare</div>
  </li>
  <li class="itemContainer uncommon">
    <div>Uncommon</div>
  </li>
  <li class="itemContainer uncommon">
    <div>Uncommon</div>
  </li>
  <li class="itemContainer rare">
    <div>Rare</div>
  </li>
  <li class="itemContainer rare">
    <div>Rare</div>
  </li>
</ul>

Edit

Below is an optimized version with some minor adjustments:

var allItems = document.getElementsByClassName("item");
var btns = document.getElementsByClassName('btn');

function changeLayout(rarity) {

  var selectedItems = document.getElementsByClassName(rarity);

  // hide all
  Array.from(allItems).forEach((el) => {
    el.classList.add('hide');
  });

  // show selected
  Array.from(selectedItems).forEach((el) => {
    el.classList.remove('hide');
  });

}

// bind click handlers
Array.from(btns).forEach((el) => {
  el.addEventListener('click', function() {
    changeLayout(el.dataset.filter);
  });
});
#grid {
  display: grid;
  grid-auto-flow: row;
  grid-template-columns: repeat(3, 1fr);
  grid-column-gap: 5px;
  grid-row-gap: 5px;
}

.hide {
  display: none;
}
<img class="btn" data-filter="all" src="https://picsum.photos/id/10/50/50">
<img class="btn" data-filter="uncommon" src="https://picsum.photos/id/30/50/50">
<img class="btn" data-filter="rare" src="https://picsum.photos/id/40/50/50">
<img class="btn" data-filter="veryrare" src="https://picsum.photos/id/50/50/50">

<ul id=grid>
  <li class="item all rare">Rare</li>
  <li class="item all veryrare">Very Rare</li>
  <li class="item all uncommon">Uncommon</li>
  <li class="item all uncommon">Uncommon</li>
  <li class="item all rare">Rare</li>
  <li class="item all rare">Rare</li>
</ul>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Identify the moment all Dropzones are added to a form

I am working on a page where multiple dropzones are set up for individual images. Once the user submits the form, all the images attached to the dropzones are resized and then added to the rest of the form fields. After resizing and appending the images, ...

Updating a Texture Image in Three.js

I'm currently working on a minecraft texture editor using three.js, with a similar interface to this. My goal is to implement basic click-and-paint functionality, but I'm facing challenges in achieving this. I have textures for each face of every ...

How to include a key-value pair to a JSON object within an array using JavaScript

I am looking to include the following functionality in the JSON data provided below: "Check if the key name default exists, and if it does, add another key within the same object => ("pin" : 91)." I have attempted to achieve this using the code snippet ...

Error Encountered when Using JQuery AJAX: Unexpected Identifier Syntax Issue

I've been struggling with a strange error for quite some time now. I want to believe that this is one of those errors where the solution will magically appear, but only time will tell. Here's the piece of code causing the issue: var images = ...

What is preventing the item from utilizing the custom texture I created?

(Using IntelliJ to code everything) I am currently working on a Minecraft Mod and have encountered a strange issue. When testing my custom item, the name displays perfectly with spaces, but the texture fails to load. The error message I receive is as follo ...

When using NodeJS, having multiple 'if' statements may result in conflicting headers being returned,

Introduction to Promises. Encountering challenges in NodeJS due to the utilization of multiple if-statements and return-statements. Considering leveraging Promise as a potential solution. This snippet showcases an example: const express = require(' ...

When resizing the window, navigation items vanish

I've implemented the collapse feature using Bootstrap, but encountered an issue where my nav elements disappear when resizing the window. Do you have any suggestions on how to fix this? Here's a snippet of my code: Navb ...

Tips for including various checkbox values in the URL

My form includes multiple checkboxes and I'm looking to insert the values of these checkboxes into the URL in the following manner var a=encodeURIComponent(document.getElementById("idofcheckbox").value) xmlhttp.open("GET","InsertPHPData.php?q="+a+,tr ...

The functionality of Skrollr on mobile is currently not working properly due to the inability to prevent default actions

Encountering the following error on all chromium browsers while using the Skrollr library and accessing the website through mobile: "[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See < ...

Enhancing the visual appeal of my PLY file with vibrant hues using three.js

Hello everyone, I've run into a little issue with three.js. I'm trying to color a ply file and need some assistance. Specifically, I want to add red coloring to the eyes only, not any other part of the model. Can anyone help me with this using th ...

Ways to identify a mobile device

My website uses Javascript to detect when someone is accessing it from a mobile device. This detection method was effective until Apple updated their iPad OS from IOS 13.1 to iPadOS 13.1. The code I use for detection is as follows: if( /Android|webOS|iPh ...

How come the changes in my react component's CSS are not updating in real-time?

After integrating redux into my create-react-app project, I've been struggling to implement a navigator that highlights the active "page link." To achieve this functionality, I am using a combination of react hooks (to maintain the current page state) ...

Although the buttons have the class ui-btn-inline, they do not exhibit inline behavior in the

My header has 2 rows. The first row is a ui-grid-solo and the second row is a ui-grid-c. The issue I'm facing is with the alignment of buttons within the first row. Despite using the class ui-btn-inline, the buttons are not behaving as inline elements ...

increasing sticky header, refreshes the scroll location of the website

My website has a fixed header that expands to reveal more content when a button is clicked. However, I noticed that if the page has been scrolled down before clicking the button, the scroll position resets to the top of the page. To see this issue in acti ...

How can I prevent the same function from being triggered in an AJAX call and a .scroll event when I click on another div with an onclick attribute

I have encountered an issue with my code where two div tags each contain a different onclick function call. The problem arises when I click on one of them and then proceed to click on the other - the .scroll(function() seems to be triggered by both functio ...

Preventing Bootstrap 4 slider images from shifting position when using background-attachment:fixed for a parallax effect

I'm trying to implement a Parallax scrolling effect on my Bootstrap 4 slider. However, every time the slider switches to the next image, the image needs to readjust itself into place. How can I avoid this? .customOverlayText { position: absolute; ...

What's the best way to shrink the size of a hyperlink without affecting the height of the text alignment?

I am currently designing a straightforward menu layout similar to this <div className="main-menu"> <ul> <li className="main-menu__app-menu"><a href="#">link 1</a></li> ...

Creating an object in JavaScript using an array type初始化数组类型为对象javascript

In my code, there is an interface defined as Products export interface Products{ category: string; imageUrl: string; price: number; title: string; } Within my component, I have a variable named products which is an array of type Product ...

"Switching a div's visibility when a link is clicked

http://jsfiddle.net/FsCHJ/2/ Currently, when I add another link, it automatically uses the same functionality as the toggle button. What I want is for "Toggle Edit Mode" to toggle a hidden div on and off. I attempted to modify the code from $("a").click(f ...

Cut costs by saving checkbox states in local storage

I have a JavaScript function that creates a checkbox and listens for a change event: function test() { var a = document.getElementById('test'); var b = document.createElement('input'); b.type = 'checkbox'; b.a ...