【问题标题】:Combine Less mixin output组合更少的mixin输出
【发布时间】:2016-08-08 19:53:13
【问题描述】:

我正在寻找某种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 中可能是不可能的?

【问题讨论】:

    标签: less mixins less-mixins


    【解决方案1】:

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

    这确实很复杂,但您可以使用 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:(如果您以后需要在不编辑基础文件的情况下添加类)

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

    框架(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();}
    

    附加组件:(带有来自前端开发人员的额外类的文件)

    @import "base.less"; /* import the base */
    
    ._responsive-margins-top(9, 90px ); /* call the margins mixin */
    

    【讨论】:

    • 这看起来不错,但只有一个预订。我需要能够在以后将 ._responsive-margins-top 添加到代码中,然后添加另一个我还没有预见到的类。您的解决方案假设我已经知道所有这些。
    • @Dominik:稍后当您需要另一个类时,您仍然需要编辑代码,因此无需再次调用 mixin,只需编辑之前的调用即可。将调用放在父 mixin 和文件底部,以便您可以在必要时对其进行编辑。除此之外,我认为没有更少的解决方案:(
    • 萨克斯·哈利。我们正在为公司编写一个框架,并阻止我们的前端编辑源代码。我必须查看循环,如果我不能让它工作,我会接受你的回答,因为它确实回答了我的问题。 (只是不是我的用例)谢谢!
    • 这正是我所希望的。向你的好先生致敬!
    • 第二个sn-p(顺便说一句)可以简化为this
    猜你喜欢
    • 2021-12-05
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多