使用LESS构建选择器列表 [英] Build list of selectors with LESS

查看:124
本文介绍了使用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值?



我的尝试



我不是在寻找此答案此答案,其中包括CSS功能。相反,我想象它使用这样:

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

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

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

),并在集合中的每个元素上附加逗号。这里是我试过只是测试输出:

  @ text-elements:p,ul, 

.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; //仅产生body.single .entry-content p,
}

没有@选择器列表构建过去的第一个元素?我不完全理解什么时候打印/返回,所以也许我会这样错误的方式?

解决方案

如前所述,你的尝试几乎是在那里,它不工作,因为变量的可见性规则。
请注意,每个 .selector-list 迭代定义了新的 @ selector-list 当前范围,但不覆盖外部范围的 @ selector-list 变量(即上一个 .selector-list iterations和之上)。所以当你在初始 .selector-list 调用后使用 @ selector-list 最高
.selector-list 迭代(即第一个具有 @i = 1 / p>

要从递归循环的最后一次迭代中返回一个值,您需要在最后一次迭代中定义一个具有此值的变量。通常,这样做的最简单的方法是提供终端混合(即,用于递归混合的最后调用的专门化)。事实上,你需要这样的终端来处理列表的最后一个逗号。例如:



#1

  (@i< length(@children)){
@child:extract(@children,@i).selector-list(@parent,@children,@i:1,@list: ;
.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});
}

//用法:

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

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



-



#2 与上述相同只是稍微优化:

  .selector-list @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 )@list;
}

//用法:

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

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



-



#3 一般来说,在使用Less的情况下,基于字符串的选择器操作并不总是一个好主意。主要的问题是,Less不把这样的字符串当作native选择器,大多数高级Less特性不能用于它们(例如,Less不会识别 & 和类似的元素,所以这样的规则不能嵌套, extend 也看不到这样的选择器等等)。
另一种更不友好的方法是将这样的列表定义为混合而不是变量,例如:

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

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

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

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

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

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

等。



-



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


General problem

I have media queries, where I change certain text elements like so:

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

How can I use LESS to build just the list of selectors, not the corresponding CSS values?

My attempt

I'm not looking for this answer or this answer, which include the CSS in the function. Instead, I imagine it used like this:

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

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

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

It would essentially build a stringified list by prepending the parent ("body.category") and appending a comma to each element from a set. Here's what I've tried just to test output:

@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,"
}

Why doesn't @selector-list build past the first element? I don't entirely understand when something is printed/returned, so perhaps I'm going about this all the wrong way?

解决方案

As already mentioned your attempt is almost there, it does not work because of variable visibility rules. Notice that each .selector-list iteration defines new @selector-list variable which have higher precedence in the current scope but does not override @selector-list variables for the outer scope (i.e. scopes of the previous .selector-list iterations and above). So when you use @selector-list after the initial .selector-list call you get the value set in the "highest" .selector-list iteration (i.e. the first one with @i = 1).

To "return" a value from the last iteration of a recursive loop you need to define a variable with this value only within that last iteration. Usually the simplest way to do this is to provide a "terminal" mixin (i.e. a specialization for the last call of the recursive mixin). In fact you would need such terminal anyway to handle the final comma of the list. 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 Same as above just slightly "optimized":

.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 Speaking of the use-case in general, a "string-based selector manipulation" is not always a good idea in context of Less. The main problem is that Less does not treat such strings as "native" selectors and most of advanced Less features won't work with them (e.g. Less won't recognize ,, & and similar elements there so such rules can't be nested, extend also can't see such selectors etc. etc.). An alternative, more "Less-friendly" approach is to define such list as a mixin rather than a variable, e.g.:

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

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

and (when you also need to reuse 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;
});

etc.

-

P.S. Also, speaking in even more general, don't miss that in Less a media query may be put into selector ruleset, so depending on a use-case it's also often more easy to write a list of selectors once and set media depended styles inside it (i.e. doing it in opposite to the standard CSS method where you have to repeat same selector(s) for each media query).

这篇关于使用LESS构建选择器列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆