amp amp - 2 months ago 17
CSS Question

Less mixin based on media query

I have two sprites:


  • One with icons for "normal" resolution;

  • One with icons for "high" resolution;



And I generated Less files with the following mixins:

For "normal sprite":

.sprite-icon_back() {
width: 25px;
height: 25px;
background: url('/Content/icons/mobile-icons-sprite.png') 0 0;
}

.sprite-icon_access() {
width: 48px;
height: 48px;
background: url('/Content/icons/mobile-icons-sprite.png') 0 -25px;
}


For "high sprite":

.sprite-icon_back() {
width: 100px;
height: 100px;
background: url('/Content/icons/HighRes/mobile-icons-sprite-high.png') 0 0;
}

.sprite-icon_access() {
width: 50px;
height: 50px;
background: url('/Content/icons/HighRes/mobile-icons-sprite-high.png') -100px 0;
}


Class names:

.m-icon-back {
.sprite-icon_back();
}

.m-icon-access{
.sprite-icon_access();
}


So, I would like to use high mixin when the following media query is detected:

@media only screen and (-webkit-min-device-pixel-ratio : 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio : 2) {
}


How could I change the
background-image
(png file) based on that media query? I don't really know if this is possible like that but I am open to new solutions/alternatives.

Answer

@media stuff is evaluated by browsers thus you can't use it as a condition for Less mixins. So the only way to handle this is to put a ruleset, a mixin or just a property of interest into the @media block of interest, e.g. for this use-case the simplest (but not necessary most optimal) solution would be something like this:

.sprite-icon_back() {

    // default properties:
    width:  25px;
    height: 25px;
    background: url('/Content/icons/mobile-icons-sprite.png') 0 0;

    @media only screen and (-webkit-min-device-pixel-ratio: 2), 
           only screen and (min--moz-device-pixel-ratio: 2),
           only screen and (min-device-pixel-ratio: 2) {
        // properties for the high resolution media:
        width:  100px;
        height: 100px;
        background: url('/Content/icons/HighRes/mobile-icons-sprite-high.png') 0 0;
    }
}

// usage:

.m-icon-back {
    .sprite-icon_back();
}

with the following CSS output:

.m-icon-back {
  width: 25px;
  height: 25px;
  background: url('/Content/icons/mobile-icons-sprite.png') 0 0;
}

@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) {
  .m-icon-back {
    width: 100px;
    height: 100px;
    background: url('/Content/icons/HighRes/mobile-icons-sprite-high.png') 0 0;
  }
}

And repeating @media code (when you'll need the same code for other mixins) is further to be optimized with variables and/or mixins. For example like this:

.high-res-media(@styles) {
    @media only screen and (min-device-pixel-ratio: 2) {
        @styles();
    }
}

.sprite-icon_back() {
    width:  25px;
    height: 25px;
    background: url('/Content/icons/mobile-icons-sprite.png') 0 0;
    .high-res-media({
        width:  100px;
        height: 100px;
        background: url('/Content/icons/HighRes/mobile-icons-sprite-high.png') 0 0;
    });
}

-

Also see an alternative method in this codepen suggested by @Harry in comments.

(I suppose there're ways to combine both methods to a certain degree to benefit from both but it's another story for a whole new book).