Как изменить / удалить определения классов CSS во время выполнения? - PullRequest
37 голосов
/ 08 апреля 2009

Я знаю, что можно добавлять новые определения классов CSS во время выполнения через JavaScript. Но ...

Как изменить / удалить определения классов CSS во время выполнения?

Например, предложите мне класс ниже:

<style>
.menu { font-size: 12px; }
</style>

Во время выполнения я хочу изменить правило font-size класса .menu, чтобы затронул каждый элемент на странице, который использует этот класс.

И я также хочу знать, как удалить определение класса .menu.

Ответы [ 8 ]

23 голосов
/ 08 апреля 2009

Нетрудно изменить правила CSS во время выполнения, но, видимо, трудно найти нужное правило. PPK проводит краткий обзор этого на quirksmode.org .

Вы захотите использовать document.styleSheets[i].cssRules - массив, который необходимо проанализировать, чтобы найти тот, который вам нужен, а затем rule.style.setProperty('font-size','10px',null);

17 голосов
/ 05 мая 2011

Я нашел ответ в http://twelvestone.com/forum_thread/view/31411, и здесь я дословно воспроизвожу части нити, потому что боюсь, что нить и очень полезный ответ испарится.

Flip 2006.06.26, 14:45 - [Хрустящая лягушка] сообщений: 2470 дата вступления: 2003.01.26

Ну, примерно через 10-12 часов поиска, чтения и повозок я это сделал! Я код CSS / JS ниндзя сегодня!

Используемый код JS выглядит следующим образом:

<script language="JavaScript">
function changeRule(theNumber) {
    var theRules = new Array();
    if (document.styleSheets[0].cssRules) {
        theRules = document.styleSheets[0].cssRules;
    } else if (document.styleSheets[0].rules) {
        theRules = document.styleSheets[0].rules;
    }
    theRules[theNumber].style.backgroundColor = '#FF0000';
}
</script>

Я проверял это на FF (Mac), Safari (Mac), O9 (Mac), IE5 (Mac), IE6 (ПК), FF (ПК), и все они работают. Причиной утверждения 'if' является то, что некоторые браузеры используют cssRules ... некоторые используют только правила ... И единственный другой волос - это то, что вы не можете использовать "background-color" для ссылки на стиль, у вас есть избавиться от дефиса и использовать первую букву после дефиса.

Чтобы сослаться на первое правило CSS, вы должны использовать «changeRule (0)», второе «changeRule (1)» и третье «changeRule (2)» и так далее ...

Я не нашел браузер, на котором он не работает .... пока .... Все, что вы говорите, может и будет использовано против вас. Снова и снова и снова.


BillyBones 2011.01.20, 11:57 - [в бочке] посты: 1 дата присоединения: 2011.01.20

Здравствуйте, я зарегистрировался на этих форумах только для того, чтобы добавить это немного, поскольку я не мог найти его в другом месте:

function changeStyle(selectorText)
{
    var theRules = new Array();
    if (document.styleSheets[0].cssRules) {
        theRules = document.styleSheets[0].cssRules;
    } 
    else if (document.styleSheets[0].rules) {
        theRules = document.styleSheets[0].rules;
    }
    for (n in theRules)
    {
        if (theRules[n].selectorText == selectorText)   {
            theRules[n].style.color = 'blue';
        }
    }
}

Это просто делает правило CSS идентифицируемым по имени селектора, а не по его индексу в массиве cssRules.

Другими словами, вы можете выполнять функцию Javascript со строковым аргументом «selectorText» вместо числа, которое трудно запомнить и подвержено частым изменениям при добавлении новых стилей.

Спасибо за ваши 10-12 часов исследований, Флип, надеюсь, я сделал достойное дополнение.

12 голосов
/ 08 апреля 2009

Я думаю, вы ищете это:

http://www.hunlock.com/blogs/Totally_Pwn_CSS_with_Javascript

это позволяет вам изменять действующие правила с помощью JavaScript. Я использовал его однажды, несколько лет назад, похоже, это сработало.

6 голосов
/ 30 сентября 2015

Я сделал простую вспомогательную функцию для тех, кто хочет это сделать:

function getCSSRule(search) {
  return [].map.call(document.styleSheets, function(item) {
    return [].slice.call(item.cssRules);
  }).reduce(function(a, b) {
    return b.concat(a);
  }).filter(function(rule) {
    return rule.selectorText.lastIndexOf(search) === rule.selectorText.length - search.length;
  })[0];
}

И затем, вы можете использовать это так:

getCSSRule('.mydiv').style.fontSize = '20px';

Взгляните на пример ниже:

function getCSSRule(search) {
  return [].map.call(document.styleSheets, function(item) {
    return [].slice.call(item.cssRules);
  }).reduce(function(a, b) {
    return b.concat(a);
  }).filter(function(rule) {
    return rule.selectorText.lastIndexOf(search) === rule.selectorText.length - search.length;
  })[0];
}

document.querySelector('button').addEventListener('click', function(e) {
  getCSSRule('.iframe').style.backgroundColor = 'orange';
});
.iframe {
  height: 200px;
  width: 200px;
  display: inline-block;
  border: 1px solid #000;
}
<p>
  <button>Change .iframe background-color</button>
</p>
<div class="iframe"></div>
<div class="iframe"></div>
0 голосов
/ 05 ноября 2018

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

(Примечание: предыдущая попытка добавления этого ответа получила немедленное понижение в течение нескольких секунд без обратной связи одной из нескольких целей автоматического уведомления этого Я не уверен, что короткого времени реакции коленного рефлекса было достаточно, чтобы понять, почему это надежное решение, которое хорошо охватывает сценарий использования ОП, тем не менее я перефразировал его, полагая, что повествование могло каким-то образом послужить толчком. отсутствие точек с запятой (которые я сейчас добавил для него). Или отсутствие ненужных фигурных скобок (также добавлено). Или отсутствие примечаний о неэффектах (добавлено). Или не использование достаточно сложного метода (выиграл ' исправить, даже упростил код еще немного). Я уверен, что он ударит снова анонимно, но все же повторите попытку, потому что это чистая и надежная техника, которую стоит использовать.)

ПРИМЕЧАНИЕ: Этот подход предполагает, что у вас есть достаточный контроль над стилем страницы, чтобы одно и то же правило класса не могло создать , созданное другим методом. (И он ожидает, что элемент HEAD существует.)

(Одной из возможных затрат такого подхода может быть повторный рендеринг на innerHtml, но поскольку мы все равно меняем CSS, перерисовка неизбежна. Кроме того, innerHtml выполняется для неотображаемого элемента, поэтому браузеры могут оптимизировать его, даже если это имеет значение.)

OK. Поскольку у вас может быть любое количество элементов STYLE, то вполне можно обернуть ваш динамический класс в отдельный отдельный. Хм, вот и все. :) Затем добавьте id или, что еще лучше, *, атрибут class к оболочке STYLE, чтобы вы могли практически получить доступ к своему правилу класса и манипулировать им, как если бы это был элемент DOM , Просто убедитесь, что он добавлен / заменен в <style class="..."> ... </style>.

Бонус: вы также можете сгруппировать несколько связанных правил и заменить их все сразу, если хотите (с тривиальными изменениями):

function replace_class(classname, block) {
    // Remove old:
    var s = document.head.querySelector("style." + classname);
    if (s) { document.head.removeChild(s); }

    // Just delete?
    if (!block) { return; }

    // Add new:
    s = document.createElement("style");
    s.className = classname;
    s.innerHTML = ("." + classname + block); // <style class="classname">.classname{...}</style>
    document.head.appendChild(s);
}

Затем обновить: replace_class("menu", "{font-size: 8px;}").

Или удалить: replace_class("menu", null).


* Поскольку CSS применяется к каждому элементу, вы можете задаться вопросом, почему сам по себе STYLE не будет неожиданно отображен, если в вашем новом классе display: ... имеет что-то другое, чем none. Ну, было бы , если бы оно было вставлено в BODY! Но, поскольку мы добавляем его в HEAD, рендеринг пропускается (если, конечно, вы не решите также отобразить HEAD). Или вы могли бы также использовать id вместо этого, но тогда вам пришлось изобрести / использовать правильную область видимости / префикс, и зачем вам это, если его можно пощадить? (И мне также нравится тонкая дерзость установки class, когда это классная оболочка в любом случае ...)

0 голосов
/ 12 июня 2018

Ниже приведен подход, который будет работать для любой заданной функции выбора и изменения правила:

// general function for selecting rules and applying changes
function change_css_rules(changeRuleFunc, selectorFunc) {
    [].concat.apply([], // flattens arrays
        Array.from(document.styleSheets).map(function(sheet) { // each ss
            return Array.from(sheet.cssRules).filter(function(rule) { // each rule
                return selectorFunc(rule); // only select desired rules
            });
        })
    ).map(changeRuleFunc); // change the selected rules
}

Пример использования:

var my_changeRuleFunc = function(rule) {
    rule.style.fontSize = '20px';
}

var my_selectorFunc = function(rule) {
    return rule.selectorText == '.myClass'; // return true to select this rule
}

change_css_rules(my_changeRuleFunc, my_selectorFunc); // apply change to selected rules
0 голосов
/ 10 ноября 2016

Я взял лучшие ответы здесь и соединил их для простоты использования и совместимости с различными браузерами. Кроме того, я рассмотрел, когда выдавал ошибки, если на странице не было таблиц стилей или правило css еще не существовало.

https://github.com/Frazer/dynamicallyAccessCSS.js

0 голосов
/ 14 ноября 2014

Трудно найти желаемое правило, потому что вам нужно перебирать массив document.styleSheets [i] .cssRules. (и сравните имя вашего класса с атрибутом selectorText) Поэтому мое решение этой проблемы - добавить новый класс CSS, удалить старый класс CSS из элемента HTML и добавить этот класс вместо него.

var length = getCssRuleLength();
var newClassName = "css-class-name" + length;

//remove preview css class from html element.
$("#your-html-element").removeClass("css-class-name");
$("#your-html-element").removeClass("css-class-name" + (length-1));

$("#your-html-element").addClass(newClassName);

//insert a css class
insertCssRule("." + newClassName + ' { max-width: 100px; }', length);


function getCssRuleLength() {
	var length = 0;
	if (document.styleSheets[1].cssRules) {
		length = document.styleSheets[1].cssRules.length;
	} else if (document.styleSheets[1].rules) { //ie
		length = document.styleSheets[1].rules.length;
	}
	return length;
}
function insertCssRule(rule, index) {
	if (document.styleSheets[1].cssRules) {
		document.styleSheets[1].insertRule(rule, index);
	} else if (document.styleSheets[1].rules) { //ie
		document.styleSheets[1].addRule(rule, index);
	}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...