Break out of scope

2019-05-24 11:29发布

问题:

Ideally, I would like to do this :

@w: 4px;

@media (max-width:900px) {
    @r: 3px; 
}
@media (min-width:900px) {
    @r: 5px; 
}

.myclass {
    border-radius: @w + @r;
}

This doesn't compile because @r isn't defined in the scope where I define .myclass. The obvious solutions are either to define .myclass inside the @media blocs or to copy the @media queries inside the definition of .myclass.

But as soon as you use @r in many classes, both solutions are messy and involve many duplications.

Is there a clean dry solution ?

回答1:

Just use a mixin, that calculates the property values according to the mediaquery. It is unnecessary to do this via import.

LESS:

@w: 4px;
.bordermixin(@w,@r) {
  .myclass{
    border-radius: @w + @r;
  }
}
@media (max-width:900px) {
    .bordermixin(@w,3px);
}
@media (min-width:900px) {
    .bordermixin(@w,5px);
}

CSS:

@media (max-width: 900px) {
  .myclass{
    border-radius: 7px;
  }
}
@media (min-width: 900px) {
  .myclass{
    border-radius: 9px;
  }
}


回答2:

I found a solution, based on @import, which lets me keep dry.

I make two files :

classes.less

@w: 4px;

.myclass {
    border-radius: @w + @r;
}

mediawidth.less

@media (max-width:900px) {
    @r: 3px; 
    @import "classes.less";
}
@media (min-width:900px) {
    @r: 5px; 
    @import "classes.less";
}

Generated CSS :

@media (max-width: 900px) {
  .myclass {
    border-radius: 7px;
  }
}
@media (min-width: 900px) {
  .myclass {
    border-radius: 9px;
  }
}

This way I don't have to repeat the many classes definition but only the import.


I accepted Martin's answer, which is much cleaner in the most common case when there are only a few numbers of variables to pass. My solution might be dryer and cleaner as soon as you have more variables and when your classes are defined in many files.