Control javascript with css

Передача данных между CSS и JavaScript с помощью CSS-переменных

Одно из самых серьёзных противостояний в мире веб-разработки – CSS против JavaScript. У обоих есть свои достоинства, собственный синтаксис и идеи, иногда понять их может быть непросто. Но есть способы заставить их общаться и использовать достоинства каждого.

С позиции JavaScript для установки различных CSS-свойств HTML-элементу, требуется найти его в DOM и получить доступ к нему. После добавления стилей, у этого элемента появляется атрибут style , который вы не стали бы, наверное, писать вручную.

Ещё один способ доступа к CSS-свойствам из JavaScript – использовать настраиваемые CSS-свойства, они также известны, как «CSS-переменные» (CSS variables), которые можно определять с помощью синтаксиса — . Так:

Это «переменные», поэтому их можно неоднократно использовать в таблице стилей.

Получить к ним доступ и управлять значениями этих переменных можно с помощью JavaScript. В этом примере настраиваемое CSS-свойство устанавливается для корневого элемента документа. Его можно прочитать так:

let bg = getComputedStyle(document.documentElement). getPropertyValue('--pagebackground');

И его можно установить с помощью JavaScript, получив доступ к стилю корневого элемента (или вообще любого другого элемента с настраиваемыми свойствами), так:

document.documentElement.style.setProperty('--pagebackground', 'firebrick');

Но самое выдающееся во всей этой истории то, что используя возможности JavaScript, можно предоставить CSS то, к чему он не может получить доступ. Например, CSS не может прочитать координаты курсора мыши, а JavaScript может.

Читайте также:  Map string list string in java

Для начала, в CSS надо определить пару свойств —mouse-x и —mouse-y , а также установить им начальные значения – 0 :

Затем, в JavaScript следует добавить документу обработчик mousemove . Тогда при движении курсора можно получать его координаты и управлять этими двумя CSS-свойствами с помощью JavaScript:

let root = document.documentElement document.addEventListener('mousemove', e => < root.style.setProperty('--mouse-x', e.x); root.style.setProperty('--mouse-y', e.y); >);

В-общем, дело нехитрое. Поскольку настраиваемые CSS-свойства реагируют на движение мыши и изменяют свое значение, теперь можно, например, показать кружок и заставить его двигаться вслед за курсором, так:

Здесь некоторые пояснения к CSS:

  • ширина и высота DIV установлены равными 20 пикселей, а фон – белый
  • добавление border-radius: 100% гарантирует, что из квадрата получится круг.
  • затем используется transform: translate , чтобы позиционировать круг на экране. Это может быть что-то вроде transform: translate (200px, 300px) , чтобы расположить наш шар на 200 пикселей по горизонтали и 300 пикселей по вертикали относительно левого верхнего угла.
  • поскольку JavaScript возвращает для настраиваемого CSS-свойства числовое значение, его необходимо преобразовать в пиксели, умножив на 1px .
  • так как размер шара составляет 20 пикселей, то чтобы поместить его центр в точки —mouse-x и —mouse-y , нужно вычесть из координат 10.

Этот трюк позволяет выполнять сложные вычисления, считывать состояние браузера и внешнее взаимодействие с ним в JavaScript, затем передавать результат в CSS и изменять его.

Источник

Передача данных в CSS

Передача данных в CSS

28 марта 2023 г.

При разработке интерфейсов часто возникает необходимость динамически менять стили HTML-элементов в зависимости от текущего состояния приложения. Существует довольно много способов передать данные из Javascript в CSS и в этой статье я предлагаю их рассмотреть.

Инлайн-стили

Самый простой способ стилизовать элемент — указать CSS-свойства прямо в HTML:

p style="color: #272727;">Lorem ipsum dolor sit.p>

Этот древнейший споособ стилизации максимально прост в использовании, но имеет ряд существенных недостатков:

  • Смешивается структура страницы и её оформление (мы же не пишем Javascript прямо в HTML);
  • Нет возможности использовать каскад, медиа-выражения и некоторые другие инструменты, доступные в CSS;
  • Нет возможности переиспользовать стили для одинаковых элементов.

В JSX последний пункт можно решить с помощью создания переменной:

const paragraphStyles =  color: "#272727" >; const MyComponent = () => ( div> p style=paragraphStyles>>Lorem ipsum dolor sit ametp> p style=paragraphStyles>>Lorem ipsum dolor sit ametp> div> );

Похожий подход применяется в React Native , но там каскада нет и возможности CSS довольно сильно ограничены, а в бразуере — родной среде для CSS — подобных ограничений нет и было бы неразумно отказываться от такой богатой функциональности.

CSS-классы

Проблема выше решается путём выноса стилей из HTML:

style> .my-paragraph   color: #272727; > style> div> p class="my-paragraph">Lorem ipsum dolor sit ametp> p class="my-paragraph">Lorem ipsum dolor sit ametp> div>

Придумывая название класса, мы создаём некую абстракцию, которую зачастую наделяем смыслом. Вероятно этот класс будет представлять собой некий компонент, но у компонентов в привычном нам понимании бывают свойства, которые можно менять при необходиости. И это не CSS свойства — мы создали абстракцию в виде класса над стилями, не будем спешить её ломать, смешивая её с конкретными стилевыми параметрами.

CSS in JS

Раз речь зашла о компонентах, попробуем вернуться к React и посмотреть, как подобная задача решается там.

В общем-то очень остроумно проблему решают CSS-in-JS фреймворки: чтобы не передавать данные из JS в CSS, мы перенесли CSS в JS:

import styled from "styled-components"; const Paragraph = styled.p`  color: #272727; `; const MyComponent = () => ( div> Paragraph>Lorem ipsum dolor sit ametParagraph> Paragraph>Lorem ipsum dolor sit ametParagraph> div> );

Если нам понадобится передать данные из JS в CSS, мы можем сделать это так же, как и с любым другим React-компонентом:

import styled,  css > from "styled-components"; interface ParagraphProps   type?: "regular" | "important"; > const paragraphTypeStyles =   regular: css`  color: #272727; `,  important: css`  background-color: #ff6287;  font-weight: bold; `, >; const Paragraph = styled.pParagraphProps>` $( type = "regular" >) => paragraphTypeStyles[type]> `; const MyComponent = () => ( div> Paragraph>Lorem ipsum dolor sit ametParagraph> Paragraph type="important">Lorem ipsum dolor sit ametParagraph> div> );

Мы передаём некий дискретный набор данных в компонент и для каждой новой их комбинации styled-components будет создавать уникальный класс и вставлять его в DOM. Но что, если параметр не дискретный и меняется часто?

import  useEffect, useState > from "react"; import styled from "styled-components"; interface BallProps   position: [x: number, y: number]; > const Ball = styled.divBallProps>`  width: 32px;  height: 32px;  border-radius: 16px;  background-color: #ff6287;  transform: $( position >) => `translate($position[0]>px, $position[1]>px)`>; `; const MyComponent = () =>  const [position, setPosition] = useState([0, 0]); useEffect(() =>  let rafId; /** Меняем позицию 60 раз в секунду */ const update = (time: number) =>  setPosition([Math.sin(time * 30), Math.cos(time * 30)]);  rafId = window.requestAnimationFrame(update); >;  rafId = window.requestAnimationFrame(update); return () =>   window.cancelAnimationFrame(rawId); >; >, []); return Ball position=position> />; >;

Спустя некоторое время styled-components вежливо намекнёт, что так делать не стоит, прямо в консоли браузера:

Слишком много сгенерированных классов

Для этого случая нам предлагают использовать инлайновые стили, но по прежнему они спрятаны за абстракцией в виде пропсы position , за счёт чего стили отделены от логики:

import  useEffect, useState > from "react"; import styled from "styled-components"; interface BallProps   position: [x: number, y: number]; > const Ball = styled.divBallProps>.attrs(( position >: BallProps) => (  style:   transform: `translate($position[0]>px, $position[1]>px)` > >))`  width: 32px;  height: 32px;  border-radius: 16px;  background-color: #ff6287; `; const MyComponent = () =>  const [position, setPosition] = useState([0, 0]); // .  return Ball position=position> />; >;

Но что если СSS-in-JS решение не подходит?

Решаем задачу нативно

Методология БЭМ предлагает модификаторы , которые могут быть:

input class="input input_invalid" /> style> .input__invalid   border-color: red; > style>
p class="paragraph paragraph_type_important">Lorem ipsump>

Аналогично можно использовать data-атрибуты:

input class="input" data-invalid="true" /> style> .input[data-invalid="true"]   border-color: red; > style>

Во многих случаях, кстати, data-атрибуты можно заменить на aria-атрибуты и таким образом убить сразу двух зайцев: стили и доступность:

input class="input" aria-invalid="true" /> style> .input[aria-invalid="true"]   border-color: red; > style>

Перечисленные выше решения опять же позволяют создавать конечные наборы значений. Вот бы был способ передать Javascript-переменную в CSS.

Что? Такой способ уже есть?

CSS Custom Properties

С их помощью можно в том числе организовать API между бизнес-логикой и визуалом:

div class="ball" style="--position-x: 35px; --position-y: 54px;">div> style> .ball   width: 32px;  height: 32px;  border-radius: 16px;  background-color: #ff6287;  transform: translate(var(--position-x), var(--position-y)); > style>
const MyComponent = () =>  const [position, setPosition] = useState([0, 0]); // .  return ( div className="ball" style= "--position-x": position[0], "--position-y": position[1], >> /> ); >;

И самая главная мощь тут заключается в том, что CSS-переменные действуют каскадно!

То есть мы можем разработать компонент, состоящий из нескольких вложенных друг в друга HTML-элементов, установить значение СSS-переменной на корневом элементе и использовать его в потомках:

div id="cube-demo" class="viewport" style="--scroll-top: 0"> div class="cube"> div class="cube-edge cube-edge_front">div> div class="cube-edge cube-edge_left">div> div class="cube-edge cube-edge_back">div> div class="cube-edge cube-edge_right">div> div class="cube-edge cube-edge_top">div> div> div> style> .cube   transform: rotateY( calc(var(--scroll-top) * 1deg) /* Не забудем о единицах измерения */ ); > style> script>  document.addEventListener("scroll", ( event >) =>   document .getElementById("cube-demo") .style.setAttribute("--scroll-top", event.target.scrollTop.toString()); >); script>

Источник

Взаимодействие между Javascript и CSS с помощью CSS-переменных

На 2016 г. CSS-переменные полностью работоспособны в Chrome и Firefox, у IE тоже в планах реализовать их.

Как часто бывает с новинками JavaScript и CSS, не сразу удается представить себе, для чего CSS-переменные могут пригодиться. Для большинства из нас эти переменные — что-то новое и непривычное, так что не всегда очевидно, к чему их применить. Но мы нашли замечательный ответ — взаимодействие между Javascript и CSS.

Что такое CSS-переменные?

CSS-переменные (см. спецификацию) добавляют в CSS два новых понятия. Отныне можно определять собственные свойства, начинающиеся с двойного дефиса ( — ):

А затем использовать их с помощью var():

Для всех, кто знаком с SASS или подобным языком, компилирующимся в CSS, преимущества этого очевидны, можно запросто менять цвета, размеры и т.п. всего в одном месте.

Что интересно, переменные подчиняются тем же правилам наследования, что другие CSS-свойства. Например, вдруг мы решили поэкспериментировать с основным цветом нашего блога:

Все ссылки внутри той части страницы, что относится к записи в блоге, окажутся страшноватого коричневого оттенка.

CSS-переменные просто великолепно сочетаются с выражением calc() :

CSS-переменные и JavaScript

Недавно мы натолкнулись на полифил для ползунка, который написала Лиа Веру, с интересным примером использования CSS-переменных для связи между JavaScript и CSS.

Исторически единственным способом управлять стилями переменной или функцией из JavaScript было, по сути, писать CSS в самом скрипте:

myElement.style.height = height + 'px'

Не так уж редко случается отказываться от отдельного CSS вообще и просто писать стили в JS:

var newStyles = document.createElement('style') document.head.append(newStyles) newStyles.innerHTML = ".my-element "

CSS-переменные позволяют делать намного лучше, возьмем тот же пример:

Тогда в JavaScript можно прописать эту переменную именно для нашего элемента:

myElement.style.setProperty('--element-height', height + 'px')

Если исхитриться, можно обойтись и без конкатенации:

myElement.style.setProperty('--element-height', height)

Можно даже определить в CSS значение по умолчанию, которое потом переопределится скриптом:

Теперь можно аккуратно передавать информацию между JavaScript и стилями. Ну разве это не потрясающе?

Вот готовый пример, с которым можно поиграть:

P.S. Это тоже может быть интересно:

Если вам понравилась статья, поделитесь ей!

Источник

Оцените статью