От автора: JavaScript и CSS живут вместе более 20 лет. И все же было невероятно сложно обмениваться между ними данными. Конечно, были хорошие попытки. Но я имею в виду что-то простое и интуитивно понятное — что-то, что не связано со структурными изменениями, а скорее включает использование пользовательских свойств CSS и даже переменных Sass.
Пользовательские свойства CSS и JavaScript
Пользовательские свойства не должны быть чем-то удивительным. С тех пор, как браузеры начали их поддерживать, им всегда удавалось работать с JavaScript, чтобы устанавливать значения и манипулировать ими.
В частности, мы можем использовать JavaScript с пользовательскими свойствами несколькими способами. Мы можем установить значение пользовательского свойства, используя setProperty:
document.documentElement.style.setProperty("--padding", 124 + "px"); // 124px
Мы также можем получить переменные CSS, используя в JavaScript getComputedStyle. Логика довольно проста: пользовательские свойства являются частью стиля, поэтому они являются частью вычисляемого стиля.
getComputedStyle(document.documentElement).getPropertyValue('--padding') // 124px
Что-то наподобие работы с getPropertyValue. Это позволило нам получить значение пользовательского свойства из встроенного стиля HTML разметки.
document.documentElement.style.getPropertyValue("--padding'"); // 124px
Обратите внимание, что пользовательские свойства ограничены. Это означает, что нам нужно получить вычисляемые стили из определенного элемента. Так как мы ранее определили переменную для :root, мы получаем их для элемента HTML.
Переменные Sass и JavaScript
Sass — это язык предварительной обработки, то есть он превращается в CSS еще до того, как становится частью веб-сайта. По этой причине доступ к ним из JavaScript так же, как и к пользовательским свойствам CSS, которые доступны в DOM в виде вычисляемых стилей, невозможен.
Нам нужно изменить процесс сборки, чтобы сделать это. Я думаю, что в большинстве случаев в этом нет особой необходимости, поскольку загрузчики часто уже являются частью процесса сборки. Но если это не так в вашем проекте, нам нужны три модуля, которые способны импортировать и переводить модули Sass.
Вот как это выглядит в конфигурации webpack:
module.exports = { // ... module: { rules: [ { test: /\.scss$/, use: ["style-loader", "css-loader", "sass-loader"] }, // ... ] } };
Чтобы сделать переменные Sass (или, в частности, в данном случае SCSS) доступными для JavaScript, нам нужно их «экспортировать».
// variables.scss $primary-color: #fe4e5e; $background-color: #fefefe; $padding: 124px; :export { primaryColor: $primary-color; backgroundColor: $background-color; padding: $padding; }
Блок :export – это магия WebPack, которая используется, чтобы импортировать переменные. Что хорошо в данном подходе, так как мы можем переименовать переменные, используя синтаксис camelCase, и выбрать то, что мы извлекаем.
Затем мы импортируем файл Sass (variables.scss) в JavaScript, предоставляя доступ к переменным, определенным в файле.
import variables from './variables.scss'; /* { primaryColor: "#fe4e5e" backgroundColor: "#fefefe" padding: "124px" } */ document.getElementById("app").style.padding = variables.padding;
Есть некоторые ограничения для синтаксиса :export, о которых стоит упомянуть:
Он должен быть на верхнем уровне, но может находиться в любом месте файла.
Если в файле он встречается более одного раза, ключи и значения объединяются и экспортируются вместе.
Если конкретный exportedKey дублируется, последний (по порядку в источнике) имеет приоритет.
exportedValue может содержать любой символ, который действителен в объявлении значений CSS (включая пробелы).
exportedValue не нужно заключать в кавычки, потому что он уже рассматривается как литеральная строка.
Есть много способов получить доступ к переменным Sass в JavaScript, которые могут вам пригодиться. Я склонен использовать этот подход для разделения контрольных точек. Вот мой файл breakpoints.scs, который я позже импортирую в JavaScript, чтобы иметь возможность использовать метод matchMedia() для создания согласованных контрольных точек.
// 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. }
Анимация является еще одним вариантом использования. Длительность анимации обычно хранится в CSS, но более сложные анимации необходимо выполнять с помощью JavaScript.
// animation.scss $global-animation-duration: 300ms; $global-animation-easing: ease-in-out; :export { animationDuration: strip-unit($global-animation-duration); animationEasing: $global-animation-easing; }
Обратите внимание, что я использую при экспорте переменной пользовательскую функцию strip-unit. Это позволяет мне легко парсировать вещи на стороне 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, });
Я рад, что могу легко обмениваться данными между CSS, Sass и JavaScript. Совместное использование таких переменных делает код простым и чистым.
Конечно, есть несколько способов достичь одного и того же. В 2017 году Лес Джеймс поделился интересным подходом, который позволяет Sass и JavaScript взаимодействовать через JSON. Я могу быть предвзятым, но думаю, что подход, который мы рассмотрели здесь, является самым простым и наиболее интуитивным. Это не требует сумасшедших изменений в том, как вы уже используете и пишете CSS и JavaScript.
Автор: Marko Ilic
Источник: https://css-tricks.com
Редакция: Команда webformyself.