如何将Sass函数转换为Less?

3

有人知道如何在Less中重新创建下面的Sass函数吗?我希望能够轻松地转换任何CSS属性中的单位(例如:字体大小、边距、填充等)。

Sass:

@function get-vw($target) {
    $vw-context: (1440 * 0.01) * 1px;
    @return ($target / $vw-context) * 1vw;
}

CSS:

selector {
    font-size: get-vw(20px)vw;
}

Sass源自这里:http://emilolsson.com/tools/vw-unit-calc-an-online-responsive-css-font-size-calculator/

1个回答

3

更新的答案:

正如下面评论中seven-phases-max所提到的,他创建了一个非常棒的自定义Less插件,允许我们在Less中编写函数(是的,带有返回值),并在规则内使用它们。

为了使用这个插件,我们必须先通过执行以下命令来安装插件:

npm install -g less-plugin-functions

下一步是编写自定义函数。操作语法是首先将函数包装在名为 .function {} 的 mixin/selector 块中,然后只需复制粘贴我在原始答案中提供的 mixin 代码(见下文)。唯一的更改是必须用 return 替换 @output 变量,因为该函数返回分配给此属性的值。因此,代码如下所示:
.function{
  .get-vw(@target) {
    @vw-context: (1440 * 0.01) * 1px;
    return: (@target / @vw-context) * 1vw; /* do calc, set output to "return" property */
  }
}

一旦函数被创建,使用起来非常简单明了,就像我们在 Sass 中所做的一样:

.selector {
  font-size: get-vw(20px);
  margin-top: get-vw(16px);
}

现在,下一步是编译Less文件以生成输出的CSS。使用命令行编译需要使用相同的lessc命令,但我们必须在执行时包含/调用自定义插件。因此,编译语句应如下所示:

lessc --functions test.less test.css

所有这些信息都已经在GitHub页面中提供,但为了完整性和安全起见,我已经在回答中再次记录了它们。
注意:如果自定义函数中没有指定return属性,则在编译过程中将抛出以下错误:
RuntimeError: error evaluating function get-vw: [plugin-functions] can't deduce return value, either no mixin matches or return statement is missing in [file name]
首先要明确的是,在Less中无法编写真正的函数,因为不可能使用return语句。
我们可以做的一件事是编写一个mixin并绕开障碍,使其行为更接近于函数。下面是一个示例:
.get-vw(@target) { /* take an input */
  @vw-context: (1440 * 0.01) * 1px;
  @output: (@target / @vw-context) * 1vw; /* do calc, set an output var */
}

.parent {
  .get-vw(20px); /* expose output var + value to current scope by calling mixin */
  font-size: @output; /* use the value of output var wherever needed */
  .child { /* scoping is not a problem as you can see with the child */
    .get-vw(16px); 
    padding: @output;
    }
}

但是上面代码片段的问题在于,如果两个属性需要使用此函数的输出,并且它们各自具有不同的输入值,则由于Less中变量的惰性加载,将会出现问题。例如,请考虑下面的代码片段(.get-vw mixin与先前的代码相同)。
.parent {
  .get-vw(20px);
  font-size: @output;
  .get-vw(16px);
  margin-top: @output;
}

您可能期望的输出如下所示:
.parent {
  font-size: 1.38888889vw;
  margin-top: 1.11111111vw;
}

但实际输出将是这样的:(您可以看到,相同的值应用于两个位置
.parent {
  font-size: 1.38888889vw;
  margin-top: 1.38888889vw;
}

解决方案是变得更加具有hacky性质,将每个这样的属性放置在一个未命名的命名空间(&)中,并因此为每个属性提供自己的作用域:
.parent {
  & {
    .get-vw(20px);
    font-size: @output;
  }
  & {
    .get-vw(16px);
    margin-top: @output;
  }
}

如您所见,这一切都变得非常混乱。在Less中编写真正的函数的唯一方法是编写自定义插件,就像Bass Jobsen在这里描述的那样。这是复杂的,但这是唯一的真正方法。


1
"Postprocessor/Feature Plugins" -> "功能函数". - seven-phases-max
1
这太棒了@seven-phases-max。刚刚安装并尝试了一下,真是太棒了。在我看来,这正是Less所缺少的。我会为你的插件点赞100次!即使在你给我链接之后,我也只关注那个Sass2Less插件,没有注意到这一个。我现在会立即编辑我的回答。 - Harry
1
函数特性一直计划作为本地功能添加,但在其确切语法方面存在许多争议(仍未达成共识,因此需要插件)。 - seven-phases-max
1
@seven-phases-max:再次感谢您的出色贡献。我真的很喜欢它。我现在已经编辑了答案,如果您发现有任何错误(或需要更正)并且您有时间,请随时编辑我的答案 :) - Harry
1
@Harry,我想出了一种类似的解决方案,更加通用,虽然似乎@seven-phases-max提到的插件最终是最好的答案。我的解决方案是使用值1调用mixin:.get-vw(1); 然后将返回值乘以所需大小: font-size: @output * 20;margin-top: @output * 16; 这简单地避免了多次调用mixin和创建单独的作用域。但这仍不完美。我会尝试使用插件! - Ryan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接