I have a Sass mixin for my media queries based on Twitter Bootstrap's responsive media queries:
#mixin respond-to($media) {
#if $media == handhelds {
/* Landscape phones and down */
#media (max-width: 480px) { #content; }
}
#else if $media == small {
/* Landscape phone to portrait tablet */
#media (max-width: 767px) {#content; }
}
#else if $media == medium {
/* Portrait tablet to landscape and desktop */
#media (min-width: 768px) and (max-width: 979px) { #content; }
}
#else if $media == large {
/* Large desktop */
#media (min-width: 1200px) { #content; }
}
#else {
#media only screen and (max-width: #{$media}px) { #content; }
}
}
And I call them throughout my SCSS file like so:
.link {
color:blue;
#include respond-to(medium) {
color: red;
}
}
However, sometimes I want to style multiple queries with the same styles. Right now I'm doing them like this:
.link {
color:blue; /* this is fine for handheld and small sizes*/
/*now I want to change the styles that are cascading to medium and large*/
#include respond-to(medium) {
color: red;
}
#include respond-to(large) {
color: red;
}
}
but I'm repeating code so I'm wondering if there is a more concise way to write it so I can target multiple queries. Something like this so I don't need to repeat my code (I know this doesn't work):
#include respond-to(medium, large) {
color: red;
}
Any suggestions on the best way to handle this?
A mixin like that leaves you in a position that's not very flexible, and not just because you're using px (see: http://blog.cloudfour.com/the-ems-have-it-proportional-media-queries-ftw/). Simply put, you've made your mixin too specific and not very reusable for other sites.
I'm currently using a collection of 4 mixins to handle the most common media queries: min-width, max-width, between, and outside (I've sampled min-width and between below)
$output-media-width: true !default; // true = all, otherwise use a list of numeric values (eg. 320px 23em)
#mixin media-min-width($bp) {
#if type-of($output-media-width) != list {
#media (min-width: $bp) {
#content;
}
} #else {
$output-bp: find-comparable($bp, $output-media-width);
#if not comparable($output-bp, $bp) {
#debug "Output breakpoint: #{$output-bp}, Chosen minimum width: #{$bp}";
} #else if $output-bp >= $bp {
#content;
}
}
}
#mixin media-between($bp1, $bp2) {
#if type-of($output-media-width) != list {
#media (min-width: $bp1) and (max-width: make-less-than($bp2)) {
#content;
}
} #else {
$output-bp1: find-comparable($bp1, $output-media-width);
$output-bp2: find-comparable($bp2, $output-media-width);
#if not comparable($output-bp1, $bp1) or not comparable($output-bp2, $bp2) {
#debug "Output breakpoints: #{$output-bp1} and #{$output-bp2}, Chosen breakpoints: #{$bp1} and #{$bp2}";
} #else if $output-bp2 >= $bp1 and $output-bp2 < $bp2 {
#content;
}
}
}
#function find-comparable($val, $list) {
#each $item in $list {
#if comparable($val, $item) {
#return $item;
}
}
}
#function make-less-than($val) {
#return if(unit($val) == em, $val - .001, $val - 1);
}
This mixin suite lets me generate a responsive CSS file or a collection of non-responsive CSS files at any width I desire (specifically for devices that don't take kindly to media queries) just by having a variable like this at the top of my file:
$output-media-width: 800px 60em;
A list of sizes lets me use px in those rare cases where em is inappropriate (such as for dealing with images).
// Device widths
$device-x-narrow: 23em; // 320px
$device-narrow: 35em; // 480px
$device-medium: 60em; // 800px
$device-wide: 70em; // 1000px
article.event {
#mixin tableify {
// footer { display: table-row }
footer section { display: table-cell }
footer section + section { padding-left: 2em }
}
#include media-min-width($device-medium) { // 2-col layout still
#main > & { // single event view
#include tableify;
}
}
// sometimes you need a non-standard breakpoint, too...
#include media-min-width(27em) { // narrow devices
section & {
#include tableify;
}
}
#include media-max-width(27em) {
footer section.categories ul {
display: block;
padding-left: 0;
li { display: inline }
li + li { margin-left: 1em }
}
}
}
Despite the fact that #cimmanon answered my question before I posted that I was using Twitter Bootstrap, it had some really interesting ideas in it which I think I'll apply from now on for my Sass projects that use Twitter Bootstrap. Here is what I found worked great:
/* Responsive dimensions */
$handheld-max: 479px;
$small-min: $handheld-max + 1;
$small-max: 767px;
$medium-min: $small-max + 1;
$medium-max: 979px;
$large-min: $medium-max + 1;
$large-max: 1199px;
$xlarge: 1200;
/*Responsive query mixins */
#mixin media-above($min) {
#media (min-width: $min) { #content; }
}
#mixin media-below($max) {
#media (max-width: $max) { #content; }
}
#mixin media-between($min, $max) {
#media (min-width: $min) and (max-width: $max) { #content; }
}
and then call it in my code like so (based on my request in the question):
.link {
color: blue;
#mixin media-above($medium-min){
color: red;
}
}
Using bootstrap-sass variables, I defined such mixins in SASS syntax:
=media-width-below($max)
#media (max-width: $max)
#content
=media-width-between($min, $max)
#media (min-width: $min), (max-width: $max)
#content
=media-width-above($min)
#media (min-width: $min)
#content
=media-xs
+media-width-above($screen-xs-min)
#content
=media-sm
+media-width-above($screen-sm-min)
#content
=media-md
+media-width-above($screen-md-min)
#content
=media-lg
+media-width-above($screen-lg-min)
#content
Those mixins will be useable just like +make-sm-column or .col-md-5 classes. You can just use it like this:
body
+media-xs
background-color: yellow
+media-sm
background-color: blue
+media-md
background-color: red
+media-lg
background-color: green
When you will be making your browser smaller by changing it from large to xs, you'll see colors in this order: green, red, blue, yellow.
Related
I have a SASS mixin for media queries which works well, especially when nesting, but the issue is I can't seem to work out how I could write my mixin so I can combine different media queries. Is there a way in which I can keep the simplicity of my mixin but allow for multiple combined queries?
For example:
#include media(tablet-p) and media(phone) {
width: 100%;
}
This is my current mixin below including how I use it currently.
#mixin media($size) {
#if $size == laptop {
#media screen and (min-width:1201px) and (max-width:1440px) {
#content;
}
} #else if $size == tablet-l {
#media screen and (min-width:1024px) and (max-width:1200px) {
#content;
}
} #else if $size == tablet-p {
#media screen and (min-width:768px) and (max-width:1023px) {
#content;
}
} #else if $size == phone {
#media screen and (max-width: 767px) {
#content;
}
}
}
#include media(phone) {
width: 100%;
}
Not being rude or so please dont take it like that but that is no a simple mixin, or flexible.
Have a variables or a map of your breakpoints, and a mixin that takes those. I work with mobile first so I always start with mobile styles so my most used cases are small, medium that is min-width. Sometimes of cause you have to use to-small ect..
$breakpoints: (
'to-small' : ( max-width: 766px ),
'small' : ( min-width: 767px ),
'to-medium' : ( max-width: 991px ),
'medium' : ( min-width: 992px ),
'to-large' : ( min-width: 1199px ),
'large' : ( min-width: 1200px ),
'to-x-large' : ( min-width: 1599px ),
'x-large' : ( min-width: 1600px )
);
mixin
#mixin media($breakpoint) {
#if map-has-key($breakpoints, $breakpoint) {
#media #{inspect(map-get($breakpoints, $breakpoint))} {
#content;
}
}
#else {
#warn "Unfortunately, no value could be retrieved from `#{$breakpoint}`. "
+ "Please make sure it is defined in `$breakpoints` map.";
}
}
Usage
.block {
width: 100%;
// this query will apply from widths larger then 1200px
// meaning you have the same for mobile and tablet
#include media('large') {
width: 25%;
}
}
.block {
width: 100%;
// this query will apply from widths larger then 992px (landscape tablet)
// meaning you have the same for mobile and tablet portrait
#include media('medium') {
width: 25%;
}
}
I'm using Bourbon Neat in my project and Neat has this neat (ha!) little mixin for media queries:
$xs-media: new-breakpoint(min-width 1px max-width 480px);
#include media($xs-media) {
// your styles
}
But #include media doesn't support multiple breakpoints. So I'm trying to do this:
#mixin multiple-media($breakpoints...) {
#each $breakpoint in $breakpoints {
#include media($breakpoint) {
#content
}
}
}
I can then use multiple breakpoints on it:
$xs-media: new-breakpoint(min-width 1px max-width 480px);
// $sm-media: ...
// $md-media: ...
#inlclude multiple-media($xs-media, $sm-media, $md-media) {
// my styles
}
But the compiled CSS doesn't quite work and look right. This is what gets generated (Just an example of what happens):
#media screen and (min-width: min-width) {
.instagram-widget .instagram-widget__images-container > a > img {
width: 25%; } }
#media screen and (min-width: min-width) {
.instagram-widget .instagram-widget__images-container > a > img {
width: 25%; } }
#media screen and (min-width: min-width) {
.instagram-widget .instagram-widget__images-container > a > img {
width: 25%; } }
#media screen and (min-width: min-width) { ??
Is there any way to use
"breakpoint"
for sass within
"Prepros"
?
you can write your breakpoints in different file and can name that file as "_breakpoint.scss"
In your main app.scss you can call you dependent file with import function. So in your app.scss you would write :-
app.scss
#import "_breakpoint.scss";
now you can use breakpoint in this file which you have define in _breakpoint.scss file.
Hope its clear!!
Yes. Here's an example:
#mixin breakpoint($point) {
#if $point == xs {
#media (min-width: 420px) { #content; }
} #else if $point == sm {
#media (min-width: 640px) { #content; }
} #else if $point == md {
#media (min-width: 960px) { #content; }
}
}
...specifying as many as you want. And then using breakpoints is as easy as this:
.my-class {
color: red;
#include breakpoint(md) {
color: blue;
}
}
In this example .my-class colour will be red, unless the viewport is at least 960px wide, in which case .my-class colour will be blue.
I hope this helps.
I have been designing with CSS for years, but I am only just now learning how to use SASS. This is very much a beginner question, so please bear with me.
The reason I started looking into SASS was because I wanted to develop a responsive web design, but was hoping there was a better way to do it than manually make different style sheets for every screen size.
I believe that in principle, a CSS preprossesor like SASS should help with this issue... but at the moment I don't understand how.
If I have a div with the id #squishable, and on large screens I want it to have a width of 1000 pixels, and on small screens a width of 100 pixels, but a red background in both cases, I think I would do something like this:
$color = red;
#squishable {
backgorundcolor: $color;
}
#media only screen
and (min-width : 321px) {
#squishable {
width:100px;
}
}
#media only screen
and (min-width : 1824px) {
#squishable {
width:1000px;
}
}
However, I'm not sure this approach is in much of an advantage over just using CSS. Maybe as an example, it's too simplistic. But, in any case, I don't see exactly what I would be doing differently with SASS to make it easier to code for a responsive web design. Is this all there is to it?
Can someone help me get over this conceptual hurdle and let me know how I take advantage of SASS to create elements that are responsive? Hopefully with a simple example similar to what I've got above?
You can absolutely improve your workflow further!
Using SASS #mixin, #include, #content and regular variables you can setup an environment where you create your media queries "inline", or inside of your regular selectors if you will.
This is my mixin for media queries:
(never mind the stupid variable names and placeholder breakpoints)
// Breakpoints
$mq-tiny: 5em;
$mq-small: 10em;
$mq-medium: 15em;
$mq-large: 20em;
$mq-huge: 25em;
$mq-crazy: 30em;
#mixin mq($size, $direction: min-width, $media-type: only all) {
#if $size == tiny { #media #{$media-type} and (#{$direction}: $mq-tiny) { #content; } }
#else if $size == small { #media #{$media-type} and (#{$direction}: $mq-small) { #content; } }
#else if $size == medium { #media #{$media-type} and (#{$direction}: $mq-medium) { #content; } }
#else if $size == large { #media #{$media-type} and (#{$direction}: $mq-large) { #content; } }
#else if $size == huge { #media #{$media-type} and (#{$direction}: $mq-huge) { #content; } }
#else if $size == crazy { #media #{$media-type} and (#{$direction}: $mq-crazy) { #content; } }
#else { #media #{$media-type} and (#{$direction}: $size) { #content; } }
}
And here's an example of how it can be used:
SCSS:
.selector {
width: 100px;
#include mq(large) {
width: 1000px;
}
}
CSS output:
.selector {
width: 100px
}
#media only all and (min-width: 20em) {
.selector {
width: 1000px
}
}
Take note that you don't need to use a variable name for the width. You can pass 1000px instead of large if you want to.
You may also have noticed the optional arguments in the #mixin; $direction and $media-type. These arguments default to min-width and only all respectively, but if you pass them through the #include they'll change for that specific element only.
Example with other arguments:
SCSS:
.selector {
#include mq(1000px, min-height) {
width: 100px;
}
}
CSS output:
#media only all and (min-height: 1000px) {
.selector {
width: 100px
}
}
Hope this helps!
Edit:
Here's a pen if you want to play around with it.
To increase maintainability of your code you can use variables to define media queries breakpoints:
// define breakpoints
$small-screen: 321px;
$large-screen: 1824px;
$small: "only screen and (min-width:"#{$small-screen}")";
$large: "only screen and (min-width:"#{$large-screen}")";
// and so on...
// now you can esely manipulate with your media breakpoints
#media #{$small} {
...
}
#media #{$large} {
...
}
Highly recommend you develop your SAAS css style import bootstrap framework, it will save you much time at responsive web designs
More detailed information please see this link:
http://pivotallabs.com/sass-with-bootstrap/
Mixins with LESS are really simple:
.some-rules() {
/* some rules */
}
.some-class {
.some-rules;
}
However, suppose I've got a ruleset within a media query, like:
#media (min-width: 800px) {
.my_ruleset {
/* more rules */
}
}
How can I include such a ruleset as a mixin?
My motivation here is that I am using Bootstrap. I am trying to avoid semantically polluting my markup with its selectors, and would rather incorporate its rulesets as mixins. That's simple enough given the first example above, but I'm not sure how to incorporate the #media selectors.
EDIT
Specifically, here is a summary of the code I am trying to use as a mixin:
.container {
.container-fixed();
}
// ...
#media (min-width: #screen-sm) {
.container {
max-width: #container-sm;
}
// ...
}
#media (min-width: #screen-md) {
.container {
max-width: #container-md;
}
// ...
}
#media (min-width: #screen-lg-min) {
.container {
max-width: #container-lg;
}
// ...
}
Just simply add:-
.my_ruleset {
/* more rules */
}
#media (min-width: 800px) {
.my_ruleset;
}
If you want to add parameters to this for instance then:-
.my_ruleset(#myMargin:5px;) {
margin:#myMargin;
}
#media (min-width: 800px) {
.my_ruleset(10px);
/* New Rules*/
}
.
.
/* And so On */
Update:-
if you want to adapt this in a dynamic form take whole media query into mixin and play with it...
.container(
#minSize:768px;
#maxSize:979px;
#myColor:green;
/* So on */
) {
#media (min-width: #minSize) and (max-width: #maxSize) {
.my_ruleset {
background-color:#myColor;
}
/* New Rules*/
}
}
.container(0px,480px,black);
.container(481px,767px,blue);
.container(768px,979px,pink);
.container(980px,1200px,white);
.container(1700px,2200px,red);
EDIT
Checkout these two answers (class set in media query, media query grouping), I feel like they are very closely related to your question. Looking at the second answer I tried to put something together. The snippet is below, but you can also see a demo.tar.gz I put together as well.
main.less
#import "less/bootstrap"; /*Obviously, make sure to have all the less src :)*/
/*source: http://tinyurl.com/less-query */
.make-container(#min-width) {
#media (min-width: #min-width) {
.page-maker(#max-width) {
.page {
max-width: #max-width;
.container-fixed();
}
}
.make-page-style() when (#min-width=#screen-lg-min) {
.page-maker(#container-lg);
}
.make-page-style() when (#min-width=#screen-md) {
.page-maker(#container-md);
}
.make-page-style() when (#min-width=#screen-sm) {
.page-maker(#container-sm);
}
.make-page-style();
}
}
.make-container(#screen-sm);
.make-container(#screen-md);
.make-container(#screen-lg-min);
HTML
...
<body>
<div class="page">
...
</div>
...
OLD
have you tried using the following mixins (n is the number of columns):
.make-row()
.make-lg-comun(n)
.make-md-column(n)
.make-xs-column(n)
These mixins are used to semantically structure the page. For example, if you have the following markup:
<div class="main">
<div class="left">
</div>
<div class="right">
</div>
</div>
then in your less you can do:
.main{
.make-row();
}
.left{
.make-lg-column(5); /* makes five large desktop column */
}
.right{
.make-lg-column(7);
}
if this is not what you are looking for, perhaps elaborate on your intent more, maybe you won't need to do a lot of media queries.
You can use parent selector:
#screen-sm: 400;
#screen-md: 800;
#screen-lg-min: 1000;
.responsive(#width-sm, #width-md, #width-lg) {
#media (min-width: #screen-sm) {
& {
max-width: #width-sm;
}
}
#media (min-width: #screen-md) {
& {
max-width: #width-md;
}
}
#media (min-width: #screen-lg-min) {
& {
max-width: #width-lg;
}
}
}
.container {
.responsive(100px, 200px, 300px);
}
Output:
#media (min-width: 400) {
.container {
max-width: 100px;
}
}
#media (min-width: 800) {
.container {
max-width: 200px;
}
}
#media (min-width: 1000) {
.container {
max-width: 300px;
}
}