johndoe johndoe - 4 months ago 23
CSS Question

Variable interpolation for a media query property in less - missing closing ")"

I'm trying to "translate" a sass function into a less function.
Here is the original SASS one :

@mixin bp($feature, $value) {
// Set global device param
$media: only screen;

// Media queries supported
@if $mq-support == true {

@media #{$media} and ($feature: $value) {
@content;
}

// Media queries not supported
} @else {

@if $feature == 'min-width' {
@if $value <= $mq-fixed-value {
@content;
}
} @else if $feature == 'max-width' {
@if $value >= $mq-fixed-value {
@content;
}
}

}
}


And here is the function I started to make in less as it seems every declaration can not be implemented the same as in sass :

.bp(@feature; @val) when (@mq-support = true) {
@med: ~"only screen";

@media @{med} and (@{feature}:@val) {
@content;
}
}


When I'm compiling this, I got the following error :

Missing closing ')' on line 15, column 34:
15 @media @{med} and (@{feature}:@val) {
16 @content;


So this error seems to come from the closing @{feature} closing bracket but following the documentation and several blog posts on the internet, it seems that since the 1.6.0 version of less, the css property interpolation is a feature that should work.

Does anybody have an idea of what could be wrong here ?
Is it actually possible to use a variable as a property in a media query ?

Maybe I'm doing it totally wrong but it seems the mixins guard feature in less does not work exactly the same as with SASS and the @if condition so the "translation" is a little bit different.

Thank you in advance

S├ębastien

Answer

Interpolation or using variables in media queries work slightly differently in Less.

  • First of all, you shouldn't use the normal interpolation syntax (@{med}). Instead it should just be @med.
  • Next the second condition should also be set to a variable and then appended to the media query just like the @med variable or it should be included as part of the @med variable itself. I've given a sample for both approaches below.
.bp(@feature; @val) when (@mq-support = true) {
  @med: ~"only screen and";
  @med2: ~"(@{feature}:@{val})";
  @media @med @med2{
    @content();
  }
}

or

.bp(@feature; @val) when (@mq-support = true) {
  @med: ~"only screen and (@{feature}:@{val})";
  @media @med {
    @content();
  }
}

Below is a sample conversion of that Sass code completely into its Less equivalent. Less does not support the @content like in Less, so it should be passed as a detached ruleset with the mixin call.

@mq-support: true;
@mq-fixed-value: 20px;

.bp(@feature; @val; @content) {
  & when (@mq-support = true) {
    @med: ~"only screen and (@{feature}:@{val})";
    @media @med {
      @content();
    }
  }
  & when not (@mq-support = true) {
    & when (@feature = min-width) {
      & when (@val <= @mq-fixed-value){
        @content();
      }
    }
    & when (@feature = max-width) {
      & when (@val >= @mq-fixed-value){
        @content();
      }
    }
  }
}

a{
  .bp(max-width, 100px, { color: red; } );
}
b{
  .bp(min-width, 10px, { color: blue; } );
}
Comments