I'm doing a code review for sass code and came across using media queries inside the code. Is it a good practice? Are there better alternatives to writing this code?
.col-md-push-8 {
padding-top: 1.5em;
.btn {
&.btn-block {
border: none;
background-color: $footer-button;
margin: 1em 0 .5em;
width: 100%;
padding: 7px 10px;
border-radius: 8px;
&:hover {
background-color: $footer-button-hover;
}
#media (min-width: $screen-md-min) {
color: #025191;
&:hover .media span p.media-heading {
color: #0070ca;
}
}
}
}
}
Note: The code is for illustration purpose only and is not completely shown here.
I think that what your way to do it is perfectly fine if you're using SASS >= 3.2 (was buggy before).
Just one thing that you could do to define your media queries breakpoints more globally is to create a mixin for that purpose that you will re-use on each element you need responsive.
This way when you have to change let's say your min breakpoint, add another or change your media min-width to max-width, you don't have to do it everywhere.
Some little example assuming you have already defined $screen-md-min and $screen-md-mid :
#mixin custom-media($size) {
#if ($size == $small) {
#media (min-width: $screen-md-min) { #content; }
}
#else if ($size == $middle) {
#media (min-width: $screen-md-mid) { #content; }
}
}
And call it like so :
.btn {
&.btn-block {
...
#include custom-media($small) {
color: #025191;
&:hover .media span p.media-heading {
color: #0070ca;
}
}
}
}
There is no difference if you put Media Query inside or outside. It just depends on your preffered style.
Style 1
.some-class {
#media (min-width: 700px) {
background: red;
}
}
Style 2
#media (min-width: 700px) {
.some-class {
background: red;
}
}
Both will compile as:
#media (min-width: 700px) {
.some-class {
background: red;
}
}
Sass handles this fine, but that code is going to produce overly qualified selectors and is hardly concise.
There are a number of patterns for writing “better” CSS and Sass, such as BEM, OOCSS, OOCSS + Sass, and SMACSS.
There's also a bunch of great information on Media Queries in Sass that is probably worth a read.
Related
I want to use one CSS style for two classes with mixin, but when I use mixin the final result will be 2 classes with the same CSS.
I have shared my code example below:
#mixin btnhover {
background-color: $bg-cl-blc;
color: $txt-cl-ff;
}
.btn-base {
font-size: 15px;
&:hover {
#include btnhover;
}
}
.btn-otln {
font-size: 15px;
&:hover {
#include btnhover;
}
}
**OUTPUT CSS**
.btn-base:hover {
background-color: #000;
color: #fff;
}
.btn-otln:hover {
background-color: #000;
color: #fff;
}
This is how Sass works - it allows for better organisation of the code, but this code is then compiled, retaining functionality and not caring about other aspects.
If you really care about how the output code is structured, I would suggest to create a separate style for the classes with the hover effect:
#mixin btnhover {
background-color: #000;
color: #fff;
}
.btn-base {
font-size: 15px;
}
.btn-otln {
font-size: 15px;
}
.btn-base:hover,
.btn-otln:hover {
#include btnhover;
}
But in this approach, the use of mixin (and Sass) is questionable (in this exact case).
Generally, when you use Sass (or any other compiled language), you don't really care about the output CSS.
This won't be your answer, but I want to show you another way to make a mixin
#mixin btnhover($back, $color) {
background: $back;
color: $color;
}
When you use it, you can plug in the values
#include mixin btnhover($bg-cl-blc, $txt-cl-ff)
That way you can use the mixin over and over in different places with different values
Just discovered this recently myself, it's a concept called 'placeholders' in SASS syntax (see example below). I've done my best to apply it to your situation below....
Put this in your .scss file:
$bg-cl-blc: #ff211a;
$txt-cl-ff: #fff;
$btn-base-size: 15px;
%btnhover {
background-color: $bg-cl-blc;
color: $txt-cl-ff;
}
%btn-common {
font-size: $btn-base-size;
}
.btn-base {
#extend %btn-common;
&:hover {
#extend %btnhover;
}
}
.btn-otln {
#extend %btn-common;
&:hover {
#extend %btnhover;
}
}
CSS output will look like this
.btn-otln:hover, .btn-base:hover {
background-color: #ff211a;
color: #fff;
}
.btn-otln, .btn-base {
font-size: 15px;
}
Great article written up on this here:
https://dev.to/kemotiadev/are-sass-mixins-really-that-lightweight-and-what-are-placeholders-119i
I have media query used in scss class, I would like to create media query and define all scss class in that media query. I have trouble accessing nested scss class in media query.
Here is my code
.data-one {
display: flex;
flex-wrap: wrap;
&.mobile {
width: 100%;
.data {
max-width: 100%;
}
}
.data {
height: 72px;
margin-right: 10px;
max-width: 224px;
// #media (max-width: layout-breakpoint-tablet-start) { -----------> This is the original code
// display: none;
// }
}
}
This is what I have tried but it is not working as expected
#media (max-width: layout-breakpoint-tablet-start) {
.data-one {
+.data {
display: none;
}
}
}
Sass 3.2 added the #content directive, which allows us to pass a content block into a mixin as following:
#mixin screen($size) {
$desktop: "(min-width: 1024px)";
$tablet: "(min-width: 768px) and (max-width: 1023px)";
$mobile: "(max-width: 767px)";
#if $size == desktop {
#media only screen and #{$desktop} {
#content;
}
}
#else if $size == tablet {
#media only screen and #{$tablet} {
#content;
}
}
#else if $size == mobile {
#media only screen and #{$mobile} {
#content;
}
}
#else {
#media only screen and #{$size} {
#content;
}
}
}
.wrapper {
margin: 0 auto;
width: 100%;
#include screen('tablet') {
width: 90%;
}
#include screen('desktop') {
width: 85%;
}
}
If you have any question about it feel free to ask.
I'm trying to update some old LESS style sheets into SCSS but am running into an issue translating media queries.
The LESS variables are as follows:
#lg: ~"(min-width: 1201px)";
#md: ~"(min-width: 993px)";
#sm: ~"(min-width: 769px)";
#xs: ~"(max-width: 768px)";
And are referenced in this manner:
.modal-dialog {
margin: 100px auto;
#media #md {
width: 880px;
}
}
I've translated this into the following SCSS variables:
$lg: "#{min-width: 1201px}";
$md: "#{min-width: 993px}";
$sm: "#{min-width: 769px}";
$xs: "#{max-width: 768px}";
and the following usage:
.modal-dialog {
margin: 100px auto;
#media ($md) {
width: 880px;
}
}
The code in question belongs to a .Vue component and is being compiled using SASS Loader FWIW. The code compiles (no errors) but the actual queries don't seem to be working. Thanks!
In SCSS / SASS the recommended approach to storing full media queries as variables is as follows:
$lg: "(min-width: 1201px)";
.modal-dialog {
margin: 100px auto;
#media #{$lg} {
width: 880px;
}
}
Which compiles to
.modal-dialog {
margin: 100px auto;
}
#media (min-width: 1201px) {
.modal-dialog {
width: 880px;
}
}
I've defined two mixins in SASS that allow me to place media queries easily. The problem I'm encountering is that I'm repeating myself frequently across many queries. That is to say, some of my style changes are the same for tablet and mobile breakpoints and others are different. Example:
.foo
float: left
width: 50%
+tablet()
float: none
display: block
width: 100%
+mobile()
float: none
display: block
width: 100%
Where my mixins are defined like this:
=tablet
#media (min-width: #{$mobile-width} + 1) and (max-width: #{$tablet-width})
#content
=mobile
#media (max-width: #{$mobile-width})
#content
I'd love to do something like this:
...
+tablet(), +mobile
float: none
display: block
width: 100%
That doesn't compile, so what is the best way to keep my SASS stylesheets DRY?
You can define mobile and tablet medias as strings and then concatenate these strings.
Scss can be easily converted to sass.
$mobile-width: 320px;
$tablet-width: 760px;
// Media queries as strings
$tablet: "(min-width: #{$mobile-width + 1}) and (max-width: #{$tablet-width})";
$mobile: "(max-width: #{$mobile-width})";
// Converts a list to a string with delimiters between elements
#function join-list($list, $separator: ", ") {
$result-string: "";
#each $item in $list {
// Index of the current item of `$list` list
$index: index($list, $item);
$result-string: $result-string + $item;
// If this is not the last item, adds separator
#if ($index != length($list)) {
$result-string: $result-string + $separator;
}
}
#return $result-string;
}
#mixin get-media($medias...) {
#media #{join-list($medias, " and ")} {
#content;
}
}
.foo {
float: left;
width: 50%;
#include get-media($mobile, $tablet) {
// or #include get-media($mobile) {
// or #include get-media($tablet) {
float: none;
display: block;
width: 100%;
}
}
Css output:
.foo {
float: left;
width: 50%;
}
#media (max-width: 320px) and (min-width: 321px) and (max-width: 760px) {
.foo {
float: none;
display: block;
width: 100%;
}
}
SassMeister demo.
As per #Stefan F's comment, the easiest thing to do in this case was to create a third mixin called (something like): +both() which encapsulated the mobile and tablet sizing. (I'm answering this myself only because he did not and it has been some time.)
Example:
=both
#media (max-width: #{$tablet-width})
#content
Usage:
.foo
float: left
width: 50%
+both()
float: none
display: block
width: 100%
Using Sass, I have the following mixin:
#mixin ss($property, $value, $value-smallscreen) {
#{$property}: $value;
#media screen and (max-height: $smallscreen-maxheight) {
#{$property}: $value-smallscreen;
}
}
.Header
{
#include ss('height', $RowHeight, $RowHeight-smallscreen);
#include ss('font-size', $HeaderFontsize, $HeaderFontsize-smallscreen);
}
The ‘problem’ that I have is that this generates two #media statements. That is, it generates the following CSS:
.Header {
height: 41px;
font-size: 11pt; }
#media screen and (max-height: 768px) {
.Header {
height: 35px; } }
#media screen and (max-height: 768px) {
.Header {
font-size: 9pt; } }
What I want to know, is there any way to both:
Keep the definitions together, to ensure that the styles are added for both big and small screens, and
Only have one '#media' section.
One of my current projects requires this approach to the SASS structure, and my solution has been to watch the CSS output using a CSS post-processor like Pleeease to watch the CSS files as SASS/Compass outputs them.
This allows live media query packing among other optimization.