Why don't Sass respect the order of CSS property using nested media query? - css

Why don't Sass respect the order of CSS property using nested media query?
Input Sass:
margin-top: 3px appears after the media query.
.myContainer {
margin: 1px;
#media only screen and (min-width: 768) {
margin: 2px;
};
margin-top: 3px;
}
Output CSS:
margin-top: 3px now appears before the media query.
.myContainer {
margin: 1px;
margin-top: 3px;
}
#media only screen and (min-width: 768) {
.myContainer {
margin: 2px;
}
}
In this example, you can see that the position of margin-top:3px is changed.
How could this happen and is it expected?

It is the expected result. Otherwise, it will have to create two separate classes like in the second snippet below. This wouldn't make sense. Try this:
.myContainer {
margin: 1px;
#media only screen and (min-width: 768px) {
margin: 2px;
};
& {
margin-top: 3px;
}
}
Output:
.myContainer {
margin: 1px;
}
#media only screen and (min-width: 768px) {
.myContainer {
margin: 2px;
}
}
.myContainer {
margin-top: 3px;
}

Related

Why doesn't this CSS get scoped by vue.js?

Inside a Vue single file component I have a scoped style section that looks like this:
<style scoped>
#media screen and (max-width: 767px) {
#suggestions, #form, #mapcontainer, #searchcontainer {
width: 100%; padding: 6px;
}
#mapcontainer div#mapx {
height: 400px
}
}
#media screen and (min-width: 768px) {
#workarea {
display: grid;
grid-template-columns: 1.5fr 1fr;
}
#mapcontainer {
grid-column: 1;
}
.blurb {
grid-column: 2;
margin-left: 12px;
}
#mapcontainer div#mapx {
height:600px;
width: 100%;
}
}
#suggestions tr { border-bottom: thin solid silver; }
#suggestions td { padding: 6px 3px 6px 3px }
#suggestions table { margin-bottom: 12px }
</style>
After checking the rendered source in Chrome's inspector I see the data tag in the rendered component like this:
<div data-s-0="" id="appspace">
but I don't see any of the expected changes to the CSS as documented in the section about scoped CSS in the vue.js docs
It seems to happen every time the scoped style contains a #media query.
What do I need to change so that styles stay scoped?

How to override all classes within in a media query?

I am building a custom .css, but I do not know, how to override a bunch of classes within a media query with "nothing". Means, I do not want this in my output, but also I don't want to delete this from the css as it needs to stay original. I also don't want to copy the whole bunch of classes and write "none" or "unset" behind every single attribute. Is there any solution for this. Thanks a lot.
/*original.css*/
#media only screen and (max-device-width: 720px) {
ol.accord li {
width: 100%;
}
.content {
height: 149px;
width: 50%;
}
ol.accord li h3 {
height: 30px;
width: 100%;
margin: 0;
border-right: none;
border-bottom: 1px solid #fff;
padding: 7px 10px;
}
}
/*custom.css*/
/*here should be nothing like it wouldn´t even exist in the original*/
You can write as many classes in the media query within the parenthesis.
Here is an example for this
Just define the class above and change as per your requirement as per screen size.
.custom_class1 {
height : 1px;
}
#media only screen and (max-device-width: 720px) {
ol.accord li {
width: 100%;
}
.content {
height: 149px;
width: 50%;
}
ol.accord li h3 {
height: 30px;
width: 100%;
margin: 0;
border-right: none;
border-bottom: 1px solid #fff;
padding: 7px 10px;
}
.custom_class1 {
height:70px;
}
.custom_class2 {
height:70px;
}
}

CSS for Media (755.4px - 991.4px)

Is it possible to write CSS for that affects a screen only when width is 755.4px - 991.4px?
I've tried the below but it also affects anything larger then #media (min-width: 767px) and (max-width: 768px)
#media (min-width: 755.4px) and (max-width: 991.4px)
#sliderText{
top:90px !important;
width: 85% !important;
}
#sliderText h1{
font-size: 1em !important;
}
}
The problem is, when the text is on a screen with width 755.4px - 991.4px, it goes on 2 lines and then it breaks the layout.
My original code is:
#ajax-content-wrap{
position:relative;
}
#sliderText{
position:absolute;
top:85%;
text-align:center;
margin-left:50px;
width:93%;
z-index:100;
}
#sliderText h1{
font-size: 4em;
font-weight: 600;
color: #31a6c7;
text-shadow: 2px 2px 2px #333;
}
#media (min-width: 767px) and (max-width: 768px) {
#sliderText{
top:90px !important;
width: 85% !important;
}
#sliderText h1{
font-size: 2em !important;
}
}
#media (max-width: 767px) {
#sliderText{
top: 84% !important;
width:75% !important;
//padding-left:50px;
//padding-right:50px;
}
#sliderText h1{
font-size: 1.7em !important;
}
}
You could try to do the following
Anything below 755.3px is small CSS
Anything above 991.4px is big CSS
Anything in the middle of that range is medium CSS
Here's a simplification of what that would look like:
/* Big CSS: Applies to everything unless overwritten */
#sliderText {
top: ;
width:
}
#sliderText h1 {
font-size:
}
/* Small CSS: Applies to small devices */
#media (max-width: 755.3px) {
#sliderText {
top: ;
width:
}
#sliderText h1 {
font-size:
}
}
/* Middle CSS: Applies to Devices in the middle of the range above */
#media (max-width: 991.4px) {
#sliderText {
top: ;
width:
}
#sliderText h1 {
font-size:
}
}

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.

Break out of scope

Ideally, I would like to do this :
#w: 4px;
#media (max-width:900px) {
#r: 3px;
}
#media (min-width:900px) {
#r: 5px;
}
.myclass {
border-radius: #w + #r;
}
This doesn't compile because #r isn't defined in the scope where I define .myclass. The obvious solutions are either to define .myclass inside the #media blocs or to copy the #media queries inside the definition of .myclass.
But as soon as you use #r in many classes, both solutions are messy and involve many duplications.
Is there a clean dry solution ?
Just use a mixin, that calculates the property values according to the mediaquery. It is unnecessary to do this via import.
LESS:
#w: 4px;
.bordermixin(#w,#r) {
.myclass{
border-radius: #w + #r;
}
}
#media (max-width:900px) {
.bordermixin(#w,3px);
}
#media (min-width:900px) {
.bordermixin(#w,5px);
}
CSS:
#media (max-width: 900px) {
.myclass{
border-radius: 7px;
}
}
#media (min-width: 900px) {
.myclass{
border-radius: 9px;
}
}
I found a solution, based on #import, which lets me keep dry.
I make two files :
classes.less
#w: 4px;
.myclass {
border-radius: #w + #r;
}
mediawidth.less
#media (max-width:900px) {
#r: 3px;
#import "classes.less";
}
#media (min-width:900px) {
#r: 5px;
#import "classes.less";
}
Generated CSS :
#media (max-width: 900px) {
.myclass {
border-radius: 7px;
}
}
#media (min-width: 900px) {
.myclass {
border-radius: 9px;
}
}
This way I don't have to repeat the many classes definition but only the import.
I accepted Martin's answer, which is much cleaner in the most common case when there are only a few numbers of variables to pass. My solution might be dryer and cleaner as soon as you have more variables and when your classes are defined in many files.

Resources