Home > Software design >  CSS nth-of-type(odd) selector doesn't work anymore after using filterbuttons
CSS nth-of-type(odd) selector doesn't work anymore after using filterbuttons

Time:08-17

How can I keep the CSS odd / even items after selecting a filter (one/two/three)?

In CSS I say .grid .show:nth-of-type(odd){filter:sepia(100%);} But when I select a filter the order is not correct. It must be something simple.

You can see here on my demo. It needs to be odd/even when I select a button which it doesn't. https://jsfiddle.net/fourroses666/otda1bec/3/

CodePudding user response:

The :nth-of-type selects the nth child of certain type, but it does not care about classes. If you want this to work consistently, you might want to add and remove items from the list to keep CSS correct, I would suggest the following (note that I have tried to remove any distracting elements here, there's no need for all the classNames and styles so I simplified it to keep the focus:

const wrapper = document.querySelector( '.grid' );
const filterables = Array.from( wrapper.children );

function filter(c) {

  filterables.forEach(item => {

    if( c === 'all' || item.classList.contains( c ) ){

      wrapper.appendChild( item );

    } else {

      item.remove();

    }

  });

}
.grid {
  margin:0 0 50px;
  transition: height .2s;
  display:flex;
  flex-wrap:wrap;
}
.grid:after {
  content: '';
  display: block;
  clear: both;
}
.grid > * {
  display: block; 
  filter: grayscale(0%);
  position: relative;
  margin: 0;
  min-width: 20%;
  max-width: 20%;
  width: 20%;
  transition: all .3s ease-in-out;
  height: 0;
  padding-top: 20%;
  background-image: url(http://placekitten.com/g/601/601);
  background-color: var(--color2);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.grid > *:hover {
  filter:grayscale(100%);
}
.grid > * h3 {
  position: absolute;
  top: 40%;
  left: 10px;
  text-align: center;
  width: 50%; 
  background: white;
}

.grid > *:nth-child(odd) {
   filter: invert(100%);
}
<div id="filter-box">
  <button  onclick="filter('all')">all</button>
  <button  onclick="filter('one')">one</button>
  <button  onclick="filter('two')">two</button>
  <button  onclick="filter('three')">three</button>
</div>

<br>

<div >

  <div ><h3>one</h3></div>
  <div ><h3>three</h3></div>
  <div ><h3>three</h3></div>
  <div ><h3>one</h3></div>
  <div ><h3>two</h3></div>
  <div ><h3>one</h3></div>
  <div ><h3>one</h3></div>
  <div ><h3>two</h3></div>
  <div ><h3>three</h3></div>
  <div  ><h3>two</h3></div>
  <div ><h3>two</h3></div>
  <div ><h3>one</h3></div>

</div>

You might also have noticed I highly simplified your filter function (you made it a little unnecessarily complicated). This filter just checks if a className is present on the element (with classList.contains(), see below) and then adds or removes the element from the page flow.

On that note, I would also like to add that in the future, don't write your own AddClass and RemoveClass methods. Instead use classList to do this consistently for you with any edge cases already solved:

htmlElement.classList.add( 'show' )
htmlElement.classList.remove( 'show' )
htmlElement.classList.toggle( 'show', optionalBooleanCheckToToggleAppropriately )

These methods are much more robust.

CodePudding user response:

You can use nth-child directly instead of nth-of-type

.grid .show:nth-child(odd) {filter:sepia(100%);}

  • Related