Generating selector lists in LESS

让人想犯罪 __ 提交于 2019-12-10 10:57:54

问题


Live demo here: http://codepen.io/KenPowers/pen/Ddfqh

Consider the following LESS code:

// Hide all list items by default and make internal labels have pointer cursors
li {
  display: none;
  label {
    cursor: pointer;
  }
}

// This function generates selectors and corresponding css
.gen (@tag) {
  @sel: ~"#@{tag}:checked";
  @{sel} {
    & ~ ul > li[data-index~=@{tag}] {
      display: list-item;
    }
    & ~ ul > li > label[for=@{tag}] {
      color: red;
    }
  }
}

// Generate required selectors and css
.gen("foo");
.gen("bar");
.gen("baz");

It generates the following CSS:

li {
  display: none;
}
li label {
  cursor: pointer;
}
#foo:checked ~ ul > li[data-index~="foo"] {
  display: list-item;
}
#foo:checked ~ ul > li > label[for="foo"] {
  color: red;
}
#bar:checked ~ ul > li[data-index~="bar"] {
  display: list-item;
}
#bar:checked ~ ul > li > label[for="bar"] {
  color: red;
}
#baz:checked ~ ul > li[data-index~="baz"] {
  display: list-item;
}
#baz:checked ~ ul > li > label[for="baz"] {
  color: red;
}

However, a more compressed output may look like the following:

li {
  display: none;
}
li label {
  cursor: pointer;
}
#foo:checked ~ ul > li[data-index~="foo"],
#bar:checked ~ ul > li[data-index~="bar"],
#baz:checked ~ ul > li[data-index~="baz"] {
  display: list-item;
}
#foo:checked ~ ul > li > label[for="foo"],
#bar:checked ~ ul > li > label[for="bar"],
#baz:checked ~ ul > li > label[for="baz"] {
  color: red;
}

Is there a way I can modify the original LESS to generate the second CSS listing?


回答1:


In Less 1.4.0+ you can :extend a placeholder class:

.dp-list-item {
  display: list-item;
}
.label-color {
  color: red;
}

// This function generates selectors and corresponding css
.gen (@tag) {
  @sel: ~"#@{tag}:checked ~ ul > li";
  @{sel} {
    &[data-index~=@{tag}]:extend(.dp-list-item){}
    & > label[for=@{tag}]:extend(.label-color){}
  }
}

// Generate required selectors and css
.gen("foo");
.gen("bar");
.gen("baz");

Forked pen

Generated CSS:

.dp-list-item,
#foo:checked ~ ul > li[data-index~="foo"],
#bar:checked ~ ul > li[data-index~="bar"],
#baz:checked ~ ul > li[data-index~="baz"] {
  display: list-item;
}
.label-color,
#foo:checked ~ ul > li > label[for="foo"],
#bar:checked ~ ul > li > label[for="bar"],
#baz:checked ~ ul > li > label[for="baz"] {
  color: red;
}

As you can see, the only drawback is that both classes which I've used as placeholders will be in the generated CSS. I believe this can't be worked around until Less implements something akin to Sass' placeholder selectors.

ps. I've omitted the global li rules which are not part of the mixin for brevity.


As per OP request, here is a Sass (with .scss syntax) equivalent:

//placeholder selectors
%dp-list-item {
  display: list-item;
}
%label-color {
  color: red;
}

// This function generates selectors and corresponding css
@mixin gen($tag) {
  ##{$tag}:checked ~ ul > li {
    &[data-index~=#{$tag}] {
      @extend %dp-list-item;
    }
    & > label[for=#{$tag}] {
      @extend %label-color;
    }
  }
}

// Generate required selectors and css
@each $item in (foo bar baz) {
  @include gen($item);
}

Demo

Generated CSS:

#foo:checked ~ ul > li[data-index~=foo], #bar:checked ~ ul > li[data-index~=bar], #baz:checked ~ ul > li[data-index~=baz] {
  display: list-item;
}

#foo:checked ~ ul > li > label[for=foo], #bar:checked ~ ul > li > label[for=bar], #baz:checked ~ ul > li > label[for=baz] {
  color: red;
}

You can see that Sass' syntax is rather verbose when compared to Less. Sass also has some nice features such as control directives and excellent interpolation which I've applied in the example above.



来源:https://stackoverflow.com/questions/20256442/generating-selector-lists-in-less

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!