1

I have a situation where I need to specify the nth instance of a given selector AND all following siblings. So I have this:

td:nth-child(n + 2)
{
    width: 125px;
}

But I do a lot of this, with different selectors and different offsets, and repeating the nth-child(n + offset) is tedious and obscures the intent of the code.

I would prefer to do something like this:

.self-and-siblings(@selector; @offset)
{
  ~'@{selector}:nth-child(n + @{offset})';
}

and then invoke it like this:

.self-and-siblings('td', 2)
{
    width: 125px;
}

But this doesn't compile. Is it possible to accomplish what I need?

0

1 Answer 1

1

Less doesn't have any true functions that can return values. Also a mixin can output content only within selector blocks (either a selector of its own or the parent selector). In your case there is only a string print but it is not assigned to any property (or) present within any selector block.

For your case, you can write a very simple mixin like below and use it:

.nth-child-mixin(@offset, @props){
  &:nth-child(n + @{offset}){
    @props();
  }
}
td{
  .nth-child-mixin(3, {
    color: red;
  });
}
td{
  .nth-child-mixin(5, {
    color: blue;
  });
}

The above nth-child-mixin takes the offset and the properties that should be assigned as inputs. The properties is a detached ruleset which is then called from within the nth-child selector block. The compiled CSS output will look as follows:

td:nth-child(n + 3) {
  color: red;
}
td:nth-child(n + 5) {
  color: blue;
}

A more comprehensive mixin would be the below as you can pass it the multiplier for n also.

.nth-child-mixin(@multiplier, @offset, @props){
  &:nth-child(@{multiplier}n + @{offset}){
    @props();
  }
}
td{
  .nth-child-mixin(2, 5, {
    color: blue;
  });
}

The compiled CSS in this case would be the following:

td:nth-child(2n + 5) {
  color: blue;
}

I feel using detached rulesets make it more clearer but if you want the mixin to just output a selector, you could make the mixin definition as follows. The only drawback is you may occasionally run into scoping issues when you need more than one such block within same nesting.

.nth-child-mixin(@multiplier, @offset){
  @sel: ~":nth-child(@{multiplier}n + @{offset})";
}
td{
  .nth-child-mixin(1, 3);
  &@{sel}{
    color: red;
  }
}
td{
  .nth-child-mixin(2, 5);
  &@{sel}{
    color: blue;
  }
}

For example if you want to write two nth-child selectors like below within same td nesting then it wouldn't produce the expected output due to scope, lazy-loading etc.

td{
  .nth-child-mixin(1, 3);
  &@{sel}{
    color: red;
  }
  .nth-child-mixin(3, 5);
  &@{sel}{
    color: red;
  }
}

and that would push you into using anonymous selector boxes like in below sample to solve the scoping issues (these hacks are just terrible).

td{
  & {
    .nth-child-mixin(1, 3);
    &@{sel}{
      color: red;
    }
  }
  &{
    .nth-child-mixin(3, 5);
    &@{sel}{
      color: red;
    }
  }
}
Sign up to request clarification or add additional context in comments.

7 Comments

Hahaha @Persijn been away for quite a long time, let me write atleast a few now :D
That's some of the way there, but I think that having to pass the styles like that will impose a really cumbersome syntax. But let me play around with it a bit.. Thanks!
@JoshuaFrank: I prefer the approach with passing rulesets but if you want to only generate a selector using the mixin then see the update to my answer. I was filling it out as I saw your comment :)
@Harry: So, when I tried your first example, I get compiler errors of props and in the latest version, I get errors on sel. I must be using a version of LESS that has different rules than your version. I'm not sure what else would explain it. Ugh.
@JoshuaFrank: I'm using the online compiler @ http://less2css.org and it runs on v2.5.3. Are you using some older version (or) a port of Less.js like LessPHP or dotLess etc?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.