簡體   English   中英

較少-參數混合,帶有簡寫的數字和/或字符串值,帶有rem和px后備

[英]Less - parametric mixin with shorthand numeric and or string values, with rem and px fallback

使用Less,我嘗試輸出屬性的css組合速記值,同時根據作為變量傳遞多少值來檢測作為變量傳遞的值的類型。

  • 一個值@v1
  • 兩個值@v1@v2
  • 四個值@v1@v2@v3@v4

對於檢測到的每個變量,請檢查是否是大於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和守衛的數量將變得非常復雜。

選擇rems的原因是,與ems相比,它易於實現,並且避免了不得不記住必須將字體大小重置為每個父項的麻煩。 此外,對於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;
}

一種非常有用的情況是生成帶有回退的font-sizeline-height

/* 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嵌套在一起。

目前,如果我要傳遞多個值,則必須為每個必需的值調用.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 mixin版本,並使用一個gaurd來檢查是否聲明了@v2

這將觸發嵌套的.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共有三個版本,每個版本的防護措施都不同。

檢測@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';
}

檢測@v1@v2是否都大於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或不是數字

不需要'@ 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的數字

不需要'@ 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種可能性,因此很容易解決這個問題,但是使用3或4個值時,嵌套的mixin和防護的數量會擴展以涵蓋所有可能性。

作為其他示例。 我已經重新調整了.rem mixin的用途,以輸出pxrem ,並使用供應商前綴作為border-radius值,以確保它僅處理數字值,我.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非常透明並且可以完全自定義(如果需要,可以添加更多條件)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM