In our current design, form elements get styled differently on a mobile device:
#media screen and (max-width: 759px) {
form label {
display: block;
float: none;
}
/*There's more...*/
}
Given the limited screen space, we're basically forcing a vertical form layout (#3-4 in this classic uxmatters link).
Because some form labels have to be insanely verbose For sensible reasons, we now want to apply this style to some desktop forms, i.e. outside of scope of the media query. This, however, is invalid SASS syntax:
#media screen and (max-width: 759px), .vertical-form {
/*...*/
}
How can the ruleset be applied on output within the media query and to .vertical-form form label (or, ideally, form.vertical-form label) elements?
Media queries are not selectors, they are special language constructs. You can't combine them with anything other than media queries. You will have to use a mixin to do what you're asking for because extends don't work across media queries either.
#mixin vertical-form {
label {
display: block;
float: none;
}
}
#media screen and (max-width: 759px) {
form {
#include vertical-form;
}
}
.vertical-form {
#include vertical-form;
}
Related
trying to figure out what the best path moving forward as I'm not wrapping my default styling with a media query since i'm assuming mobile. However, for desktop im recognizing i'm styling selectors that aren't required for my desktop.
myclass {
background-color:#FF0000;
transform: translateX(-50%);
clip-path: //some kind of clip path
#include media(">tablet") {
background-color: initial;
color: initial;
clip-path: initial;
transform: initial;
}
}
This is just an example class, but i find myself having to repeatedly use initial to reset. Any other advice instead of also wrapping my mobile styling in a media mixin?
Suppose I have the following scss variables:
$until-xs: "(max-width: 377px)";
$until-sm: "(max-width: 640px)";
...
$until-xl: "(max-width: 4000px)";
And based on them the following helper css classes are constructed:
.until-sm {
display: none;
#media #{$until-xs} {
display: block !important;
}
}
.until-md {
display: none !important;
#media #{$until-sm} {
display: block !important;
}
}
/* plus a lot of classes like this */
I am trying to create a mixin that would help me define those classes more easily by passing the $until-x variable as an input to the mixin, like so:
#mixin until($x) {
display: none;
#media #{'$until-'#{$x}} {
display: block !important;
}
}
Such that the classes above will be defined simply as:
.until-xs { #include until($until-xs); }
The problem is the media variable inlining part does not evaluate the way I wanted, like:
#{'$until-'#{$x}} (when x is 'xs') =>
#{'$until-xs'} =>
#{$until-xs} =>
(max-width: 377px)
Any way I can achieve this? Since this can be applied in multiple places in my project I am more interested in the possibility of inlining vars like this than the solution to the particular problem from the example.
Instead of defining lots of variables like $until-xs, $until-sm and so on, you can define a map that contains information of your medias like the code below:
#use "sass:map";
$until-var: ("xs": "(max-width: 377px)", "sm": "(max-width: 620px)", "md": "(max-width: 807px)");
#mixin until($x) {
display: none;
#media #{map.get($until-var, $x)} {
display: block !important;
}
}
/* using that in your classes */
.until-xs { #include until("xs"); }
.until-sm { #include until("sm"); }
I'm not sure what you mean by inlining vars! But if you want a single mixin that works for different medias, I think that works.
I'm creating a React application that has a hero display on the landing page that displays one of three images: [hero-1.jpg, hero-2.png, hero-3.png] based on the users viewport screen size.
I have been unsuccessful trying to find resources online that show a DRY method for achieving this, for the sake of participation, I'll leave this code that I attempted that - in theory made sense to me.
N.B. I am extremely new to Sass/Scss
snippet.html
<section className="hero is-fullheight has-background-black">
<div className="hero-body">
<div className="container">
</div>
</div>
</section>
hero.scss
$i: 1;
$breakpoint-phone: 480px;
$breakpoint-tablet: 768px;
$breakpoint-desktop: 1024px;
#mixin modifier ($i:1) {
#content;
#media only screen and (max-width:$breakpoint-phone) { $i: 2; }
#media only screen and (max-width:$breakpoint-tablet) { $i: 3; }
#media only screen and (max-width:$breakpoint-desktop) { $i: 1; }
}
.hero {
background-position: center;
background-size: cover
}
#include modifier {.hero {background-image: url('../assets/hero-#{$i}.jpg');}}
Methodology:
Display content by default (which is pulled from #include).
Mixin modifier will modify the $i passed to the mixin, which is interpolated in the image path.
Expected Result:
Based on each breakpoint, $i will be set to the appropriate value and change the background image dynamically.
Actual Result:
The global $i is used, and the web page displays hero-1.jpg.
There are a few ways you can achieve this. If I was going about this, this is how I would do it.
Also, it would be very wise to practice mobile first development. Use min-width and go up instead of using max-width going down. The way you currently have it structured would mean you wouldn't have a valid URL if that $i variable wasn't set at 1 at the top of your document. Writing SASS or CSS will be much easier this way once you get used to it.
$tablet: 768px;
$desktop: 1024px;
#mixin hero-image() {
.hero {
background-position: center;
background-size: cover;
background-image: url('../assets/hero-2.jpg');
#media screen and (min-width: $tablet) {
background-image: url('../assets/hero-3.jpg');
}
#media screen and (min-width: $desktop) {
background-image: url('../assets/hero-1.jpg');
}
}
}
#include hero-image();
You're still going to have to write the background-image property 3 times. The way you were doing it was close, but you would have had to #include modifier() 3 times in your consuming scss file. At the end of the day SASS compiles to CSS. You could potentially use a SASS function or For Loop to achieve this, but mixins can get really complicated and powerful, but also incredibly difficult to read and understand. Here's what the mixin I just showed you compiles to in CSS.
.hero {
background-position: center;
background-size: cover;
background-image: url("../assets/hero-2.jpg");
}
#media screen and (min-width: 768px) {
.hero {
background-image: url("../assets/hero-3.jpg");
}
}
#media screen and (min-width: 1024px) {
.hero {
background-image: url("../assets/hero-1.jpg");
}
}
I recommend putting your SCSS/SASS into this compiler to see your results before compiling your actual project.
https://www.sassmeister.com/
Even though you are repeating background-image 3 times inside of the mixin this is very much still DRY code because you can include that one mixin everywhere your images will be shown and if you need to edit it, you can edit it in one place.
I've set up some variables in SASS as follows:
// fundamental layout variables
$raw-layout-var-1: 60px;
$raw-layout-var-2: 200px;
// calculated layout variables
$calc-layout-var-1: #{$raw-layout-var-1} + #{$raw-layout-var-2};
I am attempting to use these variables with media queries so I can do something like the following, and have the calculated variables and the rest of the stylesheet update when the relevant criteria are met. I would like to be able to override the fundamental or calculated variables as I need.
#media only screen and (min-height: 500px) {
$raw-layout-var-1: 120px;
#media only screen and (min-width: 500px) {
$raw-layout-var-2: 100px;
}
Currently I have a workaround where all updates to variables use the !global keyword to update them globally, but this results in a somewhat complex setup where the fundamental variables, calculated variables, and the main css sheet are placed in mixins, to be called in each individual media query:
#mixin reset-raw-vars() {
$raw-layout-var-1: 60px !global;
$raw-layout-var-2: 200px !global;
}
#mixin update-calc-vars() {
$calc-layout-var-1: #{$raw-layout-var-1} + #{$raw-layout-var-2} !global;
}
#mixin add-main() {
div {
width: $calc-layout-var-1;
height: $raw-layout-var-1;
}
}
#media only screen and (min-width: 500px) {
#include reset-raw-vars(); // resets the raw variables in case these were changed globally in a previous media query
// here you can change any fundamental variables you need
#include update-calc-vars(); // recalculates calculated variables
// here you can override how any calculated variables are made
#include add-main(); // update the rest of the stylesheet with new layout
}
Even worse, if I have a pair of media queries such as those shown in the second code block, I have to manually create a hybrid with both min-height and min-width in order to apply both sets of conditions. Clearly this isn't DRY and could get seriously out of control with even slightly complex responsive pages. I can see from Using Sass Variables with CSS3 Media Queries that SASS doesn't have this functionality - is there a better way than I've outlined above?
When using MJML to create the email templates, it provides the carousel feature in email templates. Here is the code from the their sample. (icon-width and tb-width were added by me)
<mj-carousel icon-width="30px" tb-width="20px">
<mj-carousel-image src="https://www.mailjet.com/wp-content/uploads/2016/11/ecommerce-guide.jpg" />
<mj-carousel-image src="https://www.mailjet.com/wp-content/uploads/2016/09/3#1x.png" />
<mj-carousel-image src="https://www.mailjet.com/wp-content/uploads/2016/09/1#1x.png" />
</mj-carousel>
As you see, the attribute tb-width controls the width thumbnails of the carousel, I want to change the value of tb-width to be smaller when it goes into mobile screen, otherwise I will have to stick to one value cross all screen sizes.
I tried this:
#media all and (max-width: 480px) {
[tb-width] {
width: 50px !important;
} // this is not working
}
Then I tried this based on the official document
#media all and (max-width: 480px) {
div[style*="tb-width:20px;"] {
width: 300px !important;
}
}
None of above code works.
How do you guys solve this problem? Thanks in advance.
Thanks for #dermothghes from mjml slack channel, here is the solution:
All these mjml components will have a corresponded css class in the outputted HTML, what we need to do is to compile the .mjml file first and find the corresponded css class from the output.
In my question, this should work:
#media all and (max-width: 480px) {
.mj-carousel-thumbnail {
width: 50px !important;
}
}
.mj-carousel-thumbnail is the generated class from mj-carousel-thumbnail mjml component.