Skip to content

Instantly share code, notes, and snippets.

@ijy
Forked from Snugug/01-variable-respond-to-mixin.md
Created September 22, 2012 17:10
Show Gist options
  • Save ijy/3766813 to your computer and use it in GitHub Desktop.
Save ijy/3766813 to your computer and use it in GitHub Desktop.
Variable-driven respond-to mixin

What if controlling your media queries was as easy as adding on to a Sass list? What if I told you it now is?

This snippet comes from a modified version of mixins in the Aura Responsive Framework and came from me hijacking the respond-to mixin namespace but still wanting to use it for custom media queries. It's a little ugly and requires Sass 3.2+ (for now, (sudo) gem install sass --pre), but it works a charm.

There are two fairly mundane caveats to this method. First, every media query needs to be named. Second, every media query needs a size and assumes min-width and screen. If you want to change min-width, simply add your operator as another option, but if you want to change screen, you need to also include your operator even if you want it to be min-width.

Also, I haven't built in warnings yet for when you do bad things, so bear that in mind.

Without further adue, tada.

// Four breakpoints: foo, bar, baz, and qux.
//
// Foo assumes the defaults of min-width and screen. Foo will gen @media screen and (min-width: 500px)
// Bar changes min-width to max, but assumes screen as well. Bar will gen @media screen and (max-width: 700px)
// Baz wants to use min-width, but change media type, so min-width needs to be re-declare. Baz will gen @media tv and (min-width: 700px)
// Qux goes all out and has a full unique media query. Qux will get @media tv and (max-width: 900px)
$breakpoints: 'foo' 500px, 'bar' 700px 'max-width', 'baz' 700px 'min-width' tv, 'qux' 900px 'max-width' tv;
// Let's call respond-to!
#waldo {
background: red;
@include respond-to('foo') {
background: green;
}
@include respond-to('bar') {
background: yellow;
}
@include respond-to('baz') {
background: purple;
}
@include respond-to('qux') {
background: orange;
}
}
// Our Output:
#waldo {
background: red;
}
@media screen and (min-width: 500px) {
#waldo {
background: green;
}
}
@media screen and (max-width: 700px) {
#waldo {
background: yellow;
}
}
@media tv and (min-width: 700px) {
#waldo {
background: purple;
}
}
@media tv and (max-width: 900px) {
#waldo {
background: orange;
}
}
// Our respond-to mixin, with the new hotness?
// A little more complicated than previous respond-to mixins, but now runs off of a variable. This is also Rev 1 so if someone can help me make it better, I'm all ears.
// We need to start with a defaulted breakpoints variable.
$breakpoints: false !default;
@mixin respond-to($context) {
@if $breakpoints != false {
// Check to see if the 2nd item is a number. If it is, we've got a single query
@if type-of(nth($breakpoints, 2)) == 'number' {
// Check to see if the context matches the breakpoint namespace
@if $context == nth($breakpoints, 1) {
// Call Media Query Generator
@include media-query-gen($breakpoints) {
@content;
}
}
}
// Else, loop over all of them
@else {
// Loop over each breakpoint and check context
@each $bkpt in $breakpoints {
// If context is correct…
@if $context == nth($bkpt, 1) {
// Call the generator!
@include media-query-gen($bkpt) {
@content;
}
}
}
}
}
}
// This functionality gets used twice so I turned it into its own mixin.
@mixin media-query-gen($bpt) {
// Get length of breakpoint variable, minus the namespace
$length: length($bpt);
// Go through all of the breakpoint items, starting at the second, and add them to a variable to be passed into the media query mixin
$mq: false !default;
@for $i from 2 through $length {
// If it's the first item, override $mq
@if $i == 2 {
$mq: nth($bpt, $i);
}
// Else, join $mq
@else {
$mq: join($mq, nth($bpt, $i));
}
}
// Call Media Query mixin
@include media-query($mq) {
@content;
}
}
// Slightly modified version of my Media Query Mixin (https://gist.github.com/2490750) from earlier, modified to accommodate list input
@mixin media-query($value, $operator: 'min-width', $query: 'screen') {
// If a list is passed in for value, break it into value, operator, and query
@if type-of($value) == 'list' {
$mq: $value;
@for $i from 1 through length($mq) {
@if $i == 1 {
$value: nth($mq, 1);
}
@else if $i == 2 {
$operator: nth($mq, 2);
}
@else if $i == 3 {
$query: nth($mq, 3);
}
}
}
@media #{$query} and (#{$operator}: #{$value}) {
@content;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment