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

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

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; } );
}

Related

.less mixin guard won't accept #media in expression

I'm trying to create a mixin guard, as seen on http://lesscss.org/features/ , where they do mixin(#a) when (#media = mobile) { ... }
However, when I do mixin() when (#media = mobile) { ... } or mixin(#a) when (#media = mobile) { ... }, less is saying it's expecting a ) at #media's # sign and that it's expecting an "expression" at the closing ). Conversely, if I do mixin(#a) when (#a = 5) { ... }, less is happy.
Why is this, and how can I get #media to work in my mixin's guard?

Issue with scss syntax after conversion from less

My task is to convert all less to scss files . I used npm dependency "less-scss-convertor" for the same .
But when i am creating scss files i am getting these three errors repeatedly .
1st scenario -
In my common.scss i have defined
$S: "all and (max-width: 767px)";
in some other scss file i am using -
#media $S {
.test-class {
font-size: 8px;
}
}
error1 - "media query expression must begin with '('"
2nd scenario -
In color.scss -
#mixin test-class("black", 1, 2);
#mixin generate-color-class($color, $arg1,
$arg2) when ($arg2 > 0) {
.${color}-${arg1} {
color: ~"${${color}-${arg1}}";
}
#include generate-color-class($color,
($arg1 + 1), ($arg2 - 1));
}
error 2 - Invalid CSS after "...te-color-class(": expected ")", was '"black", 1, 2);'
3rd scenario -
#mixin vertical-translate($percent) {
-ms-transform: translateY($percent);
-webkit-transform: translateY($percent);
transform: translateY($percent);
}
.Headerclass {
#include vertical-translate (-50%);
}
error 3 - no mixin named vertical-translate
Any pointers where i am going wrong ?
1st scenario
You need to use the interpolation syntax of Sass: #{$var}
About Interpolation
#media #{$S} {
.test-class {
font-size: 8px;
}
}
2nd scenario
See how mixins work with Sass. It's very different from Less.
About Mixins
3rd scenario
It works for me. Maybe you should remove the white space.
vertical-translate(-50%);

Grouped .className + media query?

Due an effect that splits the page and lets resize one of the containers. I have to add more styles for the responsive, So I add to this resizable container a class representing my current breakpoint (xs,sm,md,lg)
Like this
if ( ui.position.left <= 480 ) { /* It represent it's width, I am using this as the drag function of draggable */
clase = 'xs';
} else if ( ui.position.left <= 768 ) {
clase = 'sm';
} else if ( ui.position.left <= 992 ) {
clase = 'md';
} else {
clase = 'lg';
}
$('.element').removeClass('xs sm md lg').addClass(clase);
for example:
#media (max-width: 320px)
h2 {
font-size:12px;
}
}
and I now have to add:
.xs h2 {
font-size:12px
}
Is there any way not to have to duplicate the styles? (I have several blocks)
Something like this that I won't work
.xs, #media (max-width:320px) {
h2 {
font-size: 12px
}
}
You can use postcss and plugin https://github.com/hail2u/node-css-mqpacker. This easy and work fine. You can use postcss with SCSS.
When using media queries, you usually have a global default, and then you override the default in the query, if a certain predicate is true (e.g. window with is less than 320px).
In your example, you would like to use the same value as the global default and the overridden value in the media query. IMHO this makes no sense whatsoever.

Print media queries using less.css loop

I'm using less.css as css preprocessor, and i was wonder if it is possible to print out media queries using less.css loops.
I've tried a very basic example loop:
#iterations: 30;
.loopingClass (#index) when (#index > 0) {
(~".myclass_#{index}") {
font-size: -#index px;
}
.loopingClass(#index - 1);
}
.loopingClass (0) {}
.loopingClass (#iterations);
but this will end up creating a class.
According to this example:
http://codepen.io/ericrasch/pen/HzoEx?editors=110
we can create media queries in less using this syntax:
#mobile: ~"only screen and (max-width: 529px)";
body {
#media #mobile {
background: orange;
content: "mobile";
}
}
But, as you can see, the media query value is a variable and not a class. So my question is, can i use less.css loop to print out media queries value as variable instead of classes? Or there's any workaround for this issue?
Thanks in advance

sass using variable as mixin data

I'm using grid from csswizardry and wanting to create breakpoints as variables...
If defined as standard "strings":
$breakpoints: (
'palm' '(max-width: 480px)'
)!default;
But when I change it to:
$palmmaxwidth: 480px;
$breakpoints: (
'palm' '(max-width: $palmmaxwidth)'
)!default;
it will not compile correctly within the mixin:
#mixin grid-media-query($media-query){
$breakpoint-found: false;
#each $breakpoint in $breakpoints{
$name: nth($breakpoint, 1);
$declaration: nth($breakpoint, 2);
#if $media-query == $name and $declaration{
$breakpoint-found: true;
#media only screen and #{$declaration}{
#content;
}
}
}
#if $breakpoint-found == false{
#warn "Breakpoint ‘#{$media-query}’ does not exist"
}
}
The error is Invalid CSS after "...nd (max-width: ": expected expression (e.g. 1px, bold), was "$palmmaxwidth)"
What am I missing?
The solution is quite simple after trying every possible combination:
$breakpoints: (
'palm' '(max-width: '+$palmmaxwidth+')'
)!default;

Resources