2015-02-11 126 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