0

So I'm trying to keep track of a counter which will increment every time the condition within the loop is met. The catch here (there's two actually) is:

  • Sass loops have no knowledge of the length of what they're iterating over
  • I need to check whether or not an element exists or has a certain class (either should work)

The second point is where I'm stuck at right now. There must be some way to write a conditional to wrap the counter increment so the counter only gets updated when the condition is met. Currently I'm inserting the counter increment inside an nth-child selector.

Code:

$total-cards: 0;
$max-cards: 10;

@for $i from 1 through $max-cards {
  .child:nth-child(#{$i}) {
    $total-cards: $total-cards + 1;
  }
}

@debug $total-cards;

Why this doesn't work^: It's updating the counter every time since that block of code runs anyway regardless of whether there are 5 children or 10.

From what I've read, I don't think this can be accomplished using the @if directive...

Jose
  • 4,880
  • 8
  • 27
  • 49
  • What's the condition you're wanting to check for? – Ouroborus Mar 01 '19 at 00:40
  • @Ouroborus If `.child` exists as a child of where this is being called. Or if elements that are children have a class of `.child`. – Jose Mar 01 '19 at 00:44
  • 1
    CSS (and, by extension, Sass) isn't "called", it just exists. If an element happens to exist for which the CSS has a matching rule then so be it. CSS (and Sass) can't tell how many elements you have or will have. – Ouroborus Mar 01 '19 at 00:56

1 Answers1

1

A set of CSS rules are static in that the structure does not change. Values might change (via --var()), but the structure stays the same and the values are applied to the same things in the same way.

Sass is just another way of writing CSS, adding syntactical sugar, but not changing how CSS works.

CSS doesn't know or care what's in your page. Instead, conceptually, for each element, the page asks the CSS if there is a rule that matches this element and then applies the associated styles.

Things like :nth-child(an+b) don't count elements and don't need to. To match against an+b, you don't need to know how many elements there are, just which would otherwise match and would have an index for which the formula can be made to fit. The other child-related pseudo-selectors are just shortcuts for :nth-child().

So you can match against things like "second from last", "every third", or even "every odd but not those that are every fifth".

While CSS can't count elements, CSS3 can be used to infer the number of elements and apply a rule accordingly, as shown in this answer:

/* one item */
li:first-child:nth-last-child(1) {
/* -or- li:only-child { */
    width: 100%;
}

/* two items */
li:first-child:nth-last-child(2),
li:first-child:nth-last-child(2) ~ li {
    width: 50%;
}

/* three items */
li:first-child:nth-last-child(3),
li:first-child:nth-last-child(3) ~ li {
    width: 33.3333%;
}

/* four items */
li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
    width: 25%;
}

These rules take advantage of the fact that, for example, in a set of four li siblings, the first element is also the fourth-from-last element. The first part of the rules applies to the "indicator" element. The second part of the rules applies to the matching siblings of that element. However the CSS still doesn't know how many elements there are, it just knows that a particular element happened to match a cross-section of selectors. It won't be able to provide you with the number so you'd still have to supply it yourself.

Sass doesn't change this. It may let you write CSS in a terser way, but, in the end, it's still going to be compiled to CSS and so will have all the same restrictions as CSS.

Ouroborus
  • 16,237
  • 4
  • 39
  • 62