Как добавить несколько правил css, чтобы минимизировать перепрошивки браузера?

#javascript #css #performance #browser #reflow

#javascript #css #Производительность #браузер #Перепрошивка

Вопрос:

Допустим, мне нужно применить кучу правил css (около 50), например, в следующем коде:

  var s = document.createElement('style');
     s.type = 'text/css';
     s = document.getElementsByTagName('head').item(0).appendChild(s);

 var cssRules = [
      ".someClass1 {text-align: center; color: red;}",
      ".someClass2 {border: 1px solid black;}",
      ".someClass3 {color: green;}",
      ".someClass4 {text-decoration: underline; color: red;}",
      ...
 ];

 if (s.sheet amp;amp; s.sheet.insertRule) {
     for (var i = 0, len = cssRules.length; i<len; i  ) {
         s.sheet.insertRule(cssRules[i], s.sheet.cssRules.length);
     }         
 }
  

Таким образом, каждый вызов s.sheet.insertRule запускает перепрошивку браузера. Как я мог бы минимизировать перепрошивки браузера только до одного раза?

Спасибо.

Комментарии:

1. Почему бы не поместить их в файл CSS и не загрузить файл при необходимости?

2. Современные браузеры, как правило, достаточно умны, чтобы вычислять перепрошивки при добавлении нескольких стилей в один и тот же скрипт, конечно, это для обычного использования javascripts element.style , при использовании довольно простой вставки правил на лист, я не уверен, что это делает?

3. @Mooseman Потому что у меня есть cssRules после некоторых действий пользователя после загрузки страницы.

4. @adeneo К сожалению, я не могу использовать element.style по своей причине. Итак, я ищу подход для оптимизации моего случая.

Ответ №1:

Вы могли бы join объединить все свои правила в одну строку:

 // Join rules and use a space as delimiter
var cssRulesAppended = cssRules.join(' ')
  

Вы также можете напрямую записать свой CSS в своей голове, добавив style тег, полностью пропустив insertRule метод:

 var head = document.head || document.getElementsByTagName('head')[0],
    styleTag = document.createElement('style')

styleTag.type = 'text/css'

if (styleTag.styleSheet) {
    styleTag.styleSheet.cssText = cssRulesAppended
} else {
    styleTag.appendChild(document.createTextNode(cssRulesAppended))
}

head.appendChild(styleTag)
  

Редактировать:
Если вы уже знаете правила, которые собираетесь добавить, я бы настоятельно не советовал вставлять их так, как вы делаете сейчас. Либо поместите их в таблицу стилей, чтобы использовать при начале загрузки страницы, либо, если вы знаете об элементах, нуждающихся в определенных стилях, используя свойства стиля JavaScript. Вот ссылка на JSPerf:.

Комментарии:

1. @answered Спасибо за ответ. Я пробую ваш подход в своем коде.

2. @Erik Я проверил документацию по insertRule , и она не допускает пакетных операций (как в случае с несколькими правилами в одном операторе). Итак, если вы хотите вставить несколько правил одновременно, вам придется использовать подход тега <style> .