Css 少参数混入与速记数字和或字符串值,rem和px回退

Css 少参数混入与速记数字和或字符串值,rem和px回退,css,less,mixins,Css,Less,Mixins,使用Less,我尝试输出属性的css组合速记值,同时根据作为变量传递的值的数量检测作为变量传递的值的类型 一个值@v1 两个值@v1和@v2 四个值@v1,@v2,@v3和@v4 对于检测到的每个变量,检查is是否是大于0的数字,如果是,则为每个属性值输出rem和px值,因此符合的css可能类似于: .demobox{ border-width: 10px 20px 0 0; border-width: 1rem 2rem 0 0; padding: 0 50px; padd

使用Less,我尝试输出属性的css组合速记值,同时根据作为变量传递的值的数量检测作为变量传递的值的类型

  • 一个值
    @v1
  • 两个值
    @v1
    @v2
  • 四个值
    @v1
    @v2
    @v3
    @v4
对于检测到的每个变量,检查is是否是大于0的数字,如果是,则为每个属性值输出rem和px值,因此符合的css可能类似于:

.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和guard的数量就会变得非常复杂

选择rems的原因是,与ems相比,rems易于实现,并且避免了记着必须为每个父项重置字体大小的头痛。此外,对于rems和ems,较旧的设备支持问题是可比较的,因此我认为px回退效果最好。

以下是我目前的情况,但我会尽可能地解释我的工作原理

有没有办法简化这个过程?我是新手。我想有一种更简单的检测方法

  • 声明值的数目
  • 每个值的类型
  • 如果数字值需要rem和px值,则返回
谢谢

我有一个参数mixin,它输出
rem
值和
px
回退值以及声明的属性

@root-font-size: 10;

.rem(@property, @v1) when (@v1 = @v1){
    @px1: @v1 * @root-font-size;
    @{property}:  ~'@{px1}px';
    @{property}: ~'@{v1}rem';
}
这对于快速生成一组css属性的rem和像素回退非常有用

/* call the rem mixin */
.demobox {
    .rem(margin, 2);
}
/* output */
.demobox {
    margin: 20px;
    margin: 2rem;
}
一个非常有用的例子是使用回退生成
字体大小
行高

/* 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
混合嵌套在另一个混合中

目前,如果我想传递多个值,我必须为每个所需值调用
.rem
mixin:

/* 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

.demobox {
    .rem(margin, 2, 1);
}
正如我前面提到的,这对于两个值来说并不困难,并且要检查值类型是什么。这需要一个版本的
.rem
混合,并应用一个gaurd来检查
@v2
是否已声明

这将触发嵌套的
.rem two
混合

// when there are two values
.rem(@property, @v1, @v2) when (@v1 = @v1) and (@v2 = @v2){
    .rem-two(@property, @v1, @v2);
}
有三个版本的
.rem two
,每个版本的防护装置都不同

检测
@v1
@v2
是否都是大于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';
}
.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
@v2
是否都是大于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';
}
.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值或不是数字

不需要“@px2”像素回退,因此已删除

检测
@v1
是否都是值0或不是数字,
@v2
是否都是大于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';
}
.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;
}
不需要“@px1”像素回退,因此已删除

由于此两值版本的mixin只有3种可能,因此很容易解决此问题,但如果有3或4个值,嵌套的mixin和保护的数量将扩展到所有可能

作为补充例子。 我重新调整了
.rem
混入的用途,以输出
px
rem
边界半径
值,并带有供应商前缀,以确保它只处理数值,我有防护装置检查传递的值是否大于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(以便我可以重置属性),或者它是否不是数字,例如输出带前缀的框大小

我之所以要求守卫使用
not(isnumber(@v1))
,而不是
(isstring(@v1))
,是因为我不必在值“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或更高:

// 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非常透明且完全可自定义(如果需要,您可以添加更多条件)。

我个人认为这一切的主要问题是您试图使其“过于智能”。也就是说,试图覆盖所有可能的用途,并对相当可疑的先发制人优化感到烦恼。通常情况下,它永远不值得(太复杂,无法实现,最终仍无法“覆盖所有内容”)。例如,说到抑制
margin:0
margin:0
等:这些都是有效的CSS值,表示零margin,而不是
“无margin值”
,因此不输出
margin:0
只需不调用
.rem(margin,0)
,而不是将这种情况编码到
.rem()
本身。而且,一如既往,对于供应商前缀,请使用专用工具(例如)。最终CSS优化也是如此(例如,
margin:0px
->
margin:0
->等)。