PostCSS compiling SASS media queries out of order? - css

I'm using a simple webpack build with PostCSS. If I don't declare a specific media query mixin in the first section of the page's SCSS, but use that specific media query mixin in a following section, that media query outputs after the other breakpoints (even though I have them defined in a specific order in my mixins file). Here's my code:
_variables.scss
$sm-screen: 576px;
$md-screen: 768px;
$lg-screen: 992px;
$xl-screen: 1200px;
_mixins.scss
#mixin sm-screen {
#media screen and (min-width: #{$sm-screen}) {
#content;
}
}
#mixin md-screen {
#media screen and (min-width: #{$md-screen}) {
#content;
}
}
#mixin lg-screen {
#media screen and (min-width: #{$lg-screen}) {
#content;
}
}
#mixin xl-screen {
#media screen and (min-width: #{$xl-screen}) {
#content;
}
}
#mixin screen-size($screen) {
#media screen and (min-width: $screen) {
#content;
}
}
_page.scss
// ————————————————————————————————————————————————————————————
// HERO SECTION
// ————————————————————————————————————————————————————————————
#hero-section {
.hero-heading {
font-size: 2rem;
}
#include sm-screen {
.hero-heading {
font-size: 5rem;
}
}
#include lg-screen {
.hero-heading {
font-size: 6.5rem;
}
}
#include xl-screen {
.hero-heading {
font-size: 6.5rem;
}
}
}
// ————————————————————————————————————————————————————————————
// INTRO SECTION
// ————————————————————————————————————————————————————————————
#intro-section {
.icon-group {
background: red;
}
#include md-screen {
.icon-group {
background: yellow;
}
}
#include xl-screen {
.icon-group {
background: blue;
}
}
}
main.scss (importing files)
#import "/base/variables";
#import "/base/mixins";
#import "page";
As you can see in _page.scss, I like to declare breakpoints right within each section (or row) as I go down the page. The problem is since I didn't declare the #include md-screen breakpoint on the first section, HERO SECTION, it comes after the #include xl-screen breakpoint in the output CSS and overrides the styles of the largest breakpoint:
output CSS:
body.home #intro-section .icon-group {
background: red;
}
#media screen and (min-width:1200px) {
body.home #intro-section .icon-group {
background: blue;
}
}
#media screen and (min-width:768px) {
body.home #intro-section .icon-group {
background: yellow;
}
}
Does this mean that my practice of declaring the breakpoints on each section is not the best way? Should I declare all breakpoints at the end of each file, that way if nothing changes in one section at a specific breakpoint, I don't need to declare that breakpoint at all to get it to compile in the correct order? Is there a way to get media queries to output in the order they're declared in the mixins file, regardless of when the mixins are called in the CSS?
My intent is to get the breakpoints to output from smallest to largest since I'm using the mobile-first, min-width approach. I would love to apply the media queries like I'm doing, but if there's a better way (such as at the end of files), so be it.

Related

Using #use for importing media queries file SASS

When importing my .scss media queries file into my main.scss I would like the media queries to be loaded in after my initial styles to avoid errors.
The problem is that #use rules must be written before any other rules. I can include it for now by using #import at the end of the main.scss file but as #import is being deprecated, I'd like to know if there is a method of utilising #use without creating any more files.
If you declare your media queries as a #mixin you can #include them wherever you want:
_media.scss
#mixin queries {
#media (min-width: 300px) {
.second {
background: green;
}
}
#media (max-width: 600px) {
.third {
background: blue;
}
}
}
style.scss
#use "media";
.first {
background: red;
}
#include media.queries;
style.css
After running sass style.scss style.css you'll get:
.first {
background: red;
}
#media (min-width: 300px) {
.second {
background: green;
}
}
#media (max-width: 600px) {
.third {
background: blue;
}
}

mixin is not found in different scss file

I am learning Angular and scss as well. So in my test Angular v.5 Project currently facing problems with #mixin. Note that default.styleExt also set to 'scss'. #mixin works fine if I use #mixin and #include in the same *.scss file. But When I try to use #include of that #mixin in a different *.scss file. It shows errors.
For example, in my styles.scss has this mixin,
#mixin breakpoint($screen){
#if $screen == window_xLarge {
#media (min-width: 1440px){
#content;
}
}
#else if $screen == window_large {
#media (min-width: 1280px){
#content;
}
}
#else if $screen == window_medium {
#media (min-width: 840px){
#content;
}
}
#else if $screen == window_small {
#media (min-width: 600px){
#content;
}
}
#else if $screen == window_xSmall {
#media (min-width: 480px){
#content;
}
}
}
Now, when I try to use this #mixin in one of my other components' '*.scss', for example,
in comp01.scss try to add this code
app-comp02{
width: 100%;
#include breakpoint(window_small){
width: 50%
}
#include breakpoint(window_medium){
width: 50%;
}
#include breakpoint(window_large){
width: 33%;
}
height: auto;
margin: 0 5px;
}
It shows error like this
Module build failed:
#include breakpoint(window_small){
^
No mixin named breakpoint
Does anyone know, why this is happening? I definitely do not want to put all codes in the same scss file. Thanks in Advance.
Keep your mixins in a _helpers.scss file and then include that file in both your different scss like this
#import "/helpers"; // Path of scss
Or you can simply import "styles.scss" in the "comp01.scss" using the same syntax as mentioned above
You have to correct your typing you have an error because you should write the media query like that and this is a good site:sassmeister to test your sass/scss you can paste your code and you will see the errors
#mixin breakpoint($screen){
#if $screen == window_xLarge {
#media screen and (min-width: 1440px){
#content;
}
}
#else if $screen == window_large {
#media screen and (min-width: 1280px){
#content;
}
}
#else if $screen == window_medium {
#media screen and (min-width: 840px){
#content;
}
}
#else if $screen == window_small {
#media screen and (min-width: 600px){
#content;
}
}
#else if $screen == window_xSmall {
#media screen and (min-width: 480px){
#content;
}
}
}
app-comp02{
width: 100%;
#include breakpoint(window_small){
width: 50%
}
#include breakpoint(window_medium){
width: 50%;
}
#include breakpoint(window_large){
width: 33%;
}
height: auto;
margin: 0 5px;
}
and you wrote it like that
#media (min-width: 1280px){
#content;
}

How to create Sass mixin aliases with support for content blocks?

How can I define multiple names for the same mixin, with support for content blocks?
Definition
#mixin desktop-breakpoint {
#media only screen and (min-width: 769px) {
#content;
}
}
#mixin large-breakpoint {
#include desktop-breakpoint;
}
Usage
.my-class {
font-size: small;
#include desktop-breakpoint {
font-size: big;
}
}
.my-other-class {
color: red;
#include large-breakpoint {
color: blue;
}
}
Error message
Mixin "large-breakpoint" does not accept a content block.
You're not passing any #content when using #include desktop-breakpoint in your large-breakpoint mixin. Doing this will fix your compilation error:
#mixin large-breakpoint {
// Remember to pass content received by mixin to #include
#include desktop-breakpoint {
#content;
}
}
Then your CSS will be compiled properly, as intended:
.my-class {
font-size: small;
}
#media only screen and (min-width: 769px) {
.my-class {
font-size: big;
}
}
.my-other-class {
color: red;
}
#media only screen and (min-width: 769px) {
.my-other-class {
color: blue;
}
}
See proof-of-concept example based on your modified code: https://www.sassmeister.com/gist/3109af060293eed0b89a22c27fa20527

SCSS - best way to organize

Im working with SCSS and I want to structure the code proberly..
In LESS it wasnt a problem, but would you say it is okay to structure the code like below..
imagine that button has its own file.
#mixin button-basic {
.button {
font-size: 14px;
}
}
#mixin button-max-480 {
.button {
color: red;
}
}
#mixin button-max-767 {
.button {
color: green;
}
}
#mixin button-max-959 {
.button {
color: blue;
}
}
#mixin button-min-960 {
.button {
font-size: 34px;
color: purple;
}
}
#media print, screen {
#include button-basic();
}
in my media-query file.. (imagine having multiple includes within each media Query type.)
#media (min-width: 960px) {
#include button-min-960();
}
#media (max-width: 959px) {
#include button-max-959();
}
#media (max-width: 767px) {
#include button-max-767();
}
#media only screen and (max-width:480px) {
#include button-max-480();
}
You could work with #mixins but I would not recommend this approach because this gets really confusing.
I suggest using modifier classes for each variation and use your media-query inside your declaration.
.button {
&--red {
color: red;
}
&--green {
color: green;
}
&--blue {
color: blue;
}
#media (min-width: 768px) {
font-size: 1.125rem;
}
#media (min-width: 960px) {
font-size: 1.25rem;
}
}
This way you have a really clean code base and can split up each component / module into it's own file.

Bootstrap4: Accessing variables?

I switched from Bootstrap 3 to Bootstrap 4. I am using sass sources which I compile on the run. When I changed the libraries, I started to get error on my media switches, i.e. for
#media screen and (min-width: $screen-md-min) {
padding: 40px 50px;
}
I get error
Undefined variable: "$screen-md-min".
What is a correct way to access variables of Bootstrap4?
Thank u.
See the relevant section of the Bootstrap 4 migration documentation.
The #screen-* variables have been replaced by the $grid-breakpoints variable along with the media-breakpoint-up(), media-breakpoint-down(), and media-breakpoint-only() helper Sass mixins.
Example usage:
#include media-breakpoint-up(md) {
padding: 40px 50px;
}
With Bootstrap 4 you could use it like this by importing bootstrap/_variables.scss in your .scss file:
.your-class-name {
color: black;
#media (min-width: map-get($grid-breakpoints, sm)) {
color: red;
}
#media (min-width: map-get($grid-breakpoints, md)) {
color: blue;
}
#media (min-width: map-get($grid-breakpoints, lg)) {
color: green;
}
#media (min-width: map-get($grid-breakpoints, xl)) {
color: yellow;
}
}
or this:
.your-class-name {
color: black;
#include media-breakpoint-up(sm) {
color: red;
}
#include media-breakpoint-up(md) {
color: blue;
}
#include media-breakpoint-up(lg) {
color: green;
}
#include media-breakpoint-up(xl) {
color: yellow;
}
}
Fore more details, view this page section responsive breakpoints.
In Bootstrap 4 I could retrieve the screen-md-min value by doing this:
$grid-breakpoint-sm: map_get($grid-breakpoints, "sm");
Which I found out from looking in bootstrap's _variables.scss file:
$print-body-min-width: map-get($grid-breakpoints, "lg") !default;
BS4 replaces Less with Sass. Less use lazy loading for variables whilst Sass does not. So you should declare your variables before using them. Make sure to import bootstrap/_variables.scss before your media switches:
#import 'bootstrap/variables';
#media screen and (min-width: $screen-md-min) {
padding: 40px 50px;
}

Resources