Установка правил псевдокласса CSS из JavaScript
Я ищу способ изменить правила CSS для селекторов псевдоклассов (таких как: ссылка,: наведение и т. Д.) Из JavaScript.
Итак, аналог кода CSS: a:hover { color: red }
в JS.
Я не мог найти ответ где-либо еще; Если кто-то знает, что это то, что браузеры не поддерживают, это также будет полезным результатом.
12 ответов
Вы не можете стилизовать псевдокласс на отдельном элементе, так же, как вы не можете иметь псевдокласс в атрибуте inline style="..." (так как нет селектора).
Вы можете сделать это, изменив таблицу стилей, например, добавив правило:
#elid:hover { background: red; }
при условии, что каждый элемент, на который вы хотите воздействовать, имеет уникальный идентификатор, позволяющий выбрать его.
Теоретически, документ, который вам нужен, это http://www.w3.org/TR/DOM-Level-2-Style/Overview.html что означает, что вы можете (с учетом уже существующей встроенной или связанной таблицы стилей) использовать синтаксис, такой как:
document.styleSheets[0].insertRule('#elid:hover { background-color: red; }', 0);
document.styleSheets[0].cssRules[0].style.backgroundColor= 'red';
IE, конечно, требует свой собственный синтаксис:
document.styleSheets[0].addRule('#elid:hover', 'background-color: red', 0);
document.styleSheets[0].rules[0].style.backgroundColor= 'red';
Старые и второстепенные браузеры, скорее всего, не поддерживают ни один из синтаксисов. Динамическое переключение таблиц стилей редко выполняется, потому что это довольно раздражает, чтобы получить правильные, редко необходимые и исторически хлопотные.
Я собрал небольшую библиотеку для этого, так как я думаю, что есть действительные варианты использования для манипулирования таблицами стилей в JS. Причины:
- Установка стилей, которые должны быть рассчитаны или получены - например, установка предпочтительного размера шрифта для пользователя из файла cookie.
- Установка поведенческих (не эстетических) стилей, особенно для разработчиков виджетов / плагинов пользовательского интерфейса. Для вкладок, каруселей и т. Д. Часто требуется простой базовый CSS для работы - не требуется таблицы стилей для основной функции.
- Лучше, чем встроенные стили, поскольку правила CSS применяются ко всем текущим и будущим элементам и не загромождают HTML при просмотре в Firebug / Developer Tools.
Просто поместите CSS в шаблон строки.
const cssTemplateString = `.foo:[psuedoSelector]{prop: value}`;
Затем создайте элемент стиля, поместите строку в тег стиля и прикрепите его к документу.
const styleTag = document.createElement("style");
styleTag.innerHTML = cssTemplateString;
document.head.insertAdjacentElement('beforeend', styleTag);
Специфика позаботится об остальном. Затем вы можете удалять и добавлять теги стиля динамически. Это простая альтернатива библиотекам и работа с массивом таблиц стилей в DOM. Удачного кодирования!
Функция, позволяющая справляться с кросс-браузерными вещами:
addCssRule = function(/* string */ selector, /* string */ rule) {
if (document.styleSheets) {
if (!document.styleSheets.length) {
var head = document.getElementsByTagName('head')[0];
head.appendChild(bc.createEl('style'));
}
var i = document.styleSheets.length-1;
var ss = document.styleSheets[i];
var l=0;
if (ss.cssRules) {
l = ss.cssRules.length;
} else if (ss.rules) {
// IE
l = ss.rules.length;
}
if (ss.insertRule) {
ss.insertRule(selector + ' {' + rule + '}', l);
} else if (ss.addRule) {
// IE
ss.addRule(selector, rule, l);
}
}
};
Мой трюк использует селектор атрибутов. Атрибуты легче настроить с помощью JavaScript.
CSS
.class{ /*normal css... */}
.class[special]:after{ content: 'what you want'}
Javascript
function setSpecial(id){ document.getElementById(id).setAttribute('special', '1'); }
HTML
<element id='x' onclick="setSpecial(this.id)"> ...
Один из вариантов, который вы могли бы рассмотреть, - это использование переменных CSS. Идея состоит в том, что вы устанавливаете свойство, которое хотите изменить, на переменную CSS. Затем в своем JS измените значение этой переменной.
См. Пример ниже
function changeColor(newColor) {
document.documentElement.style.setProperty("--anchor-hover-color", newColor);
// ^^^^^^^^^^^-- select the root
}
:root {
--anchor-hover-color: red;
}
a:hover {
color: var(--anchor-hover-color);
}
<a href="#">Hover over me</a>
<button onclick="changeColor('lime')">Change to lime</button>
<button onclick="changeColor('red')">Change to red</button>
Вместо того, чтобы напрямую устанавливать правила псевдокласса с помощью javascript, вы можете устанавливать правила по-разному в разных файлах CSS, а затем использовать Javascript, чтобы выключить одну таблицу стилей и включить другую. Метод описан в A List Apart (см. Подробнее).
Установите файлы CSS как,
<link rel="stylesheet" href="always_on.css">
<link rel="stylesheet" title="usual" href="preferred.css"> <!-- on by default -->
<link rel="alternate stylesheet" title="strange" href="alternate.css"> <!-- off by default -->
А затем переключаться между ними с помощью JavaScript:
function setActiveStyleSheet(title) {
var i, a, main;
for(i=0; (a = document.getElementsByTagName("link")<i>); i++) {
if(a.getAttribute("rel").indexOf("style") != -1
&& a.getAttribute("title")) {
a.disabled = true;
if(a.getAttribute("title") == title) a.disabled = false;
}
}
}
Есть другая альтернатива. Вместо того, чтобы манипулировать псевдоклассами напрямую, создайте реальные классы, которые моделируют одни и те же вещи, такие как класс "зависания" или "посещаемый" класс. Стиль классов с обычным "." синтаксис, а затем вы можете использовать JavaScript для добавления или удаления классов из элемента, когда срабатывает соответствующее событие.
Как уже говорилось, это не то, что поддерживают браузеры.
Если вы не разрабатываете стили динамически (т. Е. Извлекаете их из базы данных или чего-то еще), вы сможете обойти это, добавив класс в тело страницы.
CSS будет выглядеть примерно так:
a:hover { background: red; }
.theme1 a:hover { background: blue; }
И JavaScript, чтобы изменить это было бы что-то вроде:
// Look up some good add/remove className code if you want to do this
// This is really simplified
document.body.className += " theme1";
Включение и выключение таблиц стилей - это способ сделать это. Вот библиотека для динамического создания таблиц стилей, так что вы можете устанавливать стили на лету:
http://www.4pmp.com/2009/11/dynamic-css-pseudo-class-styles-with-jquery/
Вот решение, включающее две функции: addCSSclass добавляет новый класс css в документ, а toggleClass включает его
В примере показано добавление пользовательской полосы прокрутки в div
// If newState is provided add/remove theClass accordingly, otherwise toggle theClass
function toggleClass(elem, theClass, newState) {
var matchRegExp = new RegExp('(?:^|\\s)' + theClass + '(?!\\S)', 'g');
var add = (arguments.length > 2 ? newState : (elem.className.match(matchRegExp) === null));
elem.className = elem.className.replace(matchRegExp, ''); // clear all
if (add) elem.className += ' ' + theClass;
}
function addCSSclass(rules) {
var style = document.createElement("style");
style.appendChild(document.createTextNode("")); // WebKit hack :(
document.head.appendChild(style);
var sheet = style.sheet;
rules.forEach((rule, index) => {
try {
if ("insertRule" in sheet) {
sheet.insertRule(rule.selector + "{" + rule.rule + "}", index);
} else if ("addRule" in sheet) {
sheet.addRule(rule.selector, rule.rule, index);
}
} catch (e) {
// firefox can break here
}
})
}
let div = document.getElementById('mydiv');
addCSSclass([{
selector: '.narrowScrollbar::-webkit-scrollbar',
rule: 'width: 5px'
},
{
selector: '.narrowScrollbar::-webkit-scrollbar-thumb',
rule: 'background-color:#808080;border-radius:100px'
}
]);
toggleClass(div, 'narrowScrollbar', true);
<div id="mydiv" style="height:300px;width:300px;border:solid;overflow-y:scroll">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a eros metus. Nunc dui felis, accumsan nec aliquam quis, fringilla quis tellus. Nulla cursus mauris nibh, at faucibus justo tincidunt eget. Sed sodales eget erat consectetur consectetur. Vivamus
a diam volutpat, ullamcorper justo eu, dignissim ante. Aenean turpis tortor, fringilla quis efficitur eleifend, iaculis id quam. Quisque non turpis in lacus finibus auctor. Morbi ullamcorper felis ut nulla venenatis fringilla. Praesent imperdiet velit
nec sodales sodales. Etiam eget dui sollicitudin, tempus tortor non, porta nibh. Quisque eu efficitur velit. Nulla facilisi. Sed varius a erat ac volutpat. Sed accumsan maximus feugiat. Mauris id malesuada dui. Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Sed a eros metus. Nunc dui felis, accumsan nec aliquam quis, fringilla quis tellus. Nulla cursus mauris nibh, at faucibus justo tincidunt eget. Sed sodales eget erat consectetur consectetur. Vivamus a diam volutpat, ullamcorper justo
eu, dignissim ante. Aenean turpis tortor, fringilla quis efficitur eleifend, iaculis id quam. Quisque non turpis in lacus finibus auctor. Morbi ullamcorper felis ut nulla venenatis fringilla. Praesent imperdiet velit nec sodales sodales. Etiam eget
dui sollicitudin, tempus tortor non, porta nibh. Quisque eu efficitur velit. Nulla facilisi. Sed varius a erat ac volutpat. Sed accumsan maximus feugiat. Mauris id malesuada dui.
</div>
В jquery вы можете легко установить псевдо-классы при наведении.
$("p").hover(function(){
$(this).css("background-color", "yellow");
}, function(){
$(this).css("background-color", "pink");
});
Если вы используете РЕАКТ, есть то, что называется радием. Это так полезно здесь:
Добавьте обработчики в реквизиты, если указаны интерактивные стили, например, onMouseEnter для:hover, при необходимости оборачивая существующие обработчики
Если какой-либо из обработчиков срабатывает, например, при наведении, Radium вызывает setState, чтобы обновить специфичное для Radium поле в объекте состояния компонентов.
- При повторном рендеринге разрешите все применяемые интерактивные стили, например:hover, просмотрев ключ элемента или ref в специфичном для Radium состоянии.