Css 无冗余的更少的媒体查询

Css 无冗余的更少的媒体查询,css,less,media-queries,Css,Less,Media Queries,我使用的是基于组件的CSS样式,因此我一直使用mixin来允许我使用媒体查询,而不会意外地编译数百个查询。这就是我为屏幕尺寸所做的: 主文件: .mq-medium() {} @import //other files @media only screen and (min-width: 600px) { .mq-medium; } 另一个文件: .mq-medium() { .banner { width: 50%; } } 这可以多次使用,并导致分组查询 问题 我

我使用的是基于组件的CSS样式,因此我一直使用mixin来允许我使用媒体查询,而不会意外地编译数百个查询。这就是我为屏幕尺寸所做的:

主文件:

.mq-medium() {}

@import //other files

@media only screen and (min-width: 600px) {
  .mq-medium;
}
另一个文件:

.mq-medium() {
  .banner {
    width: 50%;
  }
}
这可以多次使用,并导致分组查询

问题 我正在尝试对视网膜背景图像查询做同样的事情,但我很难弄清楚如何做到这一点。这是我的测试:

.mq-retina() { }

.background-image(@image){
  @filename:  ~`/(.*)\.(jpg|jpeg|png|gif)/.exec(@{image})[1]`;
  @extension: ~`/(.*)\.(jpg|jpeg|png|gif)/.exec(@{image})[2]`;
  background-image: ~`"url(@{filename}.@{extension})"`;
  .mq-retina() {
    & {
      background-image: ~`"url(@{filename}_2x.@{extension})"`;
      background-size: 100%;
    }
  }
}

.lol {
  .background-image("test.jpg");
}

@media only screen and (min-device-pixel-ratio: 1.5) { //shortened for this example
  .mq-retina;
}
但产出只是一个小问题

.lol {
  background-image: url(test.jpg);
}
我相信这与范围界定问题有关,但我不确定如何解决这个问题。如何添加到
.mq-retina()
mixin而不出现范围问题?

(有关此解决方案的上下文,请参阅上面的注释)。 我要说的是,不重复的媒体查询的代价永远是“重复其他内容”。即,它必须是媒体依赖的财产,如:

// ...................................
// usage:

.mq-default() {
    .banner {
        .background-image("test.jpg");
    }
}

.mq-retina() {
    .banner {
        .background-image("test.jpg");
    }
}

// ...................................
// impl:

.mq-default() {}
.mq-retina()  {}

& {
    .mq-default;

    .background-image(@image) {
        background-image: @image;
    }
}

@media (min-device-pixel-ratio: 1.5) {
    .mq-retina;

    .background-image(@image) {
        background-image: replace(@image, "\.", "_2x.");
        background-size: 100%;
    }
}
或媒体选择器本身,如:

// ...................................
// usage:

.background-image(banner, "test.jpg");

// ...................................
// impl:

.mq-retina() {}

@media (min-device-pixel-ratio: 1.5) {
    .mq-retina;
}

.background-image(@class, @image) {
    .@{class} {
        background-image: @image;
    }

    .mq-retina() {
        .@{class} {
            background-image: replace(@image, "\.", "_2x.");
            background-size: 100%;
        }
    }
}
--- 注意:对于这种简化的情况,也可以修改第一个示例以避免重复,例如:

// ...................................
// usage:

.mq-common() {
    .banner {
        .background-image("test.jpg");
    }
}

// ...................................
// impl:

.mq-default() {.mq-common}
.mq-retina()  {.mq-common}

& {
    .mq-default;

    .background-image(@image) {
        background-image: @image;
    }
}

@media (min-device-pixel-ratio: 1.5) {
    .mq-retina;

    .background-image(@image) {
        background-image: replace(@image, "\.", "_2x.");
        background-size: 100%;
    }
}
但这样一来,它实际上就变成了第二个示例的变体(在第二个示例中,更复杂的代码将导致在生成的CSS中重复选择符,因为您不想将所有属性都放入
.mq common
),更不用说整个过程也变得非常麻烦了

--- 最后,通过引入另一个间接层次,最终可以整合“一切”(在生成的CSS中),但源代码本身变得过于冗长,无法在实践中实际使用。(在本例中,我将把它分成两个文件,以获得更清晰的代码,但这并不是必需的-导入的文件可以编写为一个大的mixin):



好的,是的,当然
.mq retina
mixin在
中定义。背景图像在gobal范围内不可见(因此在媒体块中,就像您尝试调用它一样)。将媒体移动到mixin或
.lol
中,或者相反,将mixin移动到全局范围中。(另一个建议是减少内联javascript滥用,最后还有一个
replace
函数。至少不要做
~`“url(@{filename}.@{extension})`;
这真的很奇怪);我是从网上的某个地方得到的,只是在测试它是否有效。但这仍然不能解决我的问题——我的目标是有一个单一的媒体查询,并自动将每个背景图像定义添加到其中,而无需每次都专门编写。这可能是不可能的,但我想在写之前我会问一下。好吧,现在我想我知道你需要什么了——简言之,不,这是不可能的(或者更严格地说是可能的,但代价是代码非常冗长)。问题是,由于您需要在不同的媒体静默中使用不同的规则集,因此您必须以这种或那种方式重复这些规则集,而mixin在这里也无能为力,因为您无法创建一个将其外部内容从上到下暴露的mixin(因为mixin内容在被调用时而不是在其定义时被扩展,即
.background image(“test.jpg”);
inside
.lol
无法创建全局
.mq-retina()
.lol
inside)。
// ...................................
// styles.less:

.banner {
    .mq-default({
        color: red;
    });

    .mq-medium({
        color: green;
    });

    .mq-retina({
        color: blue;
    });

    .background-image("test.jpg");
    note: not "wrapped" properties will appear in every media block;
}

.background-image(@image) {
    .mq-default({
        background-image: @image;
    });

    .mq-retina({
        background-image: replace(@image, "\.", "_2x.");
        background-size: 100%;
    });
}
// ...................................
// main.less:

.media-import(default);

@media (min-width: 600px) {
    .media-import(medium);
}

@media (min-device-pixel-ratio: 1.5) {
    .media-import(retina);
}

.media-import(@device) {
    .mq-default(@styles) when (@device = default) {@styles();}
    .mq-medium(@styles)  when (@device = medium)  {@styles();}
    .mq-retina(@styles)  when (@device = retina)  {@styles();}
    @import (multiple) "styles.less";
}