减少混合输出

Combine Less mixin output

我正在寻找某种 extend 媒体查询,但我知道 extend 在这里不合适。

我有一个 mixin,它应该为每个创建 类 和媒体查询。不幸的是,我当前的 mixin 会像您期望的那样一个一个地创建它们,这会导致特异性问题。

My current mixins:

//create two classes and their media queries
._responsive-margins-top( 1, 6px );
._responsive-margins-top( 7, 60px );

//globals
@screen-xs: 480px;
@screen-sm: 768px;
@screen-md: 992px;
@screen-lg: 1200px;

//////////////////////////////////////| MARGINGS MIXIN
/*
 * MARGINS-TOP
 *
 * @param  @el         {string}  Element name appendix, We use numbers
 * @param  @value      {margin}  Space for this margin, We use px
 */
._responsive-margins-top( @el, @value ) {
    @xs: ~"top-margin@{el}-xs";
    @sm: ~"top-margin@{el}-sm";
    @md: ~"top-margin@{el}-md";
    @lg: ~"top-margin@{el}-lg";

    .@{xs},
    .@{sm},
    .@{md},
    .@{lg} {
        &:extend(.no-top-margin-xs all);
    }

    //////////////////////////////////////| XS
    .@{xs} {
        margin-top: @value;
    }

    //////////////////////////////////////|  SM
    @media (min-width: @screen-sm) {
        .@{sm} {
            margin-top: @value;
        }
    }

    //////////////////////////////////////|  MD
    @media (min-width: @screen-md) {
        .@{md} {
            margin-top: @value;
        }
    }

    //////////////////////////////////////|  LG
    @media (min-width: @screen-lg) {
        .@{lg} {
            margin-top: @value;
        }
    }
}

输出结果如下:

.top-margin1-xs {
    margin-top: 6px;
}
@media (min-width: 768px) {
    .top-margin1-sm {
        margin-top: 6px;
    }
}
@media (min-width: 992px) {
    .top-margin1-md {
        margin-top: 6px;
    }
}
@media (min-width: 1200px) {
    .top-margin1-lg {
        margin-top: 6px;
    }
}
.top-margin7-xs {
    margin-top: 60px;
}
@media (min-width: 768px) {
    .top-margin7-sm {
        margin-top: 60px;
    }
}
@media (min-width: 992px) {
    .top-margin7-md {
        margin-top: 60px;
    }
}
@media (min-width: 1200px) {
    .top-margin7-lg {
        margin-top: 60px;
    }
}

但是what I need is this:

.top-margin1-xs {
    margin-top: 6px;
}
.top-margin7-xs {
    margin-top: 60px;
}
@media (min-width: 768px) {
    .top-margin1-sm {
        margin-top: 6px;
    }
    .top-margin7-sm {
        margin-top: 60px;
    }
}
@media (min-width: 992px) {
    .top-margin1-md {
        margin-top: 6px;
    }
    .top-margin7-md {
        margin-top: 60px;
    }
}
@media (min-width: 1200px) {
    .top-margin1-lg {
        margin-top: 6px;
    }
    .top-margin7-lg {
        margin-top: 60px;
    }
}

感谢任何帮助。我怀疑这在 Less 中是不可能的?

选项 1:(如果您知道所有 classes)

这当然很复杂,但您可以使用 Less 循环来实现。关键部分是更改父 mixin 以接受多个参数(即 @el@value 对)并添加新的 mixin 以循环遍历参数并生成所需的输出。

._responsive-margins-top(1, 6px;7, 60px); /* send all el + value pairs as argument */

@screen-xs: 480px;
@screen-sm: 768px;
@screen-md: 992px;
@screen-lg: 1200px;

/* parent mixin supporting multiple args */
._responsive-margins-top(@args... ) { 

  .loop-args(length(@args), xs); /* generate classes for xs size */

  @media (min-width: @screen-sm) {
    /* call the loop within media query so that all classes are generated at one go */
    .loop-args(length(@args), sm); /* generate classes for sm size */
  }

  @media (min-width: @screen-md) {
    .loop-args(length(@args), md); /* generate classes for md size */
  }

  @media (min-width: @screen-lg) {
    .loop-args(length(@args), lg); /* generate classes for lg size */
  }
}

/* loop mixin for iterating through el + value pairs */
.loop-args(@index, @size) when (@index > 0){ 
  @arg: extract(@args, @index); /* extract each el + value pair based on iteration index */
  @el: extract(@arg, 1); /* extract 1st value in el + value pair*/
  @value: extract(@arg, 2); /* extract 2nd value in el + value pair */
  @sel: ~"top-margin@{el}-@{size}"; /* form selector by concatenating text + el + size */

  .@{sel} {margin-top: @value;}
  .loop-args(@index - 1, @size); /* call the next iteration */
}

选项2:(如果以后需要添加classes w/o编辑基础文件)

以下内容对我来说似乎有点过于冗长,但您可以将其用于您的用例。它涉及将规则写入父响应边距混合中的通用混合名称,然后在媒体查询下调用它们。

框架 (base.less):

 ._responsive-margins-top(1, 6px);
._responsive-margins-top(7, 60px);

@screen-xs: 480px;
@screen-sm: 768px;
@screen-md: 992px;
@screen-lg: 1200px;

._responsive-margins-top(@el, @value) {
  @xs: ~"top-margin@{el}-xs";
  @sm: ~"top-margin@{el}-sm";
  @md: ~"top-margin@{el}-md";
  @lg: ~"top-margin@{el}-lg";

  .xs() {
    .@{xs} {margin-top: @value;}
  }
  .sm() {
    .@{sm} {margin-top: @value;}
  }
  .md() {
    .@{md} {margin-top: @value;}
  }
  .lg() {
    .@{lg} {margin-top: @value;}
  }
}

& {.xs();}
@media (min-width: @screen-sm) {.sm();}
@media (min-width: @screen-md) {.md();}
@media (min-width: @screen-lg) {.lg();}

附加组件:(包含来自前端开发人员的额外 class(es) 的文件)

@import "base.less"; /* import the base */

._responsive-margins-top(9, 90px ); /* call the margins mixin */