2015-02-11 127 views
2

我已經欠了下面的代碼:少CSS - 減少重複

我敢肯定,這可以進一步與某種混入的抽象出來的,但我一直在抓我的頭一會兒。我希望能夠傳入諸如@xs或@ xs-gutter之類的變量,並且可以使用該函數填充代碼。

任何想法?

.padding 
{ 
    &.bottom { 
     padding-bottom: @xs-gutter; 
    } 
    &.left { 
     padding-left: @xs-gutter; 
    } 
    &.right { 
     padding-right: @xs-gutter; 
    } 
    &.top { 
     padding-top: @xs-gutter; 
    } 

    @media @sm-screen { 
     &.bottom { 
      padding-bottom: @sm-gutter; 
     } 
     &.left { 
      padding-left: @sm-gutter; 
     } 
     &.right { 
      padding-right: @sm-gutter; 
     } 
     &.top { 
      padding-top: @sm-gutter; 
     } 
    } 
    @media @md-screen { 
     &.bottom { 
      padding-bottom: @md-gutter; 
     } 
     &.left { 
      padding-left: @md-gutter; 
     } 
     &.right { 
      padding-right: @md-gutter; 
     } 
     &.top { 
      padding-top: @md-gutter; 
     } 
    } 
    @media @lg-screen { 
     &.bottom { 
      padding-bottom: @lg-gutter; 
     } 
     &.left { 
      padding-left: @lg-gutter; 
     } 
     &.right { 
      padding-right: @lg-gutter; 
     } 
     &.top { 
      padding-top: @lg-gutter; 
     } 
    } 
} 

回答

2

您可以使用循環和數組列表來減少代碼中的重複。以下是如何實現簡化的示例片段。請參閱內聯註釋以瞭解代碼的作用。

注:我所做的實際填充代混入作爲一個單獨的一個這需要雙方作爲參數,因爲你可以重新使用的mixin來生成多個側面填充(通過將兩側和邊溝作爲參數),而不會爲它們生成媒體查詢。

@gutters: 4px, 6px, 8px, 10px; // the gutter sizes corresponding to each screen size 
@media-sizes: xs, sm, lg, md; // possible screen sizes 
@media-conditions: ~"(min-width: 100px)", ~"(min-width: 150px)", ~"(min-width: 200px)", ~"(min-width: 250px)"; // media condition for each screen size 

.media-generator(){ 
    .loop-sizes(length(@media-sizes)); // loop through all screen sizes 
    .loop-sizes(@screenIndex) when (@screenIndex > 0) { 
     & when (extract(@media-sizes, @screenIndex) = xs){ // since we need xs as default 
      .padding-per-side(extract(@gutters, 1); left; right; bottom; top); 
     } 
     & when not (extract(@media-sizes, @screenIndex) = xs){ // when screen size is not xs 
      @condition: extract(@media-conditions, @screenIndex); // extract media condition corresponding to screen type 
      @media @condition{ 
       .padding-per-side(extract(@gutters, @screenIndex); left; right; bottom; top); // call the mixin to generate padding for all sides 
      } 
     } 
     .loop-sizes(@screenIndex - 1); 
    } 
} 
.padding-per-side(@gutter; @sides...){ 
    .loop-sides(length(@sides)); 
    .loop-sides(@index) when (@index > 0){ 
     @side: extract(@sides, @index); 
     &[email protected]{side}{ 
      [email protected]{side}: @gutter; 
     } 
     .loop-sides(@index - 1); 
    } 
} 
.padding{ 
    .media-generator(); // generate padding for all sides and screens like in question 
} 

#demo{ // extra :) 
    .padding-per-side(10px; left;right); // generates 10px padding for left and right 
} 

的下面是上述的增強版本,其允許我們以產生具有僅用於某些側面媒體查詢的填充。下面的片段和上面的片段之間的區別在於,您可以在這裏爲媒體查詢版本單獨生成特定面的填充。

@gutters: 4px, 6px, 8px, 10px; 
@media-sizes: xs, sm, lg, md; 
@media-conditions: ~"(min-width: 100px)", ~"(min-width: 150px)", ~"(min-width: 200px)", ~"(min-width: 250px)"; 

.media-generator(@sides...){ 
    & when (length(@sides) = 0){ 
     .loop-sizes(length(@media-sizes)); 
     .loop-sizes(@screenIndex) when (@screenIndex > 0) { 
      & when (extract(@media-sizes, @screenIndex) = xs){ 
       .padding-per-side(extract(@gutters, 1); left; right; bottom; top); 
      } 
      & when not (extract(@media-sizes, @screenIndex) = xs){ 
       @condition: extract(@media-conditions, @screenIndex); 
       @media @condition{ 
        .padding-per-side(extract(@gutters, @screenIndex); left; right; bottom; top); 
       } 
      } 
      .loop-sizes(@screenIndex - 1); 
     } 
    } 
    & when not (length(@sides) = 0){ 
     .loop-sizes(length(@media-sizes)); 
     .loop-sizes(@screenIndex) when (@screenIndex > 0) { 
      & when (extract(@media-sizes, @screenIndex) = xs){ 
       .padding-per-side(extract(@gutters, 1); @sides); 
      } 
      & when not (extract(@media-sizes, @screenIndex) = xs){ 
       @condition: extract(@media-conditions, @screenIndex); 
       @media @condition{ 
        .padding-per-side(extract(@gutters, @screenIndex); @sides); 
       } 
      } 
      .loop-sizes(@screenIndex - 1); 
     } 
    } 
} 
.padding-per-side(@gutter; @sides...){ 
    .loop-sides(length(@sides)); 
    .loop-sides(@index) when (@index > 0){ 
     @side: extract(@sides, @index); 
     &[email protected]{side}{ 
      [email protected]{side}: @gutter; 
     } 
     .loop-sides(@index - 1); 
    } 
} 
.padding{ 
    .media-generator(left; right); // specify sides if needed else leave blank 
} 
+1

哇哈利 - 當然知道你的少 – dotnetnoob 2015-02-11 12:15:10

1

我親自闡述了3種可能的解決方案,從最簡單的一種開始,然後將其優化到第3種。最容易有更好的可讀性,最難使用雙嵌套LOOP

在這裏,我報告3個解決方案之間的「共同」的代碼(我決定到十個分量分開可能尺寸的定義,更加直觀):

@sm-screen:~"(min-width: 320px)"; 
@md-screen:~"(min-width: 720px)"; 
@lg-screen:~"(min-width: 1200px)"; 

@xs-gutter:20px; 
@sm-gutter:30px; 
@md-gutter:40px; 
@lg-gutter:50px; 

@property:padding; 
//@property:margin; 

注意@property可能是「margin」或「padding 「漠不關心,簡單地轉換評論。

爲了這個變量定義可以追加以下3點建議:


SOLUTION 1

這是最簡單的解決方案。其缺點是,它產生一個不同mediaquery爲每個規則,導致冗餘代碼:

.side(top, right, bottom, left); 

.side(@possible-values...) 
{ 
    .generate-property-loop(1, @possible-values); 
} 

.generate-property-loop(@var; @possible-values) when (@var <= length(@possible-values)) 
{ 
    //Let's extract values in @var position from list @possible-values 
    @direction: extract(@possible-values, @var); 

    [email protected]{property}[email protected]{direction} 
    { 
     @{property}[email protected]{direction}: @xs-gutter; 

     @media @sm-screen 
     { 
      @{property}[email protected]{direction}: @sm-gutter; 
     } 

     @media @md-screen 
     { 
      @{property}[email protected]{direction}: @md-gutter; 
     } 

     @media @lg-screen 
     { 
      @{property}[email protected]{direction}: @lg-gutter; 
     } 

    } 

    .generate-property-loop((@var + 1), @possible-values); 
} 

SOLUTION 2

一種可能的解決方案是移動mediaquery外LOOP但它仍然需要明確mediaquery定義:

.side(top, right, bottom, left); 

.side(@possible-values...) 
{ 
    .generate-property-loop(1, @possible-values, @xs-gutter); 

    @media @sm-screen 
    { 
    .generate-property-loop(1, @possible-values, @sm-gutter); 
    } 

    @media @md-screen 
    { 
    .generate-property-loop(1, @possible-values, @md-gutter); 
    } 

    @media @lg-screen 
    { 
    .generate-property-loop(1, @possible-values, @lg-gutter); 
    } 

} 

.generate-property-loop(@var, @possible-values, @gutter) when (@var <= length(@possible-values)) 
{ 
    //Let's extract values in @var position from list @possible-values 
    @direction: extract(@possible-values, @var); 

    [email protected]{property} 
    { 
    &[email protected]{direction} 
    { 
     @{property}[email protected]{direction}: @gutter; 
    } 
    } 

    .generate-property-loop((@var + 1), @possible-values, @gutter); 
} 

SOLUTION 3

隨着雙嵌套循環,可以實現完全的靈活性,簡單地通過「方向」和「scren尺寸」作爲參數,但在較小的可讀性的成本:

.side(top, right, bottom, left); 

.side(@possible-values...) 
{ 
    .generate-property-loop(1, @possible-values, @xs-gutter); 

    .mediaquery-loop(sm,md,lg); 
} 

.mediaquery-loop(@possible-screens...) 
{ 
    .generate-mediaquery-loop(1, @possible-screens); 
} 

.generate-property-loop(@var, @possible-values, @gutter) when (@var <= length(@possible-values)) 
{ 
    @direction: extract(@possible-values, @var); 

    [email protected]{property} 
    { 
    &[email protected]{direction} 
    { 
     @{property}[email protected]{direction}: @gutter; 
    } 
    } 

    .generate-property-loop((@var + 1), @possible-values, @gutter); 
} 

.generate-mediaquery-loop(@var, @possible-sizes) when (@var <= length(@possible-screens)) 
{ 
    @sizes: extract(@possible-sizes, @var); 

    @screen-size: ~"@{sizes}-screen"; 
    @gutter-size: ~"@{sizes}-gutter"; 

    @media @@screen-size 
    { 
    .generate-property-loop(1, @possible-values, @@gutter-size); 
    } 

    .generate-mediaquery-loop((@var + 1), @possible-screens); 
} 
+1

好一個夥計.. – Harry 2015-02-12 06:28:21