Want to change my variable value on media queries but the value doesn't change at all. Why is that?
I tried to simple change the value on the media query but nothing happens.
// My variables
// All these variables works outside the media queries
$marq-width: 80vw; // using this one
$marq-height: 20vh;
$marq-elm-displayed: 5;
$marq-elements: 9;
$marq-elm-width: calc( #{$marq-width} / #{$marq-elm-displayed} );
$marq-animation-duration: calc(#{$marq-elements} * 3s);
$color: black;
$break-md: 600px;
// Here is my problem
#media(max-width: 600px) {
body {
background: red; // this works
}
$marq-width: 100vw; // this not work
}
Here is my codepen link: https://codepen.io/G-ROS/pen/JjPzovR?editors=0100
You can shrink the viewport on <= 600px and see the background changing to red but the variable did not changes at all. I expect the variable changes has the value "100vw", but it remains with the original value of "80vw".
You are missing to define width you define the variable but not width.
chnaging only variable will not impact on css you will use that variable to such css like below.
#media(max-width: 600px) {
body {
background: red; // this works
}
$marq-width: 100vw; // this will not work
.marquee{width:$marq-width;} // this works
}
Check the codepen
Related
Is there a way to modify a previously-declared CSS variable inside a media query with just vanilla CSS? What I'm after would look like this (which of course doesn't work as the variables all get computed in the end):
#container {
--elem-size: 20px;
}
#media only screen and (min-width: 800px) {
#container {
--elem-size: calc(var(--elem-size) * 2);
}
}
I'm aware that it would be possible to declare a "base variable" (e.g. --base-elem-size) and then use it to generate new variable values for different viewports. However, I'm working with a very large number of CSS variables which makes it undesirable to create a duplicate base set out of them. The ideal solution would be able to "modify" a previously-declared value.
This might be far from ideal but to some degrees does define the style in one line. It uses fallback values of CSS variables.
Open full screen and change window size to see the result:
:root {
--elem-size-base: 50px;
}
#container {
/* 👇 Fallback for base value, optional 2nd fallback for no variable value */
width: var(--elem-size, var(--elem-size-base, 50px));
height: var(--elem-size, var(--elem-size-base, 50px));
outline: 2px solid #000;
background-color: pink;
}
#media only screen and (min-width: 768px) {
#container {
/* 👇 This variable for various #media */
--elem-size: calc(var(--elem-size-base) * 2);
background-color: lightblue;
}
}
#media only screen and (min-width: 1024px) {
#container {
/* 👇 This variable for various #media */
--elem-size: calc(var(--elem-size-base) * 4);
background-color: lightgreen;
}
}
<div id="container"></div>
I think having base CSS variables would make your CSS much more readable and easier to maintain, specially if you are working with a big codebase.
May be something like this:
:root {
/* Define you base variables */
--font-size-default: 16px;
--font-size--large: calc(var(--font-size-default) * 1.25);
/* Assign the base variable to the element variables */
--elem-size: var(--font-size-default);
}
#media screen and (min-width: 840px) {
:root {
/* Change base variable used for element variable */
--elem-size: var(--font-size--large);
}
}
This allows you to set a base font-size variable and one (or more) "variants" of that variable, which you can then use on your whole project
I would suggest you look into something like the Open Props (which has some really great ideas for what base variables can be and how to use them)
I use CSS grid and Sass, and I use different grid layouts for different screen sizes (phone, tablet, desktop). But for some pages, I would like the same layouts but chosen at slightly bigger or smaller screens than for other pages.
Is something like that possible? Or am I approaching it from the wrong angle? My current solution (see below) works, but duplicates the styles a lot.
In more detail:
I have 3 different grids that are chosen according to the screen size.
.hero {
&__container {
grid-template-areas:
"header"
"image"
"text";
}
#media min-width: 1000px {
grid-template-areas:
"header header header"
"text ... image"
"text ... image";
}
// other definitions for this screen size
}
#media min-width: 1300px {
grid-template-areas:
"header header image"
"text ... image"
"text ... image";
}
// other definitions for this screen size
}
}
&__header {
grid-area: header;
font-size: 2.5rem;
#media min-width: 1000px {
font-size: 2.8rem;
}
#media min-width: 1300px {
font-size: 3.2rem;
}
}
...
}
They are used in about 20 similar web pages.
<div class="page_a">
<div class="hero">
<div class="hero__container">
<div class="hero__header">...</div>
<div class="hero__text">...</div>
<div class="hero__image">...</div>
</div>
</div>
</div>
The layout is very similar, but I would like to switch to different layouts at a different point based on the specifics of the content: the header text length, the size & importance of the image, etc.
What I would like to do is something like this:
.page_a {
.hero {
// redefine nothing, use defaults
}
}
.page_c {
.hero {
// the header is longer so we need a bigger screen to switch to the biggest layout
// somehow say that the 1300px layout should be used from 1500px
}
}
The only thing I managed to do is to simply redefine all the grids at each possible point (the default points + the custom points), which means the code is very repetitive:
.page_c {
.hero {
// use 1000px layout also for 1300px - the whole thing has to be repeated
#media min-width: 1300px {
grid-template-areas:
"header header header"
"text ... image"
"text ... image";
}
// other definitions for this size
}
// use 1300px layout for 1500px - the whole thing has to be repeated
#media min-width: 1500px {
grid-template-areas:
"header header image"
"text ... image"
"text ... image";
}
// other definitions for this size
}
}
}
Which means that every time I change some layout I have to go to all the places it is used at various size and change it too.
Here you go...
Your problem could be solved with SASS or SCSS, more precisely with a #mixin. I'm using SCSS because I'm more familiar with it, but you could also use SASS.
What is a #mixin?
As stated on SASS official website: Mixins allow you to define styles that can be re-used throughout your stylesheet. First you define a #mixin then you call it later in your code with an #include. Every #mixin should have a unique name. For example: define a #mixin layout_600 and call it with an #include layout_600.
Two things are important when defining a #mixin:
A #mixin should be defined before you call it with an #include. Otherwise, SCSS will try to call something that isn't defined yet (it is defined but later in your stylesheet).
A #mixin should be defined outside of your nested code (ideally at the top of your stylesheet). If you define a #mixin inside your nested code, you won't be able to call it later when you want to change default styles. The easiest way for you to understand what I mean is to show you the correct way and the wrong way.
Correct:
#mixin layout_600 {
font-size: 3rem;
color: blue;
font-weight: 700;
}
.hero {
&__header {
#media (min-width: 600px) {
#include layout_600;
}
}
}
.page_b {
.hero {
// Use the 600px layout also for the 1000px.
&__header {
#media (min-width: 1000px) {
// It will work.
#include layout_600;
}
}
}
}
Wrong:
.hero {
&__header {
#media (min-width: 600px) {
#mixin layout_600 {
font-size: 3rem;
color: blue;
font-weight: 700;
}
}
}
}
.page_b {
.hero {
// Use the 600px layout also for the 1000px.
&__header {
#media (min-width: 1000px) {
// It won't work.
#include layout_600;
}
}
}
}
You need to write a #mixin for each layout that you want to have (e.g. 600px, 1000px). You only need to do it once for every layout but you can call a particular #mixin n-times. This is perfect because:
you don't have to re-write your code, you just call a particular #mixin with an #include as many times as you want and
if you want to change your styling, you do it just once in your #mixin and the style will be changed in every place that is referring to this #mixin.
Working example
Before changing the default style
I defined three #mixins like this:
when: window width < 600px,
when: 600px < window width < 1000px and
when: window width > 1000px.
As you can see, the font-size and the color is different at different window width. The font is getting bigger and the color goes from black to blue to red as the window is getting wider. By the way, in the right upper corner I added a div that shows the current window width.
Here's a live demo before changing the default style.
After changing the default style
I decided that for the page_b I would use the 600px layout (i.e. #mixin layout_600) also for the 1000px. This can easily be done by calling the #mixin layout_600 with the #include layout_600 like this:
.page_b {
.hero {
// Use the 600px layout also for the 1000px.
&__header {
#media (min-width: 1000px) {
#include layout_600;
}
}
}
}
As you can see, the style of the page_b when window width is actually 1000px is the same as if the window width is 600px (smaller font and blue color).
Here's a live demo after changing the default style.
Customizing a #mixin
Also, it's possible to customize a #mixin if you want. For example, I used the 600px layout (i.e. #mixin layout_600) but changed the color from red to green. This can be done like this:
.page_b {
.hero {
// Use the 600px layout also for the 1000px.
&__header {
#media (min-width: 1000px) {
#include layout_600;
color: green; // Customize the mixin.
}
}
}
}
As you can see, the color should be blue (as in #mixin layout_600) but it's green.
Here's a live demo after customizing a #mixin.
I want to solve my issue only using pure CSS.
Here's the problematic code that I have:
#if (100vh > 830px) {:root { --cwv:100vh;}}
#else {:root { --cwv: 830px;}}
What I'm trying to do: if browser window size is smaller than 830px, the "- -cvw" (custom width variable/ unit) should be relative (another problem that my code probably has) to 830px rather than 100vw (built-in viewport "vertical width" unit), as the elements on the page get too small.
I know I can use multiple other ways to solve this problem using other languages, but I am just wondering how to make the CSS code work - as it is supposed to - according to the places that I have researched:
CSS custom properties (variables) - states that variables are declared in the following manner: :root{--variable-name: variable-value;}
CSS Conditionals (if/ else statements)
What am I doing wrong? I expect that I have multiple syntax errors in my code (that I've provided above) too... :/
Use media queries max-width.
Example:
Default --cwx set to viewport width:
:root{
--cwv: 100vw;
}
In case where viewport width is lesser or equal 830px, set --cwx to 830px:
#media all and (max-width: 830px){
:root{
--cwv: 830px;
}
}
Finally, example's black bar will be set to ½ of --cwx, thus ½ of viewport width, but not less than ½ of 830px (=415px):
:root{
--cwv: 100vw;
}
#media all and (max-width: 830px){
:root{
--cwv: 830px;
}
}
body{
margin: 0;
}
:root::after{
content: "";
display: block;
background: black;
height: 10px;
width: calc(var(--cwv) * .5);
}
use media queries for window size like this below
#media screen and (min-width : 830 px) {
/* your code */
}
This is my class:
.center-block-xs {
// This style is given to an image. I want the image to keep
// its original CSS (whatever the default display and margin
// is for an image) unless the screen size fits within the
// media query below.
}
#media(max-width:767px) {
.center-block-xs {
display: block;
margin-right: auto;
margin-left: auto;
}
}
Basically, what I want to do is this: If an element has the class .center-block-xs, then the CSS should be applied to the element only if the screen size is within the media query. I know I can do this:
#media(max-width:767px) {
.color-red-xs { color: red; }
}
#media(min-width:768px){
.color-red-xs { color: black; }
}
In which case the color is red only if the screen size is within the media query, otherwise it gets overridden with the black color. But I don't want to have to override any CSS in my case; I just want the CSS to be what it normally would be unless the screen size is within the media query. Is this possible?
What you're describing is precisely how CSS and media queries work by default. If you define a class of .center-block-xs within a media query, that definition will only be applied to elements that a) have that class, when b) the media-query rules apply. There is no need to explicitly define the alternative case(s) if you want inherited styles to be applied.
Just set the default color to what you want, such as the following:
.center-block-xs {
color: red;
}
Then set a minimum width for the CSS change, like so:
#media(min-width: 767px) {
.center-block-xs {
color: black;
}
}
when the screen hits a width of 767px, the text will change.
I am looking for a solution where I define 1 variable globally and than overwrite it inside a media query - without putting the entire code in it (like LESS CSS set variables in media query?).
I thought something like that(defining):
#media (min-width: 768px) {
#BWInputHeight: 40px;
}
#media (max-width: 768px) {
//responsive screens
#BWInputHeight: 20px;
}
And using it like that:
.dataTables_filter input {
.form-control;
max-width: 135px;
display: inline-block;
height: #BWInputHeight;
padding: 1px 6px;
margin-right: 15px;
}
The problem here, "#BWInputHeight" is a undeclared variable. How can I solve this with LESS ?
You can sort of achieve this by using list arrays for each property and screen-width (like the below sample):
#BWInputHeight: '20px','40px','60px'; // Height of the button for min-width=320 and min-width=768 respectively
#minwidths: '320px','768px','1024px'; // The widths for which you need the media queries to be created
.loop-column(#index) when (#index > 0) { // Loop to iterate through each value in #minwidths and form the corresponding output
.loop-column(#index - 1);
#width: extract(#minwidths, #index); // extracts width based on array index
#media (min-width: e(#width)){
.dataTables_filter input{
height: e(extract(#BWInputHeight,#index)); // extracts button height for the corresponding screen width
max-width: 135px;
display: inline-block;
padding: 1px 6px;
margin-right: 15px;
}
}
}
.loop-column(length(#minwidths)); // calling the function
Demo in Code-pen - Modify output area width to see difference and click the eye icon in CSS tab to see compiled CSS.
Note: As per this Stack Overflow thread, both dotless and less.js should be 99% compatible and hence I have given this answer. In case this doesn't work for you, I will happily have this answer removed.