New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extends in MediaQueries #640
Comments
If you search 'media extend' there are a ton of issues that talk about this. At its most basic, .this-style, .that-style, @media (min-width: 25em) { .other_style }, .last-style {
...
} |
That explains how the compiler works - thanks But as I see it - if the @media rule were to:
... wouldn't we be happy ? :) Best, |
As @robwierzbowski explains, If copying the CSS is the behavior you want, we recommend you use mixins for that, as they're the language construct that explicitly supports copying. |
I think the problem here is that while we can't extend an outer class from within a media query, inner classes (inside a query or nest) are extended along with outer ones when an In my view, This is incidentally how the "Roole" preprocessor has chosen to implement |
Extends in MediaQueries - a sort of workaround Knowing that we can extend classes inside MediaQueries as long as we make sure the class names does not conflict (prefix/namespace) - then all we need to do is to create a media version of each class. // This will work
@media (max-width:480px){ %mobile_class{ content:'Mobile'; }; }
@media (min-width:481px) and (max-width:768px){ %tablet_class{ content:'Tablet'; } }
.foo { @extend %mobile_class; }
.foo { @extend %tablet_class; }
.bar { @extend %mobile_class; }
.bar { @extend %tablet_class; }
// Output:
@media (max-width: 480px) { .foo, .bar { content: 'Mobile'; } }
@media (min-width: 481px) and (max-width: 768px) { .foo, .bar { content: 'Tablet'; } }
OK - let's get some automation // ====================================================================
// MediaExtends (very much a beta version)
//
// First - let's start by defining the breakpoints we need
// (key-label, min-value, max-value). 0 = omitted.
$breakpoints:(
(mobile,0,480),
(tablet,481,768),
(desktop,769,1200),
(large,1201,0)
);
// Next - a function to get breakpoints by key
// (objects would have been nice ;)
@function breakpoint($key){
@for $i from 1 through length($breakpoints){
@if(nth(nth($breakpoints,$i),1)==$key){ @return nth($breakpoints,$i); }
} @return $key;
}
// Next - a mixin to create prefixed versions of the classes
// we want to extend within @media.
//
// Example:
// @include mediaExtend(myExtend){ @content };
//
// Output:
// %mobile_myExtend { @content }
// %tablet_myExtend { @content }
// %desktop_myExtend { @content }
// %large_myExtend { @content }
//
// passing true as second parameter will
// create a regular extend class too
//
// E.g. %myExtend { @content }
@mixin mediaExtend($name,$regularextend:false){
@if($regularextend){ %#{$name}{ @content; }; }
@for $i from 1 through length($breakpoints){
$key:nth(nth($breakpoints,$i),1);
%#{$key+'_'+$name}{ @include media($key){ @content; } };
}
}
// Last - a mixin to create MediaQueries
// $breakpoint - $breakpoints key-label e.g. mobile, tablet,...
// $extends... - mediaExtends to extend (no prefix)
//
// ------------------------------------
// Example 1 - basic:
// ------------------------------------
// @include mediaExtend(myExtend){ border:1px solid #f0f; };
// .foo { @include media(mobile,myExtend); }
//
// Output:
// @media screen and (max-width: 480px) {
// .foo { border:1px solid magenta; }
// }
//
// ------------------------------------
// Example 2 - multible includes:
// ------------------------------------
// @include mediaExtend(myExtend){ border:1px solid #f0f; };
// .foo { @include media(mobile,myExtend); }
// .bar { @include media(mobile,myExtend); }
//
// @media screen and (max-width: 480px) {
// .foo, .bar { border: 1px solid magenta; }
// }
//
// ------------------------------------
// Example 3 - multible extends:
// ------------------------------------
// @include mediaExtend(myExtend_1){ border:1px solid #f0f; };
// @include mediaExtend(myExtend_2){ color:red; };
// .foo { @include media(mobile, myExtend_1, myExtend_2); }
//
// @media screen and (max-width: 480px) {
// .foo { border: 1px solid magenta; }
// }
// @media screen and (max-width: 480px) {
// .foo { color: red; }
// }
//
// I'm still looking for a way to store @content
// to provide an optimized version - like:;
// @media screen and (max-width: 480px) {
// .foo { border: 1px solid magenta; color: red;}
// }
// - Please let me know if you know :)
//
// ...or we'll just have to wait for
// https://github.com/nex3/sass/issues/116
//
// ------------------------------------
// Example 4 - @content:
// ------------------------------------
// @include mediaExtend(myExtend){ border:1px solid #f0f; };
// .foo { @include media(mobile,myExtend){ color:red; }; }
// .bar { @include media(mobile,myExtend){ color:blue; }; }
//
// Output:
// @media screen and (max-width: 480px) {
// .foo, .bar { border: 1px solid magenta; }
// }
// @media screen and (max-width: 480px) {
// .foo { color: red; }
// }
// @media screen and (max-width: 480px) {
// .bar { color: blue; }
// }
//
@mixin media($breakpoint,$mediaextends...){
$min:nth(breakpoint($breakpoint),2)* 1px;
$max:nth(breakpoint($breakpoint),3) * 1px;
$mq:'(min-width:'+$min+') and (max-width:'+$max+')';
@if($min and $max==0px){ $mq:'(min-width:'+$min+')'; }
@if($min==0px and $max){ $mq:'(max-width:'+$max+')'; }
@each $ext in $mediaextends { @extend #{'%'+$breakpoint +'_'+ $ext }; }
@media screen and #{unquote($mq)}{ @content; }
}
The shorter version breakpoints:(
(mobile,0,480),
(tablet,481,768),
(desktop,769,1200),
(large,1201,0)
);
@function breakpoint($key){
@for $i from 1 through length($breakpoints){
@if(nth(nth($breakpoints,$i),1)==$key){ @return nth($breakpoints,$i); }
} @return $key;
}
@mixin mediaExtend($name,$regularextend:false){
@if($regularextend){ %#{$name}{ @content; }; }
@for $i from 1 through length($breakpoints){
$key:nth(nth($breakpoints,$i),1);
%#{$key+'_'+$name}{ @include media($key){ @content; } };
}
}
@mixin media($breakpoint,$mediaextends...){
$min:nth(breakpoint($breakpoint),2)* 1px;
$max:nth(breakpoint($breakpoint),3) * 1px;
$mq:'(min-width:'+$min+') and (max-width:'+$max+')';
@if($min and $max==0px){ $mq:'(min-width:'+$min+')'; }
@if($min==0px and $max){ $mq:'(max-width:'+$max+')'; }
@each $ext in $mediaextends { @extend #{'%'+$breakpoint +'_'+ $ext }; }
@media screen and #{unquote($mq)}{ @content; }
}
// Example:
// A super simple responsive grid
@mixin Grid($grid-columns){
$i:1;
@while $i<=$grid-columns {
@include mediaExtend(gridSpan#{$i},true){
float:left;
width:100% / $grid-columns * $i;
}
$i:$i+1;
}
}
@include Grid(4);
// Does the same as:
// @include mediaExtend(gridSpan1,true){ float:left; width:25%; }
// @include mediaExtend(gridSpan2,true){ float:left; width:50%; }
// @include mediaExtend(gridSpan3,true){ float:left; width:75%; }
// @include mediaExtend(gridSpan4,true){ float:left; width:100%; }
// Just plain stupid ;)
@include mediaExtend(comment){ &:after { content:'Hey there!'; }; }
article {
@extend %gridSpan1;
@include media(mobile, gridSpan4){ color:blue; };
@include media(tablet, gridSpan3);
@include media(desktop, gridSpan2);
@include media(large, gridSpan1, comment);
}
section {
@extend %gridSpan2;
@include media(mobile, gridSpan4){ color:red; };
@include media(tablet, gridSpan3);
}
// Output:
article { float: left; width: 25%; }
@media screen and (min-width: 1201px) { article { float: left; width: 25%; } }
section { float: left; width: 50%; }
@media screen and (min-width: 769px) and (max-width: 1200px) { article { float: left; width: 50%; } }
@media screen and (min-width: 481px) and (max-width: 768px) { article, section { float: left; width: 75%; } }
@media screen and (max-width: 480px) { article, section { float: left; width: 100%; } }
@media screen and (min-width: 1201px) { article:after { content: 'Hey there!'; } }
@media screen and (max-width: 480px) { article { color: blue; } }
@media screen and (max-width: 480px) { section { color: red; } }
Happy SCSS'ing |
That is an epic workaround! IMO it seems like a Pandora's box that's been opened up with the features in 3.2 (but a good one); I'm convinced it must means however that more control or specificity is needed with respect to Awesome work with that approach above |
I don't buy this one bit. "Why can't I
Until we get mixin interpolation or the ability to pass a mixin as an argument to another mixin, this isn't a reasonable solution in some instances. I get that you don't want to change how |
This isn't a problem; this is exactly how You shouldn't think about
Users have two mutually unsatisfiable expectations. They expect
Mixin interpolation is coming. |
Update. I've added a cleaner and simpler version of "The Workaround" here: |
@extends are great - but why they can't be used in @media I don't understand ???
It becomes a BIG issue when trying to create reusables or frameworks.
Also it seems odd that while you can't use an @extend placed outside @media it
will mess up the output if named the same inside (test 2 +3)
Thanks for making things a lot better :)
Jakob E (using v. 3.2.5 + CodeKit)
The text was updated successfully, but these errors were encountered: