使用LESS构建选择器列表

时间:2014-05-29 13:55:25

标签: css less

一般问题

我有媒体查询,我更改了某些文本元素:

body.single .entry-content p,
body.single .entry-content ul,
body.single .entry-content ol,
body.single .entry-content table {
    line-height: 1.8;
}

如何使用LESS只构建选择器列表,而不是相应的CSS值?

我的尝试

我没有找到this answerthis answer,其中包含函数中的CSS。相反,我想它是这样用的:

/* .selector-list() { ... } */

@text-elements: p, ul, ol, table;

.selector-list("body.single .entry-content", @text-elements);
@selector-list {
    line-height: 1.8;
}

它基本上构建一个字符串化列表,方法是在父元素前加上(" body.category")并在一个集合中为每个元素添加一个逗号。以下是我尝试测试输出的内容:

@text-elements: p, ul, ol, table;

.selector-list(@parent, @children, @i:1, @list:"") when (@i <= length(@children)) {
    @child: extract(@children, @i);
    @selector-list: "@{list} @{parent} @{child},";
    .selector-list(@parent, @children, (@i + 1), @selector-list);
}

.selector-list("body.single .entry-content", @text-elements);

section {
    content: @selector-list; // yields only " body.single .entry-content p,"
}

为什么没有@ selector-list构建超过第一个元素?我不完全理解什么时候打印/退回的东西,所以也许我会以错误的方式解决这个问题?

2 个答案:

答案 0 :(得分:4)

如前所述,您的尝试几乎就在那里,由于可变可见性规则,它无效。 请注意,每个.selector-list次迭代定义了新的@selector-list变量,该变量在当前范围内具有更高的优先级,但不会覆盖外部范围的@selector-list变量(即前一个.selector-list的范围迭代和上面的 )。因此,当您在初始@selector-list来电后使用.selector-list时,您会获得在&#34;最高&#34;中设置的值。 .selector-list迭代(即第一个@i = 1)。

To&#34; return&#34;在递归循环的最后一次迭代中,您需要在最后一次迭代中使用此值 定义变量。通常最简单的方法是提供一个&#34;终端&#34; mixin(即递归mixin的最后一次调用的专门化)。事实上,无论如何你都需要这样的终端来处理列表的最后一个逗号。 E.g:

<强>#1

.selector-list(@parent, @children, @i: 1, @list: "") when (@i < length(@children)) {
    @child: extract(@children, @i);
    .selector-list(@parent, @children, (@i + 1), "@{list} @{parent} @{child},");
}

.selector-list(@parent, @children, @i, @list) when (@i = length(@children)) {
    @child: extract(@children, @i);
    @selector-list: e("@{list} @{parent} @{child}");
}

// usage:

@text-elements: p, ul, ol, table;

.selector-list("body.single .entry-content", @text-elements);
@{selector-list} {
    line-height: 1.8;
}

-

#2 与上述相同&#34;优化&#34;:

.selector-list(@parent, @children, @i: length(@children), @list...) when (@i > 1) {
    .selector-list(@parent, @children, (@i - 1),
        e(", @{parent}") extract(@children, @i) @list);
}

.selector-list(@parent, @children, 1, @list) {
    @selector-list: e(@parent) extract(@children, 1) @list;
}

// usage:

@text-elements: p, ul, ol, table;

.selector-list("body.single .entry-content", @text-elements);
@{selector-list} {
    line-height: 1.9;
}

-

#3 说到一般的用例,一个基于字符串的选择器操作&#34;在Less的背景下并不总是一个好主意。主要问题是Less不会将这些字符串视为&#34; native&#34;选择器和大多数高级较少的功能都不能与它们一起使用(例如,少赢了,不能识别,&和类似的元素,所以这些规则不能嵌套, extend也无法看到此类选择器等。 另一种选择,更多&#34;不太友好&#34;方法是将这样的列表定义为mixin而不是变量,例如:

.text-elements(@-) {p, ul, ol, table {@-();}}

body.single .entry-content { 
    .text-elements({
        line-height: 1.8;
    });
}

和(当你还需要重用body.single .entry-content /.text-elements/时):

.text-elements(@-) {
    p, ul, ol, table 
        {@-();}}

.selector-list(@-) {
    body.single .entry-content {
        .text-elements(@-);
    }
}

.selector-list({
    line-height: 1.9;
});

-

P.S。另外,更一般地说,不要错过在Less中将媒体查询放入选择器规则集中,因此根据用例,它通常也更容易编写选择器列表一次并在其中设置媒体依赖样式(即与标准CSS方法相反,您必须为每个媒体查询重复相同的选择器。)

答案 1 :(得分:1)

这非常接近。需要进行一些调整以使其完全正确,但肯定是一个良好的开端。

您尝试的问题是LESS不喜欢覆盖相同的变量,它会产生错误。这是因为变量是LESS中的常量。

<强> LESS

@text-elements: p, ul, table;

.selector-list(@el,@t1) {
  @selector-list: ~"@{t1}, body.single .entry-content @{el}";
}

.selector-list(@index, @elements, @t1) when (@index > 1) {
  @el: extract(@elements, @index);
  @t2: "@{t1}, body.single .entry-content @{el}";
  .selector-list(@elements,@t2);
}

.selector-list(@elements) {
  @num: length(@elements);
  @el: extract(@elements, @num);

  @t2: "body.single .entry-content @{el}";
  .selector-list((@num - 1), @elements, @t2);
}

.selector-list(@text-elements);
@{selector-list} { content: 'Bacon'; }

<强>输出

body.single .entry-content table, 
body.single .entry-content ul, 
body.single .entry-content p, ul, table {
   content: 'Bacon';
}

我从这个答案得到了大部分内容; Concatenate string in less in loop