2

I am looking to define a variable for my media queries across my SASS/CSS files.

The general structure of my sass files for a given page are

  • file.scss
  • _variables.scss
  • _colors.scss
  • _web.scss
  • _tablet.scss
  • _mobile.scss

file.scss has nothing but @use statements (@use over @import because the SASS team is headed away from @import), _variables/_colors have my CSS variables for element properties and colors (respectively) and the remaining 3 files (I'll refer to them generically as _layout.scss) have the layouts and other features per screen size.

Since I have multiple file.scss files, and each corresponding _layout.scss needs a @media query with max-width set, I would ideally like a global variable I can use in an _global.scss file to include in all the _layout.scss files consistently rather than redefine the same max-widths manually in each of them.

I cannot use a CSS variable (I don't think) because those need to be defined inside a selector, and that doesn't import well into the @media query (I tried this including just defining the variable in :root to no avail).

A local sass variable (notably only the pre-processor can see this which is kind of a bummer, but I could live with that) will work as is shown in this CSS Tricks post, but this doesn't really provide a global solution where I could simply use the value.

That is all to say I want a global sass variable (i.e. defined in only one file, but used in may files) where I can then use @media(max-width: var(--my-variable)) or @media(max-width: $my-variable) in my local _layout.scss files for a consistent use of the same values.

I attempted to create a _global.scss file with my declarations and @use them in my _layout.scss files, but my sass compiler (Dart v 1.25.0) doesn't recognize this, and while I can do this using @import, the same reason as above (@import going away) makes me reticent to do that if there's an actual good solution out there which are going to be stable through that change.

An example of how this is structured in page.scss:

@use 'web';
@use 'tablet';
@use 'mobile';
//Note only one of the two below is present at once
@use '../App/global'; //doesn't work
@import '../App/global'; //does work

My styles folder structure

  • styles
    • AppFolder

       - _colors.scss
       - _global.scss
       - _variables.scss
       - App.scss
      
    • GenericComponentFolder

       - \_colors.scss
       - \_mobile.scss
       - \_tablet.scss
       - \_web.scss
       - file.scss
      

_global.scss looks like this (recall we're using SASS variables since CSS variables need to be defined inside a selector):

$small-laptop: 1400px;

$tablet: 1023px;

$mobile: 765px;

$small-mobile: 400px;

in _web.scss we use the variables like so

@media(max-width: $small-laptop) {
.my-selector {
height: 10%;
} 
13
  • 2
    Why don't you declare all your variables in file.scss? You seem to import them everywhere, so wouldn't that be a good place? Commented Jul 9, 2020 at 13:09
  • 1
    It's a maintainability question, the variables are global to the entire site, updating a ton of sass files when it's a single static value is a pain. One of the goals of doing a lot of these things in CSS rather than code is also that non-technical folks like designers can update things like fonts, line sizes, and (most importantly) colors (among other things) by updating the single global file (the _variables.scss holds variables specific to a single component and are "private" implementation details for that component). It reduces overhead and reduces the skill/tool set needed to do the work Commented Jul 9, 2020 at 13:31
  • I would honestly use @import for this. @import is not going to be deprecated anytime soon - the SASS team is saying October of 2021 and then ending support a year later. So, there is at least 2 years to convert to @use if your project is still being maintained. The good solution is that @use and @import will work at the same time, so you can gradually shift to @use Commented Jul 24, 2020 at 15:28
  • 1
    The problem is when you use @use you need to namespace the variable using the file name it comes from. You should be doing this @media(max-width: global.$small-laptop)... Commented Jul 24, 2020 at 17:10
  • 1
    Thank you, that's perfect/exactly what I needed! If you want to put that in an answer I'd happily accept it. Commented Jul 24, 2020 at 17:15

1 Answer 1

2

When using @use you need to include the namespace of the file prior to the variable.

In your structure, you are declaring your variables in _global.scss, so any variable that comes from that file, you need to namespace with that file name.

In your case, you have in _global.scss:

$small-laptop: 1400px;
$tablet: 1023px;
$mobile: 765px;
$small-mobile: 400px;

So, when use it in your code, you do this global.$variable:

@media(max-width: global.$small-laptop) {
    .my-selector {
        height: 10%;
   }
}

This is the main benefit to using @use in the future. You can have very generic variable names that won't conflict with anything else because you can call them from specific files. You could technically have 20 variables with the name $test, but depending on the context that you use them, you would call $test from whatever declaration/partial file that corresponds to the context.

@import is global, so once you declare a variable, it's global. And if that variable gets assigned somewhere else, you'll run into conflicts and unintended overwriting.

Sign up to request clarification or add additional context in comments.

1 Comment

For others reading this in the future, I also found it helpful to @forward my global variables from my local _variables file for some consistency in how I accessed things and making things bottleneck through the _variables files. I could see the flexibility of not doing that if you wanted to re-use the same variable name in your local variables file or from multiple sources, but this happened to meet our project's coding standards pretty well, so it's worth considering as a stylistic implementation point.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.