更少-具有简写数字和/或字符串值的参数混合,具有rem和px后备 [英] Less - parametric mixin with shorthand numeric and or string values, with rem and px fallback

查看:46
本文介绍了更少-具有简写数字和/或字符串值的参数混合,具有rem和px后备的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用更少的代码,我尝试输出属性的CSS组合速记值,同时根据作为变量传递的值检测作为变量传递的值的类型.

Using Less, I'm trying output css combination shorthand values for properties, whilst detecting the type of a value passed as a variable depending on how many values are passed as variables.

  • 一个值@v1
  • 两个值@v1@v2
  • 四个值@v1@v2@v3@v4
  • one value @v1
  • two values @v1 and @v2
  • four values @v1, @v2, @v3 and @v4

对于每个检测到的变量,请检查是否是大于0的数字,如果是,则为每个属性值输出一个rem和px值,因此编译的css可能类似于:

And for each variable detected, check if is is a number greater than 0, and if so output a rem and px value for each property value, so the complied css might be something like:

.demobox{
  border-width: 10px 20px 0 0;
  border-width: 1rem 2rem 0 0;
  padding: 0 50px;
  padding: 0 2rem;
  margin: 20px auto;
  margin: 2rem auto;
  font-size: 16px;
  font-size: 1.6rem;
}

这很容易解决,只要声明两个以上的值即可,但是如果我需要四个值,则嵌套的mixin和守卫的数量将变得非常复杂.

This is fairly easy to solve where no more than two values are ever declared, but If I need four values, the number of nested mixins and guards becomes pretty complicated.

选择rems的原因是,与ems相比,它易于实现,并且避免了记住必须将字体大小重置为每个父项的麻烦.此外,在rems和ems上,较旧的设备支持问题都差不多,因此我认为px后备效果最好.

以下是我目前为止的代码笔,但我会尽力尽我最大的努力解释我的工作.

Here's' the code pen of where I am so far, but I'll try and explain my workings so far as best as I can.

有没有一种方法可以简化此过程?我是新手.我想有一种更简单的方法来检测

Is there a way to simplify this process? I'm new to less. I imagine there is a much simpler way to detect

  • 声明值的数量
  • 每个值的类型
  • 如果数字值需要rem和px值回退

谢谢

我有一个参数混合,它输出rem值和px后备值以及声明的属性

I have a parametric mixin which outputs a rem value and px fallback value along with the declared property

@root-font-size: 10;

.rem(@property, @v1) when (@v1 = @v1){
    @px1: @v1 * @root-font-size;
    @{property}:  ~'@{px1}px';
    @{property}: ~'@{v1}rem';
}

这对于为一组css属性快速生成rem和像素回退非常有用

This is great for quickly generating both the rem and pixel fallback for a set css property

/* call the rem mixin */
.demobox {
    .rem(margin, 2);
}
/* output */
.demobox {
    margin: 20px;
    margin: 2rem;
}

一种非常有用的情况是生成具有后备功能的font-sizeline-height

One really useful case for this is generating font-size and line-height values with fallbacks

/* call the font-classes mixin */
.font-classes(@fontsize, @lineheight) {
    .rem(font-size, @fontsize);
    .rem(line-height, @lineheight);
}
/* output */
.demobox {
    font-size: 16px;
    font-size: 1.6rem;
    line-height: 24px;
    line-height: 2.4rem;
}

到目前为止,我可以为单个值输出一个rem和像素回退,并将.rem mixin与另一个mixin嵌套在一起.

So far so good, i can output a rem and pixel fallback for a single value and nest the .rem mixin with in another mixin.

此刻,如果我想传递多个值,则必须为每个所需的值调用.rem mixin:

At the moment, if I want to pass more than one value I have to call the .rem mixin for each required value:

/* call the rem mixin */
.demobox {
    .rem(margin-left, 2);
    .rem(margin-right, 2);
}
/* output */
.demobox {
    margin-left: 20px;
    margin-left: 2rem;
    margin-right: 20px;
    margin-right: 2rem;
}

理想情况下,我希望能够将具有属性的一两个或四个值传递给.rem mixin.

Ideally I'd like to be able to do is pass either one two or four values with a property to the.rem mixin.

.demobox {
    .rem(margin, 2, 1);
}

正如我前面提到的,对于两个值,并检查值类型是什么并不那么困难.这需要.rem mixin版本,并使用一个gaurd来检查是否声明了@v2.

As I mentioned earier this is not so difficult for two values, and to check what the value type is. This requires a version of the .rem mixin with a gaurd applied to check that @v2 is declared.

这将触发嵌套的.rem-two mixin.

This the triggers a nested .rem-two mixin.

// when there are two values
.rem(@property, @v1, @v2) when (@v1 = @v1) and (@v2 = @v2){
    .rem-two(@property, @v1, @v2);
}

.rem-two的三个版本,其中每个防护罩都不同.

There are three versions of the .rem-two, where the guards are different for each.

如果@v1@v2都大于0,则检测

Detect if both @v1 and @v2 are numbers greater than 0

.rem-two(@property, @v1, @v2) when (@v1 = @v1) and not (@v1 = 0) and (isnumber(@v1)) and (@v2 = @v2) and not (@v2 = 0) and (isnumber(@v2)) {
    @px1: @v1 * @root-font-size;
    @px2: @v2 * @root-font-size;
    @{property}:  ~'@{px1}px @{px2}px';
    @{property}: ~'@{v1}rem @{v2}rem';
}

如果@v1@v2都大于0,则检测

Detect if both @v1 and @v2 are numbers greater than 0

.rem-two(@property, @v1, @v2) when (@v1 = @v1) and not (@v1 = 0) and (isnumber(@v1)) and (@v2 = 0), not (isnumber(@v2)){
    @px1: @v1 * @root-font-size;
    @{property}:  ~'@{px1}px @{v2}';
    @{property}: ~'@{v2}rem @{v2}';
}

/* call the rem mixin */
.demobox {
    .rem(margin, 2, 1);
}
/* outputs */
.demobox {
    margin: 10px 20px;
    margin: 1rem 2rem;
}

如果两个@v1都是大于0的数字并且@v2都是0或不是数字

Detect if both @v1 is a number greater than 0 and @v2 is either a value of 0 or not a number

不需要'@ px2'像素后备广告,因此将其删除.

.rem-two(@property, @v1, @v2) when (@v1 = @v1) and not (@v1 = 0) and (isnumber(@v1)) and (@v2 = 0), not (isnumber(@v2)){
    @px1: @v1 * @root-font-size;
    @{property}:  ~'@{px1}px @{v2}';
    @{property}: ~'@{v2}rem @{v2}';
}
/* call the rem mixin */
.demobox {
    .rem(margin, 2, auto);
}
/* outputs */
.demobox {
    margin: 10px auto;
    margin: 1rem auto;
}

检测是否两个@v1均为0或不是数字,并且@v2是大于0的数字

Detect if both @v1 is either a value of 0 or not a number and @v2 is a number greater than 0

不需要'@ px1'像素后备广告,因此将其删除.

.rem-two(@property, @v1, @v2) when (@v1 = 0), not (isnumber(@v1)) and (@v2 = @v2) and not (@v2 = 0) and (isnumber(@v2)){
    @px2: @v2 * @root-font-size;
    @{property}:  ~'@{v1} @{px2}px';
    @{property}: ~'@{v1} @{v2}rem';
}
/* call the rem mixin */
.demobox {
    .rem(margin, 0, 20);
}
/* outputs */
.demobox {
    margin: 0 20px;
    margin: 0 2rem;
}

由于mixin的这两个值版本只有三种可能性,因此很容易解决这个问题,但是使用3或四个值时,嵌套的mixin和防护的数量会扩展以涵盖所有可能性.

As there are only 3 possibilities for this two value version of the mixin It is easy to solve this problem, but with 3 or four values the number of nested mixins and guards expands to cover all possibilities.

作为其他示例. 我已将.rem mixin改用于输出带有供应商前缀的pxremborder-radius值,以确保它仅处理数字值,我有防范措施来检查传递的值是否为大于0

As additional examples. I have repurposed the .rem mixin to output px and rem, border-radius values with vendor prefixing, to ensure that it only processes numeric values, I have guards to check if the value being passed is a number that is greater that 0

.prefix(@property, @v1) when (isnumber(@v1)) and (@v1 > 0) {
    @px1: @v1 * @root-font-size;
    -webkit-@{property}: ~'@{px1}px';
    -moz-@{property}: ~'@{px1}px';
    @{property}: ~'@{px1}px';
    -webkit-@{property}: ~'@{v1}rem';
    -moz-@{property}: ~'@{v1}rem';
    @{property}: ~'@{v1}rem';
}
/* call prefix mixin */
.demobox{
    .prefix(border-radius,5);
}
/* output */
.demobox{
    -webkit-border-radius: 50px;
    -moz-border-radius: 50px;
    border-radius: 50px;
    -webkit-border-radius: 5rem;
    -moz-border-radius: 5rem;
}

我可以调换警惕,以检查该值是否为0(以便我可以重置属性)或该值是否不是数字,例如输出带前缀的框大小.

I can swap the guards around to check that the value is either 0 (so i can reset a property) or if it is anything else than a number, such as outputting prefixed box sizing.

我要求提供not (isnumber(@v1))而不是(isstring(@v1))的保护措施的原因是,这样我就不必添加单引号了'border-box'值.

The reason I ask a guard of not (isnumber(@v1)), rather than (isstring(@v1)), is so I don't have to add single quotes the the value `'border-box'.

.prefix(@property, @v1) when (@v1 = 0), not (isnumber(@v1)) {
    -webkit-@{property}: ~'@{v1}';
    -moz-@{property}: ~'@{v1}';
    @{property}: ~'@{v1}';
}
/* call prefix mixin */
.demobox {
    .prefix(box-sizing, border-box);
}
/* output */
.demobox {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

推荐答案

如果将传递的参数视为数组,则可以简化操作(简化的隐含形式,代码段中的要求太多,无法包含在示例),小于1.7.x 或更高版本:

You can simplify things if you treat passed arguments as an array (a simplified impl., there're too many requirements in your snippet to cover in an example), Less 1.7.x or higher:

// usage

@root-font-size: 10;

div {
    .rem(border-radius, 1, margin, 2 auto, padding, 4 5 6 inherit);
}

// impl:

.rem-value_(@p, @v, @u) when (isnumber(@v)) {
    @{p}+_: (@v * @u);
}

.rem-value_(@p, @v, @u) when (default()) {
    @{p}+_: @v;
}

.rem(@args...) {
    .i; .i(@i: length(@args)) when (@i > 0) {
        .i((@i - 2));
        @property: extract(@args, (@i - 1));
        @values:   extract(@args,  @i);
        .j(@property, @values, (1px * @root-font-size));
        .j(~'@{property} ', @values, 1rem); // have to use ~'@{property} ' hack to isolate rem and px properties;
    }
    .j(@p, @v, @u, @j: length(@v)) when (@j > 0) {
        .j(@p, @v, @u, (@j - 1));
        .rem-value_(@p, extract(@v, @j), @u);
    }
} 

循环非常可怕,但是值输出mixin非常透明并且可以完全自定义(如果需要,您可以添加更多条件).

The loop is quite scary but the value output mixin is pretty transparent and fully customizable (you can add more conditions if you need to).

这篇关于更少-具有简写数字和/或字符串值的参数混合,具有rem和px后备的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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