Home > Software engineering >  How can I have :not(.class):nth-of-type(even)?
How can I have :not(.class):nth-of-type(even)?

Time:12-21

I've been using CSS for stuff like this for a while, but it seems this one specific scenario doesn't work how it should.

What I want to have a list like you would in a spreadsheet, with each line alternating from a light grey to a slightly darker grey.

Spreadsheet lines 1-9, with alternating colors

<style>
  .spreadsheet {
    display: grid;
    grid-auto-flow: row;
  }
  .spreadsheet > div {
    padding: 0.5rem;
  }
  .spreadsheet > :first-of-type {
    border-radius: 1rem 1rem 0 0;
  }
  .spreadsheet > :only-of-type {
    border-radius: 1rem;
  }
  .spreadsheet > :last-of-type {
    border-radius: 0 0 1rem 1rem;
  }
  .spreadsheet > :nth-of-type(odd) {
    background-color: #fafafa
  }
  .spreadsheet > :nth-of-type(even) {
    background-color: #eaeaea
  }
</style>

<div >
  <div>Line 1</div>
  <div>Line 2</div>
  <div>Line 3</div>
  <div>Line 4</div>
  <div>Line 5</div>
  <div>Line 6</div>
  <div>Line 7</div>
  <div>Line 8</div>
  <div>Line 9</div>
</div>

Everything above works just fine, as anticipated. Now here's my issue... In my scenario, I'm using JavaScript to change the classes of certain lines, based on a filter. With this, I simply want to set the display of lines that are filtered out to none, whilst keeping the same pattern of alternating colors as before. This should also render the first and last lines to have rounded borders.

Spreadsheet lines 2, 5, 6-7, and 9 with incorrect alternating colors

<style>
  .spreadsheet {
    display: grid;
    grid-auto-flow: row;
  }
  .spreadsheet > div {
    padding: 0.5rem;
  }
  .spreadsheet > :not(.hidden):first-of-type {
    border-radius: 1rem 1rem 0 0;
  }
  .spreadsheet > :not(.hidden):only-of-type {
    border-radius: 1rem;
  }
  .spreadsheet > :not(.hidden):last-of-type {
    border-radius: 0 0 1rem 1rem;
  }
  .spreadsheet > :not(.hidden):nth-of-type(odd) {
    background-color: #fafafa
  }
  .spreadsheet > :not(.hidden):nth-of-type(even) {
    background-color: #eaeaea
  }
  .hidden {
    display: none;
  }
</style>

<div >
  <div >Line 1</div>
  <div>Line 2</div>
  <div >Line 3</div>
  <div >Line 4</div>
  <div>Line 5</div>
  <div>Line 6</div>
  <div>Line 7</div>
  <div >Line 8</div>
  <div>Line 9</div>
</div>

You'll notice, Line 1 is hidden, so Line 2 should have a background-color of #fafafa and a border-radius of 1rem 1rem 0 0, but it has neither. This is very obvious when the same colored lines are right next to each other.

Any ideas on how I can accomplish this?

CodePudding user response:

I'm not quite sure if this will work, but wouldn't it be easier to do something like this in JS:

document.getElementById(id).style.visibility = "hidden";

or

document.getElementById(id).style.display = "none";

And assigning a different id for each line, instead of changing the classes? I think you might be overcomplicating the entire thing.

CodePudding user response:

This snippet avoids the question of CSS trying to 'decide' whether its an odd or even element, and avoids the need for extra JS.

It just puts the background as a linear-gradient, repeating, on the parent element.

Likewise, the border radius is on the parent too so there is no need to work out whether an element is the last visible one or not:

* {
  margin: 0;
}

.spreadsheet {
  display: grid;
  grid-auto-flow: row;
  border-radius: 1rem;
  background-image: linear-gradient(#fafafa 0 2rem, #eaeaea 2rem 4rem);
  background-size: 100% 4rem;
}

.spreadsheet>div {
  padding: 0.5rem;
  line-height: 1rem;
}
<div >
  <div>Line 1</div>
  <div>Line 2</div>
  <div>Line 3</div>
  <div>Line 4</div>
  <div>Line 5</div>
  <div>Line 6</div>
  <div>Line 7</div>
  <div>Line 8</div>
  <div>Line 9</div>
</div>
With some children display: none;
<div >
  <div style="display: none;">Line 1</div>
  <div>Line 2</div>
  <div>Line 3</div>
  <div style="display: none;">Line 4</div>
  <div>Line 5</div>
  <div style="display: none;">Line 6</div>
  <div>Line 7</div>
  <div>Line 8</div>
  <div>Line 9</div>
</div>

  • Related