JavaScript and CSS have been coexisting for over 20 years. But sharing data between them is very difficult. Of course there are a lot of attempts. But what I had in mind was something simple and intuitive - not involving structural changes, but using CSS custom properties or even Sass variables.
Custom Properties should come as no surprise here. One thing that browsers have been doing for as long as they've supported it is working with JavaScript toset and manipulate values.
But specifically, there are a few ways we can make JavaScript work with custom properties. You can set the value of a custom property usingsetProperty
:
document.documentElement.style.setProperty("--padding", 124 + "px"); // 124px
We can also usegetComputedStyle
in JavaScript to retrieve CSS variables. The logic behind this is very simple: custom properties are part of the style, so they are part of the calculated style.
getComputedStyle(document.documentElement).getPropertyValue('--padding') // 124px
is the same asgetPropertyValue
. This way we can get the custom attribute value from the inline style of the HTML tag.
document.documentElement.style.getPropertyValue("--padding'"); // 124px
Please note that custom attributes have scope. This means we need to get the calculated style from a specific element. As we defined the variables earlier in:root
, we place them on the HTML element.
Sass is a preprocessed language, which means it is turned into CSS before it becomes part of the website. So they cannot be accessed from JavaScript in the same way as CSS custom properties (they can be accessed in the DOM in computed styles).
We need to change this by modifying our own build process. I suspect that in most cases it won't be necessary to do much since the loader is usually already part of the build process. But if that's not the case for your project, we'll need three modules that can import and translate Sass modules.
looks like this in the Webpack configuration:
module.exports = { // ... module: { rules: [ { test: /\.scss$/, use: ["style-loader", "css-loader", "sass-loader"] }, // ... ] } };
In order to enable Sass (or in this case, SCSS specifically ) variables are available in JavaScript, we need to "export" them.
// variables.scss $primary-color: #fe4e5e; $background-color: #fefefe; $padding: 124px; :export { primaryColor: $primary-color; backgroundColor: $background-color; padding: $padding; }
:export
block is used by webpack to import variables. The benefit of this approach is that we can rename the variables using camelCase syntax and then choose what to expose.
Then, import the Sass file (variables.scss
) into JavaScript so you can access the variables defined in the file.
import variables from './variables.scss'; /* { primaryColor: "#fe4e5e" backgroundColor: "#fefefe" padding: "124px" } */ document.getElementById("app").style.padding = variables.padding;
It's worth mentioning some restrictions on the:export
syntax:
exportedKey
is copied, the last one (in source order) takes precedence.exportedValue
can contain any valid characters (including spaces) in CSS declared values.exportedValue
does not need to be quoted because it is already treated as a text string.There are many ways to easily access Sass variables in JavaScript. I prefer this method of shared breakpoints. Below is mybreakpoints.scs
file, which I later imported into JavaScript so that I could get consistent breakpoints using thematchMedia()
method.
// Sass variables that define breakpoint values $breakpoints: ( mobile: 375px, tablet: 768px, // etc. ); // Sass variables for writing out media queries $media: ( mobile: '(max-width: #{map-get($breakpoints, mobile)})', tablet: '(max-width: #{map-get($breakpoints, tablet)})', // etc. ); // The export module that makes Sass variables accessible in JavaScript :export { breakpointMobile: unquote(map-get($media, mobile)); breakpointTablet: unquote(map-get($media, tablet)); // etc. }
Animation is another use case. The duration of an animation is usually stored in CSS, but more complex animations require help from JavaScript.
// animation.scss $global-animation-duration: 300ms; $global-animation-easing: ease-in-out; :export { animationDuration: strip-unit($global-animation-duration); animationEasing: $global-animation-easing; }
Please note that when exporting variables, I used a customstrip-unit
function. This allows me to easily parse the content in JavaScript.
// main.js document.getElementById('image').animate([ { transform: 'scale(1)', opacity: 1, offset: 0 }, { transform: 'scale(.6)', opacity: .6, offset: 1 } ], { duration: Number(variables.animationDuration), easing: variables.animationEasing, });
This makes it easy to exchange data between CSS, Sass and JavaScript. Sharing variables like this keeps the code simple and less verbose.
Of course there are multiple ways to achieve the same goal. Les Jamesshared an interesting approachthat allows Sass and JavaScript to interact via JSON. I may be biased on this, but I find the method presented here to be the simplest and most intuitive. No need to make crazy changes to the CSS and JavaScript you already use and write.
English original address: https://css-tricks.com/getting-javascript-to-talk-to-css-and-sass/
Author: Marko Ilic
For more programming-related knowledge, please visit:Programming Video! !
The above is the detailed content of Let's take a look at how JavaScript interacts with CSS and Sass. For more information, please follow other related articles on the PHP Chinese website!