Media query and if else statement in LESS - 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.

Related

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

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

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

Is it possible to nest variables within variables in SASS?

I have a mixin that accepts an argument that I want to pass into a variable.
#mixin my_mixin($arg) {
background-color: $state-#{$arg}-text;
}
Interpolation of variable names is currently not possible in SASS. Here is the issue that discusses.
However, you may use interpolation of placeholders:
%my-dark-styles {
background-color: #000;
}
%my-white-styles {
background-color: #FFF;
}
#mixin my_mixin($arg) {
#extend %my-#{$arg}-styles;
}
.header {
#include my_mixin("dark");
}
.footer {
#include my_mixin("white");
}
This compiles to:
.header {
background-color: #000;
}
.footer {
background-color: #FFF;
}
Since Sass 3.3 you can use maps also https://sass-lang.com/blog/sass-33-is-released
Here is an example:
$state-light-text : #FFFFFF;
$state-dark-text : #000000;
$color-map: ( //create a array to support the two colors light and dark
light: $state-light-text,
dark: $state-dark-text
);
#each $color-key, $color-var in $color-map {
.myclass--#{$color-key} { //will generate .myclass--light .myclass--dark
background-color: $color-var; // equal $state-light-text or $state-dark-text
}
}
It will compile into:
.myclass--light {
background-color: #FFFFFF;
}
.myclass--dark {
background-color: #000000;
}

Bootstrap, pull-left for small devices

I'm building a site in Bootstrap 3.
Is there anyway to make a element use the class pull-left on smaller devices and use pull-right on larger ones?
Something like: pull-left-sm pull-right-lg.
I've managed to do it with jquery, catching the resize of the window. Is there any other way? Pref without duplicating the code in a hidden-x pull-left. Or is it considered more ok to duplicate code/content now when going responsive?
Just add this to your SASS file:
#media (max-width: $screen-xs-max) {
.pull-xs-left {
float: left;
}
.pull-xs-right {
float: right;
}
}
#media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
.pull-sm-left {
float: left;
}
.pull-sm-right {
float: right;
}
}
#media (min-width: $screen-md-min) and (max-width: $screen-md-max) {
.pull-md-left {
float: left;
}
.pull-md-right {
float: right;
}
}
#media (min-width: $screen-lg-min) {
.pull-lg-left {
float: left;
}
.pull-lg-right {
float: right;
}
}
Insert actual px values for $screen-* if you use plain CSS of course.
HTML:
<div class="pull-md-left pull-lg-left">
this div is only floated on screen-md and screen-lg
</div>
You can use CSS Media Queries
basic usage will be like this; if you want to float left below devices of width 500px, then
#media (max-width: 500px) {
.your_class {
float: left;
}
}
#media (min-width: 501px) {
.your_class {
float: right;
}
}
There is no need to create your own class with media queries. Bootstrap 3 already has float ordering for media breakpoints under Column Ordering.
The syntax for the class is col-<#grid-size>-(push|pull)-<#cols> where <#grid-size> is xs, sm, md or lg and <#cols> is how far you want the column to move for that grid size. Push or pull is left or right of course.
I use it all the time so I know it works well.
Possibly you can use column ordering.
<div class="row">
<div class="col-md-9 col-md-push-3">.col-md-9 .col-md-push-3</div>
<div class="col-md-3 col-md-pull-9">.col-md-3 .col-md-pull-9</div>
</div>
Looks like floating columns will be getting added to version 4 by like #Alex has done - https://github.com/twbs/bootstrap/issues/13690
Yes. Create your own style. I don’t know what element you’re trying to float left/right, but create an application.css file and create a CSS class for it:
/* default, mobile-first styles */
.logo {
float: left;
}
/* tablets and upwards */
#media (min-width: 768px) {
.logo {
float: right;
}
}
Don’t be afraid to write custom CSS. Bootstrap is meant to be exactly that: a bootstrap, a starter point.
This is what i am using . change #screen-xs-max for other sizes
/* Pull left in mobile resolutions */
#media (max-width: #screen-xs-max) {
.pull-xs-right {
float: right !important;
}
.pull-xs-left {
float: left !important;
}
.radio-inline.pull-xs-left + .radio-inline.pull-xs-left ,
.checkbox-inline.pull-xs-left + .checkbox-inline.pull-xs-left {
margin-left: 0;
}
.radio-inline.pull-xs-left, .checkbox-inline.pull-xs-left{
margin-right: 10px;
}
}
LESS version of #Alex's answer
#media (max-width: #screen-xs-max) {
.pull-xs-left {
.pull-left();
}
.pull-xs-right {
.pull-right();
}
}
#media (min-width: #screen-sm-min) and (max-width: #screen-sm-max) {
.pull-sm-left {
.pull-left();
}
.pull-sm-right {
.pull-right();
}
}
#media (min-width: #screen-md-min) and (max-width: #screen-md-max) {
.pull-md-left {
.pull-left();
}
.pull-md-right {
.pull-right();
}
}
#media (min-width: #screen-lg-min) {
.pull-lg-left {
.pull-left();
}
.pull-lg-right {
.pull-right();
}
}

Splitting up a list of variables in Sass

In Sass is there a way to split up a list of variables / classes with hyphens?
It's a fuzzy question title so it's probably best I show what I'm trying to achieve.
In the below example I'm trying to create some utility classes that I can apply to HTML elements to help with vertical rhythm.
For example I may want to give an element a small margin that is consistent with my vertical rhythm strategy and so I'll add the class .m-t-s (which stands for margin-top-small).
I then want to output versions of those utility classes against for each media query I have for fine grain control e.g. I may want a class .m-t-s-768 which will add a small top margin when there is a minimum viewport width of 768px.
I have achieved this below, but it is a very long-winded and repetitive way of doing it. Can anyone suggest a more concise way?
Variables
––––––––––
$mediaQueries-px:
640,
768,
1024
;
$s: 20px; /* FYI I've simplified these examples for the sake of demonstration, normally I use something like ($baseLineHeight / 1.5) + rem */
$m: 50px;
$l: 60px;
Creating the classes
–––––––––––––––––––––
.m-t-s {
margin-top: $s;
}
/* Create versions for each defined media query */
#each $mediaQuery in $mediaQueries-px {
#media screen and (min-width: ($mediaQuery / 16px)) {
.m-t-s-#{$mediaQuery} {
margin-top: $s;
}
}
}
.m-t-m {
margin-top: $m;
}
/* Create versions for each defined media query */
#each $mediaQuery in $mediaQueries-px {
#media screen and (min-width: ($mediaQuery / 16px)) {
.m-t-m-#{$mediaQuery} {
margin-top: $m;
}
}
}
This repeats for .m-t-l too (margin top large), and then it continues for padding classes (e.g. .p-t-s and so on), so it gets to be a pretty long list of utility classes.
To programatically generate that output, you need another list and an inner loop:
$mediaQueries-px:
640,
768,
1024
;
$s: 20px;
$m: 50px;
$l: 60px;
$sizes: s $s, m $m, l $l;
#each $size in $sizes {
.m-t-#{nth($size, 1)} {
margin-top: nth($size, 2);
}
}
#each $mediaQuery in $mediaQueries-px {
#media screen and (min-width: ($mediaQuery / 16 * 1em)) { // modified for compilation purposes
#each $size in $sizes {
.m-t-#{nth($size, 1)}-#{$mediaQuery} {
margin-top: nth($size, 2);
}
}
}
}
Output:
.m-t-s {
margin-top: 20px;
}
.m-t-m {
margin-top: 50px;
}
.m-t-l {
margin-top: 60px;
}
#media screen and (min-width: 40em) {
.m-t-s-640 {
margin-top: 20px;
}
.m-t-m-640 {
margin-top: 50px;
}
.m-t-l-640 {
margin-top: 60px;
}
}
#media screen and (min-width: 48em) {
.m-t-s-768 {
margin-top: 20px;
}
.m-t-m-768 {
margin-top: 50px;
}
.m-t-l-768 {
margin-top: 60px;
}
}
#media screen and (min-width: 64em) {
.m-t-s-1024 {
margin-top: 20px;
}
.m-t-m-1024 {
margin-top: 50px;
}
.m-t-l-1024 {
margin-top: 60px;
}
}