Does LESS have something comparable to the #content directive in Sass? - less

I tried to convert a more "advance" mixin from SASS to LESS but unsuccessful.
Here is the mixin:
.breakpoint(#point) {
#if #point == really big{
#media (max-width: 80em) { #content; }
}
#if #point == mid {
#media (max-width: 60em) { #content; }
}
#if #point == small {
#media (max-width: 42em) { #content; }
}
}
and another one, I didn't touch this one:
#mixin keyframes( $animationName )
{
#-webkit-keyframes $animationName {
#content;
}
#-moz-keyframes $animationName {
#content;
}
#-o-keyframes $animationName {
#content;
}
#keyframes $animationName {
#content;
}
}

update
I did not check the sample code provide by #Harry in the comments, before answering this question. This sample code provide a good a clean way to solve your question too. Please also see: http://codepen.io/hari_shanx/pen/ayIej
First notice that Less do not support if / else constructs (alhought mixins libraries such as https://github.com/pixelass/more-or-less adds .if() (if - then - [else]) ), but uses guards to create conditional mixins, also see: http://lesscss.org/features/#mixin-guards-feature
or alternatively consider http://lesscss.org/features/#mixins-parametric-feature-pattern-matching
Your mixins also use the #content; which you call the #content directive, i think you should compare this with "Passing Rulesets to Mixins", see: http://lesscss.org/features/#detached-rulesets-feature.
Your first mixin using pattern-matching:
.breakpoint(reallybig;#content)
{
#media (max-width: 80em) { #content(); }
}
.breakpoint(mid;#ruleset)
{
#media (max-width: 80em) { #content(); }
}
example caller:
.breakpoint(reallybig; {p{color:red;}});
Your first mixins leveraging guards:
.breakpoint(#size;#content) when (#size = 'really big')
{
#media (max-width: 80em) { #content(); }
}
.breakpoint(mid;#ruleset) when (default())
{
#media (max-width: 80em) { #content(); }
}
.breakpoint('really big'; {p{color:red;}});
And your second mixin:
.keyframes(#animationName;#animation)
{
#-webkit-keyframes #animationName {
#animation();
}
#-moz-keyframes #animationName {
#animation();
}
#-o-keyframes #animationName {
#animation();
}
#keyframes #animationName {
#animation();
}
}
#animation: {0% {
left: 0;
transform: translate(10px, 20px);
}
100% {
left: 100%;
transform: translate(100px, 200px);
}};
.keyframes(test;#animation);

Related

Media query and if else statement in LESS

In Sass I hadle responsive like this. But how can I write this in LESS. I find the way that they use when but I still cannot write it correctly in LESS
html {
/*font-size: 10px;*/
font-size: 62.5%; //1 rem = 10px; 10px/16px = 62.5%
#include respond(tab-land) {
font-size: 56.25%; //1 rem = 9px; 9px/16px = 56.25%
}
#include respond(tab-port) {
font-size: 50%; //1 rem = 8px; 8px/16px = 50%
}
#include respond(big-desktop) {
font-size: 75%; //1 rem = 12px; 10px/16px = 62.5%
}
}
#mixin respond($breakpoint) {
#if $breakpoint == phone {
#media (max-width: 37.5em) {#content} //600px
}
#if $breakpoint == tab-port {
#media (max-width: 56.25em) {#content} //900px
}
#if $breakpoint == tab-land {
#media (max-width: 75em) {#content} //1200px
}
#if $breakpoint == big-desktop {
#media (min-width: 112.5em) {#content} //1800
}
}
You can use css guards.
Less mixin:
.respond(#size, #content) {
& when(#size = phone) {
#media (max-width: 37.5em) { #content() }
}
}
Usage:
.a {
.respond(phone, {
color: red;
});
.respond(unknown, {
color: green;
});
}
Compiles to:
#media (max-width: 37.5em) {
.a {
color: red;
}
}
Codepen demo.

Change mixin variable based on media (or some other condition)

Say I have a complex mixin function. Something like
.MyMixin(#Count, #ManyOtherVars)
{
.Item
{
width: calc( 100% / #Count);
}
//lot's of other rules not affected by #Count
}
And then I want to call this mixin with different values for different media
e.g.
.SomeClass
{
#media screen (max-width: 1000px)
{
.MyMixin(5, 1);
}
#media screen (min-width: 1000px)
{
.MyMixin(10, 1);
}
}
This works fine, except the generated css duplicates all the stuff which has not changed
#media screen (max-width: 1000px)
{
.SomeClass .Item
{
width: calc( 100% / 5 );
}
.SomeClass
{
/* lot's of other rules not affected by #Count */
}
}
#media screen (min-width: 1000px)
{
.SomeClass .Item
{
width: calc( 100% / 10 );
}
.SomeClass
{
/* lot's of other rules not affected by #Count */
}
}
Which, needless to say, is quite wasteful when only one thing changed.
Are there any workarounds to produce a leaner output that don't require the calling class to know something about what the mixin does, or for the mixin to know about media rules?
I thought maybe a detached rule-set could help, but given variables are not exported from those I'm not sure how it would.
Desired output:
#media screen (max-width: 1000px)
{
.SomeClass .Item
{
width: calc( 100% / 5 );
}
}
#media screen (min-width: 1000px)
{
.SomeClass .Item
{
width: calc( 100% / 10 );
}
}
.SomeClass
{
/* lot's of other rules not affected by #Count */
}
Remove static styles from your mixin and place them directly to SomeClass selector.
.SomeClass {
// Lot's of other rules not affected by #Count
#media screen (max-width: 1000px) {
.MyMixin(5, 1);
}
#media screen (min-width: 1000px) {
.MyMixin(10, 1);
}
}
Better solution:
.MyMixin(#Count, #ManyOtherVars) {
width: calc( 100% / #Count);
}
.SomeClass {
// Lot's of other rules not affected by #Count
.Item {
#media screen (max-width: 1000px) {
.MyMixin(5, 1);
}
#media screen (min-width: 1000px) {
.MyMixin(10, 1);
}
}
}
Now mixin does only one thing. It's simple and reusable.

Error when minifying CSS with #keyframes

I'm using the default bundling and minification in MVC 4.
One of our stylesheets starts with this bit of CSS:
#media (max-width: 979px) {
#keyframes sidebarSlideInRight {
from { right: -220px }
to { right: 0 }
}
#-webkit-keyframes sidebarSlideInRight {
from { right: -220px }
to { right: 0 }
}
}
The minification fails with this error: run-time error CSS1019: Unexpected token, found '}' and it points to the first character on line 13 (that's the very last } in the snippet above).
I'm not overly familiar with CSS in general and I was wondering:
Is that valid CSS? It fails validation at
https://jigsaw.w3.org/css-validator/validator
What changes are needed to get the file minified? There are about 300 lines in the file so I would really like to get it minified if possible.
#keyframes declarations must be outside media queries.
#keyframes sidebarSlideInRight {
from { right: -220px }
to { right: 0 }
}
And then you use them in the media query like this:
#media (max-width: 979px) {
.some-class {
animation: sidebarSlideInRight 1s;
}
}
To add to #Flower's answer:
If you need the animation to work differently based on a media query, make multiple keyframes with different names. Then in the media query use the animation-name for the needed keyframe.
#keyframes sidebarSlideInRight-1 {
from { right: -220px }
to { right: 0 }
}
#keyframes sidebarSlideInRight-2 {
from { right: -250px }
to { right: 50 }
}
#media (max-width: 768px) {
.some-class {
animation: sidebarSlideInRight-1 1s;
}
}
#media (max-width: 979px) {
.some-class {
animation: sidebarSlideInRight-2 1s;
}
}
Like #Flower said, just make sure the keyframes are not in the media query.

Set "min-width" or "max-width" in a media query passing a parameter to a mixin

I would like to make dynamic MIN/MAX suffix in properties defined in a Less MediaQuery.
I wrote this code but it does not compile:
#screen-md: 800px;
.MEDIAQUERY(#min-max, #size)
{
#media screen and (#{min-max}-width: #size)
{
#{min-max}-width:100px;
}
}
header
{
background-color: blue;
.MEDIAQUERY ( #min-max: max, #size: #screen-md );
}
While #{min-max}-width:100px; is a correct syntax, equivalent applied in Mediaquery definition is not allowed, but I need to set sometime "max-width" value, and others "min-width" value in my media queries. How to obtain this?
Option 1: (Using a variable and interpolation)
You can do it like below
.MEDIAQUERY(#min-max, #size) {
#mediaQuery: ~"screen and (#{min-max}-width: #{size})";
#media #mediaQuery {
#{min-max}-width:100px;
}
}
Option 2: (Using Guards)
You can use guards in the mixin like below to check what was the value that was passed for the #min-max parameter and then output the appropriate CSS based on it.
.MEDIAQUERY(#min-max, #size){
& when (#min-max = min) {
#media screen and (min-width: #size) {
min-width:100px;
}
}
& when (#min-max = max) {
#media screen and (max-width: #size) {
max-width:100px;
}
}
}
When the above mixin is called like below (with either of the options mentioned above):
header
{
background-color: blue;
.MEDIAQUERY ( #min-max: max, #size: #screen-md );
}
div{
background-color: red;
.MEDIAQUERY ( #min-max: min, #size: #screen-md );
}
it would compile into the below CSS:
header {
background-color: blue;
}
#media screen and (max-width: 800px) {
header {
max-width: 100px;
}
}
div {
background-color: red;
}
#media screen and (min-width: 800px) {
div {
min-width: 100px;
}
}

How to declare same style for #media and descendant selector?

I need to define same style for elements under a media query and descendant by another class.
Perfect solution in LESS could be the following [pseudo-code]:
.foo
{
color:red;
.example &,
#media (min-width:800px)
{
color:blue;
}
}
that should be desirable that would be compiled into:
.foo {
color: red;
}
.example .foo {
color: blue;
}
#media (min-width: 800px) {
.foo {
color: blue;
}
}
THIS SYNTAX IS INCORRECT but, do you have some suggestion to solve my problem?
Nope, selectors and #media queries are too different language entities (despite having similar {} syntax) so you can't combine those with comma like in your example.
So to get it DRY (assuming that shared style has more than one property of course) you'll need a mixin (or sort of), for example:
.foo {
color: red;
.somename() {
color: blue;
}
.example & {.somename}
#media (min-width: 800px) {.somename}
}
Also see Passing Rulesets to Mixins examples (if you need even more generic solution).
Thanks to #seven-phases-max suggestion, I finally found a possible solution using Detached Ruleset:
#screen-xs: 480px;
#screen-sm: 769px;
#screen-md: 992px;
#screen-lg: 1200px;
.MEDIAQUERY(#only-media, #min-max, #size, #RULES)
{
#screen-width:~"#{screen-#{size}}";
#mediaQuery: ~"screen and (#{min-max}-width: #{screen-width})";
#media #mediaQuery { #RULES(); }
& when (#only-media = false) {
.#{size} & { #RULES(); }
}
}
.foo_media-and-class
{
color:red;
.MEDIAQUERY(#only-media:false, #min-max:max, #size:md,
{
color:blue;
}
);
.MEDIAQUERY(#only-media:false, #min-max:min, #size:lg,
{
color:yellow;
}
);
}
.foo_only-media
{
color:red;
.MEDIAQUERY(#only-media:true, #min-max:max, #size:md,
{
color:blue;
}
);
.MEDIAQUERY(#only-media:true, #min-max:min, #size:lg,
{
color:yellow;
}
);
}
This solution go beyond and offer other options:
Possibility to set a custom value of screen width for media query,
Pass MIN/MAX value of property used in media query (Try to pass "max" instead of "min" calling .MEDIAQUERY mixin)
Toggling generation of simple media query or media query + descendant selector, through #only-media boolean.
I think your comma might be causing the error.
.foo {
color:red;
.example & {
color:blue;
#media (min-width:800px) {
color:blue;
}
}
}
This is proper syntax to output the following:
.foo {
color: red;
}
.example .foo {
color:blue;
}
#media (min-width:800px) {
.example .foo {
color:blue;
}
}