SASS media queries best practise? - css

Is it ok to nest media queries inside an element? If I want to use min-width: 480px in another places there will be huge repetition. Please look at my code example. Or just use the old way? Any idea?
SASS
.navbar {
height: 500px;
width: 500px;
#media screen and (min-width: 480px) {
background-color: lightgreen;
}
}
.items {
padding: 15px;
color: red;
#media screen and (min-width: 480px) {
border: 1px solid black;
}
}
CSS
#media screen and (min-width: 480px) {
.navbar {
background-color: lightgreen;
}
.items {
border: 1px solid black;
}
}

$pc: 1024px; // PC screen size.
$tablet: 720px; // Tablet screen size.
$phone: 320px; // Phone screen size.
#mixin responsive($media) {
#if $media= phone {
#media only screen and (max-width: $tablet - 1) {
#content;
}
}
#else if $media= tablet {
#media only screen and (min-width: $tablet - 1) and (max-width: $pc) {
#content;
}
}
#else if $media= pc {
#media only screen and (min-width: $pc + 1) and (min-width: $pc) {
#content;
}
}
#else if $media= pc_tablet {
#media only screen and (min-width: $tablet - 1) {
#content;
}
}
}
Examples
body {
#include responsive(pc) {
background: red;
}
#include responsive(tablet) {
background: yellow;
}
#include responsive(phone) {
background: green;
}
}

Related

About #media in CSS

my question about #media code in CSS
when I create a website I use #media in media to change on many screens like this:
#media (min-width: 280px) and (max-width: 767px) {
#media (min-width: 280px) {
.main-header .main-textmonial {
font-size: 11px;
}
}
#media (min-width: 320px) {
.main-header .main-textmonial {
font-size: 13px;
}
}
#media (min-width: 360px) {
.main-header .main-textmonial {
font-size: 15px;
}
}
#media (min-width: 411px) {
.main-header .main-textmonial {
font-size: 18px;
}
}
#media (min-width: 450px) {
.main-header .main-textmonial {
font-size: 24px;
}
}
}
This method is correct or not?
Is there a method better than that?
For this #media query , this is the only way can be can be doing different screen size that set to specification settings by using css
It seems to be valid. I can show You how I like to handle RWD with #media
Create a mixin like so
#mixin breakpoint($point) {
#if $point == desktop {
#media (min-width: 70em) { #content ; }}
#else if $point == laptop {
#media (min-width: 64em) { #content ; }}
#else if $point == tablet {
#media (min-width: 50em) { #content ; }}
#else if $point == phablet {
#media (min-width: 37.5em) { #content ; }}
#else if $point == mobileonly {
#media (max-width: 37.5em) { #content ; }}
}
Use it like this
.podcasts {
margin: 1em auto;
#include breakpoint(phablet){
width: 100%;
}
}
It's just a suggestion, Maybe You'll like it :)
Yes, this is a valid method. Maybe you can also delete the duplicated check for #media (min-width: 280px), like this:
#media (min-width: 280px) and (max-width: 767px) {
.main-header .main-textmonial {
font-size: 11px;
}
#media (min-width: 320px) {
.main-header .main-textmonial {
font-size: 13px;
}
}
#media (min-width: 360px) {
.main-header .main-textmonial {
font-size: 15px;
}
}
#media (min-width: 411px) {
.main-header .main-textmonial {
font-size: 18px;
}
}
#media (min-width: 450px) {
.main-header .main-textmonial {
font-size: 24px;
}
}
}
But again the way you did it is valid for this #media query.

Problem with CSS breakpoints selectors override with SASS

I have a _display.scss partial.
It contains #mixin and classes related to display CSS property.
_display.scss
#mixin d-block{
display: block;
}
#mixin d-none{
display: none;
}
.d-block{
#include d-block();
}
.d-none{
#include d-none();
}
I developer a #mixin generate-responsive-content that take the #content of a class and generate a different #media query for each breakpoint.
In this way:
.d-block{
#include generate-responsive-content() {
#include d-block();
}
}
.d-none{
#include generate-responsive-content() {
#include d-none();
}
}
// Generate all breakpoints from content
#mixin generate-responsive-content() {
// Responsive styles
// Loop over each size
#each $breakName, $width in $breakpoints {
// Check breakpoint
#if ($breakName != "") {
$breakName: '-' + $breakName;
#media (min-width: $width) {
&#{$breakName} {
#content
}
}
} #else {
#content;
}
}
}
eg. generated classes: .d-block, .d-block-xs, .d-block-sm...
But in this way, I cannot override the classes of .d-none with the classes of .d-block for each breakpoint because they have been generated before and are overwritten by those of .d-none.
I also have a class with the same name but without breakpoint variant, like d-none-lg, d-block-lg, these overwrite all others.
Check this CodePen. Here d-none variants overwrite every class of d-block.
How I can solve that?
I have created a quick demo for you - https://codepen.io/rhythm19/pen/OJVMyLa and its working as expected. I think you just need to swap the order. Generate d-none classes first and then d-block classes.
.d-none{
#include generate-responsive-content() {
#include d-none();
}
}
.d-block{
#include generate-responsive-content() {
#include d-block();
}
}
Updated answer to include max-width breakpoint.
.see{outline:1px solid black;padding:1em;}
// BREAKPOINT
$breakpoints: (
"xs": 575px,
"sm": 576px,
"md": 768px,
"lg": 992px,
"xl": 1200px
);
#mixin d-block() {
display: block;
}
#mixin d-none() {
display: none;
}
.d-block{
#include d-block();
}
.d-none{
#include d-none();
}
// Generate all breakpoints from content
#mixin generate-responsive-content() {
// Responsive styles
// Loop over each size
#each $breakName, $width in $breakpoints {
// Check breakpoint
#if ($breakName == 'xs' ) {
$breakName: '-' + $breakName;
#media (max-width: $width) {
&#{$breakName} {
#content
}
}
}
#else if ($breakName != 'xs' ) {
$breakName: '-' + $breakName;
#media (min-width: $width) {
&#{$breakName} {
#content
}
}
} #else {
#content;
}
}
}
.d-block{
#include generate-responsive-content() {
#include d-block();
}
}
.d-none{
#include generate-responsive-content() {
#include d-none();
}
}
This is what is output:
.see {
outline: 1px solid black;
padding: 1em;
}
.d-block {
display: block;
}
.d-none {
display: none;
}
#media (max-width: 575px) {
.d-block-xs {
display: block;
}
}
#media (min-width: 576px) {
.d-block-sm {
display: block;
}
}
#media (min-width: 768px) {
.d-block-md {
display: block;
}
}
#media (min-width: 992px) {
.d-block-lg {
display: block;
}
}
#media (min-width: 1200px) {
.d-block-xl {
display: block;
}
}
#media (max-width: 575px) {
.d-none-xs {
display: none;
}
}
#media (min-width: 576px) {
.d-none-sm {
display: none;
}
}
#media (min-width: 768px) {
.d-none-md {
display: none;
}
}
#media (min-width: 992px) {
.d-none-lg {
display: none;
}
}
#media (min-width: 1200px) {
.d-none-xl {
display: none;
}
}
UPDATED CODEPEN: Here's the OPs codepen, with this update:
https://codepen.io/chrislafrombois/pen/JjdGKGJ
Here is the code from the pen:
.see {
outline: 1px solid black;
padding: 1em;
}
.d-block {
display: block;
}
.d-none {
display: none;
}
#media (max-width: 575px) {
.d-block-xs {
display: block;
}
}
#media (min-width: 576px) {
.d-block-sm {
display: block;
}
}
#media (min-width: 768px) {
.d-block-md {
display: block;
}
}
#media (min-width: 992px) {
.d-block-lg {
display: block;
}
}
#media (min-width: 1200px) {
.d-block-xl {
display: block;
}
}
#media (max-width: 575px) {
.d-none-xs {
display: none;
}
}
#media (min-width: 576px) {
.d-none-sm {
display: none;
}
}
#media (min-width: 768px) {
.d-none-md {
display: none;
}
}
#media (min-width: 992px) {
.d-none-lg {
display: none;
}
}
#media (min-width: 1200px) {
.d-none-xl {
display: none;
}
}
<div class="see">
<span>I CANNOT SEE ANYTHING BECAUSE d-none OVERWRITE EVERYTHING</span>
<div class="d-none d-none-xs d-block-sm d-block-md d-block-lg">
CHECK CSS STYLE D-BLOCK-LG OVERWRITE EVERITHING
</div>
</div>
Per our discussion, you should not try and put the default d-none and d-block into this mixin. Because of how the code will output, you should just separate that concern and place the defaults before the media query blocks.

My Media queries are not changing as wanted

Currently I'm trying to change the padding of my landing page text, so it pushes my smooth scroll button to the bottom of the page. However the queries work up until (min-width: 600px), and they dont change higher.
Mixins Partial
#mixin for-phone-only {
#media (max-width: 599px) {
#content;
}
}
#mixin for-tablet-portrait {
#media (min-width: 600px) {
#content;
}
}
#mixin for-tablet-landscape {
#media (min-width: 899px) {
#content;
}
}
#mixin for-desktop-up {
#media (min-width: 1200px) {
#content;
}
}
Landing Page Partial
.welcomeTitle {
font-family: $landing-font;
font-size: $landing-header-size-l;
text-shadow: 1px 1px 15px #000;
padding-top: 20%;
#include for-phone-only {
font-size: $landing-header-size-sm;
}
}
.welcomeText {
#include for-desktop-up {
padding: 0 20% 21.5% 20%;
font-size: $landing-text-size-l;
}
#include for-tablet-landscape {
padding: 0 20% 20% 20%;
}
#include for-tablet-portrait {
padding: 0 20% 60% 20%;
}
#include for-phone-only {
padding: 0 20% 50% 20%;
}
}
So it applies the tablet portrait query, but when the width goes above 899px, it dose not apply the tablet landscape, or when it goes above 1200px, it dosent apply the desktop query.
Thanks :D

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.

Can I set a global variable using a media query?

I have a code smell that looks like this:
$mobile-bg-color: #ddddff;
$desktop-bg-color: #ffdddd;
$mobile-border: solid 2px black;
$desktop-border: solid 2px red;
div {
margin: 50px;
#media screen and (max-width: $mobile_threshold){
background-color: $mobile-bg-color;
border: $mobile-border;
}
#media screen and (min-width: $mobile_threshold + $threshold_step){
background-color: $desktop-bg-color;
border: $desktop-border;
}
}
And I'm having to do this anywhere where details might be different between mobile and desktop.
What I'd really like to do is:
div {
margin: 50px;
border: $responsive-border;
background-color: $responsive-bg-color;
}
This is possible using Sass?
You can achieve this with a mixin. Define a mixin like so:
#mixin responsive-border {
#media screen and (max-width: $mobile_threshold){
background-color: $mobile-bg-color;
border: $mobile-border;
}
#media screen and (min-width: $mobile_threshold + $threshold_step){
background-color: $desktop-bg-color;
border: $desktop-border;
}
}
Then call it like this:
div {
margin: 50px;
#include responsive-border;
}
You can do the same for any set of rules you will use often. Mixins help keep your code DRY.
Expanding on jmargolisvt's answer - you can also pass in the name of a property to the mixin, and have it resolve that.
eg.
#mixin responsive-bg-color ($prop){
#media screen and (max-width: $mobile_threshold){
#{$prop} : #ddddff;
}
#media screen and (min-width: $mobile_threshold + $threshold_step){
#{$prop} : #ffffdd;
}
}
#mixin responsive-margin-value($prop) {
#media screen and (max-width: $mobile_threshold){
#{$prop} : 2px
}
#media screen and (min-width: $mobile_threshold + $threshold_step){
#{$prop} : 20px
}
}
div {
margin: 50px;
border: solid 2px;
#include responsive-bg-color ("background-color");
#include responsive-margin-value("padding-top");
}
p {
#include responsive-margin-value("padding-bottom");
background-color: #ddeedd;
}
This is a little limited, as you won't be able to use shorthand css for example, but it works.

Resources