Используйте JS для динамического управления css, сколько способов вы знаете?

JavaScript CSS

Добавить Автора

Переводчик: Front-end Xiaozhi

Источник: css-tricks.com

Чем больше вы знаете, тем больше вы не знаете

Ставьте лайк и смотрите снова, формируйте привычку


эта статьяГитхаб:GitHub.com/QQ449245884…Он был включен в вышеизложенное, и более ранние статьи с высокими похвалами были классифицированы, а также было систематизировано множество моих документов и учебных материалов. Добро пожаловать в Star and Perfect. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Надеюсь, у нас что-то получится вместе.

JavaScript, возможно, является королем взаимодействия, как язык сценариев, а также многие другие.Web ApiЭто еще больше расширяет его набор функций и обогащает работоспособность интерфейса взаимодействия. такого родаAPIПримеры включаютWebGL API,Canvas API,DOM APIи группа менее известныхCSS API.

из-заJSXи бесчисленное множествоJS框架появлениеJS APIа такжеDOMИдея интерактивности действительно прижилась, но похоже, что в CSS не так много подобных техник. Конечно, естьCSS-in-JSТакие решения, но самые популярные основаны напереводить(транспиляция) для генерации CSS без дополнительных прогонов. Это определенно хорошо для производительности, потому чтоCSS APIИспользование может привести к дополнительным перерисовкам, связанным сDOM APIиспользуйте то же самое. Но это не то, чего мы хотим. Что, если компания однажды попросит нас манипулировать стилями и классами CSS элементов DOM и создать полную таблицу стилей, используя JS, как HTML?

встроенный стиль

Прежде чем мы углубимся в некоторые более сложные вещи, давайте вернемся к некоторым основам. Например, мы можем изменить его.styleсвойства для редактирования данногоHTMLElementвстроенные стили.

const el = document.createElement('div')

el.style.backgroundColor = 'red'
// 或者 
el.style.cssText = 'background-color: red'
// 或者
el.setAttribute('style', 'background-color: red')

прямо в.styleУстановка свойств стиля для объекта потребует использованиягорбназваны ключами свойств вместо использования短横线命名. Если нам нужно установить дополнительные свойства встроенного стиля, мы можем установить.style.cssTextсвойства, чтобы установить их более эффективным способом.

пожалуйста, помните, ** После установки cssText исходный стиль css очищается, ** Поэтому нам требуется умирать кучу стилей за раз.

Если этот встроенный стиль настройки слишком громоздкий, мы также можем рассмотреть.styleа такжеObject.assign()Используется вместе для одновременной установки нескольких свойств стиля.

// ...
Object.assign(el.style, {
    backgroundColor: "red",
    margin: "25px"
})

Эти «основы» гораздо больше, чем мы думаем..styleреализация объектаCSSStyleDeclarationинтерфейс. Это показывает, что он также имеет некоторые интересные свойства и методы, в том числе только что использованный.cssText,Также включает.length(количество заданных свойств) и.item(),.getPropertyValue()а также.setPropertyValue()такие методы, как:

// ...
const propertiesCount = el.style.length
for(let i = 0; i < propertiesCount; i++) {
    const name = el.style.item(i) // 'background-color'
    const value = el.style.getPropertyValue(name) // 're'
    const priority = el.style.getPropertyPriority(name) // 'important'
    
    if(priority === 'important') {
        el.style.removeProperty()
    }
}

Вот маленькая хитрость - во время обхода.item()Методы имеют альтернативный синтаксис в виде доступа по индексу.

// ...
el.style.item(0) === el.style[0]; // true

CSS-класс

Далее рассмотрим более продвинутую структуру —CSS-класс, который при извлечении и установке имеет строковую форму:.classname.

// ...
el.className = "class-one class-two";
el.setAttribute("class", "class-one class-two");

Другой способ установить строку класса — установитьclassатрибут (то же, что и поиск). Однако, как и использование.style.cssTextсвойства, набор.classNameпотребует от нас включить в строку все классы данного элемента, как измененные, так и неизмененные классы.

Конечно, для выполнения этой работы можно использовать некоторые простые манипуляции со строками, а также использовать более новый.classListимущество, это имущество,IE9 не поддерживает его, а IE10 и IE11 поддерживают лишь частично..

classlistсвойство реализованоDOMTokenList, есть целая куча полезных методов. Например.add(),.remove(), .toggle() и.replace()позволяет нам изменить текущий набор классов CSS, в то время как другие, такие как.item(),.entries()или.foreach()Тогда процесс обхода этой коллекции индексов может быть упрощен.

// ...
const classNames = ["class-one", "class-two", "class-three"];
classNames.forEach(className => {
    if(!el.classList.contains(className)) {
        el.classList.add(className);
    }
});

Stylesheets

Все это время у Web Api был еще одинStyleSheetListинтерфейс, состоящий изdocument.styleSheetsреализация имущества.document.styleSheetsсвойство только для чтения, которое возвращаетStyleSheetсделанный из предметовStyleSheetList, каждыйStyleSheetОбъекты представляют собой таблицы стилей, связанные или встроенные в документ.

for(styleSheet of document.styleSheets){
	console.log(styleSheet);
}

Распечатывая результаты, мы можем знать, что то, что печатается в каждом цикле, равноCSSStyleSheetобъект, каждый объект CSSStyleSheet состоит из следующих свойств:

Атрибуты описывать
media Получить носитель, на котором действует текущий стиль.
disabled Включить или отключить таблицу стилей.
href Возвращает адрес таблицы стилей, к которой присоединен объект CSSStyleSheet.
title Возвращает значение заголовка объекта CSSStyleSheet.
type Возвращает значение типа объекта CSSStyleSheet, обычно text/css.
parentStyleSheet Возвращает таблицу стилей, содержащую текущую таблицу стилей.
ownerNode Возвращает узел DOM, в котором находится объект CSSStyleSheet, обычно<link>или<style>.
cssRules Возвращает все правила таблицы стилей.
ownerRule При импорте через @import свойство является указателем на правило, представляющее импорт, в противном случае — null. IE не поддерживает это свойство.

Методы объекта CSSStyleSheet:

метод описывать
insertRule() Вставьте правила CSS в объект cssRules текущей таблицы стилей.
deleteRule() Удаляет правила CSS из объекта cssRules в текущей таблице стилей.

имеютStyleSheetListполное содержание, давайтеCSSStyleSheetсам. Здесь интересно,CSSStyleSheetрасширенныйStyleSheetинтерфейс и иметь только такие свойства только для чтения, как.ownerNode,.href,.titleили.type, которые в основном берутся непосредственно из того места, где объявлена ​​данная таблица стилей. Вспомним стандартный HTML-код для загрузки внешнего CSS-файла, и мы увидим, что это значит:

<head>
<link rel="stylesheet" type="text/css" href="style.css" title="Styles">
</head>

Теперь мы знаем, что документ HTML может содержать несколько таблиц стилей, каждая из которых может содержать разные правила и даже больше таблиц стилей (при использовании@importВремя).CSSStyleSheetЕсть два метода:、.insertrule()а также.deleterule()для добавления и удаления правил Css.

// ...
const ruleIndex = styleSheet.insertRule("div {background-color: red}");
styleSheet.deleteRule(ruleIndex);

.insertRule(rule,index): Эту функцию можно использовать вcssRulesВставить указанное правило в набор правил, параметрruleпредставляет собой строку, указывающую правило, параметрindex— это позиция, в которую вставляется строка правила значения.

deleteRule(index): Эта функция может удалить правила указанного индекса, параметрыindexУказывает индекс правила.

CSSStyleSheetТакже имеет два собственных свойства:.ownerRuleа также.cssRule. несмотря на то что.ownerRuleа также@importпохоже, но интереснее.cssRules . Проще говоря, этоCSSRuleListизCSSRule, вы можете использовать ранее упомянутый.insertrule()а также.deleterule()метод его изменения. Имейте в виду, что некоторые браузеры могут препятствовать доступу к внешнему CSSSt из другого источника (домена).yleSheet.cssRulesАтрибуты.

Так что жеCSSRuleList?

CSSRuleListпредставляет собой объект массива, содержащий упорядоченныйCSSRuleколлекция предметов. КаждыйCSSRuleв состоянии пройтиrules.item(index)форма доступа илиrules[index]. здесьrulesэто реализацияCSSRuleListобъект интерфейса,indexосновывается на0начинается последовательно сCSSПорядок в таблице стилей постоянный. Количество объектов стиля определяетсяrules.lengthВыражать.

дляCSSStyleRuleОбъект:

каждая таблица стилейCSSStyleSheetОбъект может содержать несколькоCSSStyleRuleОбъекты, то есть правила стиля CSS, следующие:

<style type="text/css">
  h1{color:red}
  div{color:green}
</style>

в коде вышеstyleлейбл представляет собойCSSStyleSheetобъект таблицы стилей, этот объект таблицы стилей содержит дваCSSStyleRuleObject, то есть два правила стиля CSS.

CSSStyleRuleОбъекты обладают следующими свойствами:

1.type:вернуть0-6Число , указывающее на тип правила.Список типов выглядит следующим образом:

0: CSSRule.UNKNOWN_RULE.

1: CSSRule.STYLE_RULE (определяет объект CSSStyleRule).

2: CSSRule.CHARSET_RULE (определить объект CSSCharsetRule, используемый для установки набора символов текущей таблицы стилей, значение по умолчанию совпадает с текущей веб-страницей).

3: CSSRule.IMPORT_RULE (Определите объект CSSImportRule, просто используйте@importимпортировать другие таблицы стилей)

4: CSSRule.MEDIA_RULE (определяет объект CSSMediaRule, который используется для установки этого стиля для дисплеев, принтеров или проекторов и т. д.).

5: CSSRule.FONT_FACE_RULE (определить объект CSSFontFaceRule, @font-face CSS3).

6: CSSRule.PAGE_RULE (определяет объект CSSPageRule).

2.cssText: возвращает строку, представляющую содержимое текущего правила, например:

div{color:green}

3.parentStyleSheet: Вернуться кCSSStyleRuleобъект.

4.parentRule: если правило находится в другом правиле, это свойство ссылается на другой объект CSSRule.

5.selectorText: возвращает селектор этого правила, например, элемент div выше является селектором.

6.style: вернутьCSSStyleDeclarationобъект.

// ...
const ruleIndex = styleSheet.insertRule("div {background-color: red}");
const rule = styleSheet.cssRules.item(ruleIndex);

rule.selectorText; // "div"
rule.style.backgroundColor; // "red"

выполнить

Теперь давайте взглянем на связанные с CSSJS ApiОбладая достаточным пониманием, мы можем создавать свои собственные, небольшие, основанные на среде выполненияCSS-in-JSвыполнить. Идея состоит в том, чтобы создать функцию, которой передается объект конфигурации простого стиля, который генерирует хеш-имя только что созданного класса CSS для последующего использования.

Процесс реализации прост, нам нужна функция, которая может получить доступ к определенной таблице стилей, и просто использовать.insertrule()Конфигурация метода и стиля готова к запуску. Начнем с раздела таблицы стилей:

function createClassName(style) {
  // ...
  let styleSheet;
  for (let i = 0; i < document.styleSheets.length; i++) {
    if (document.styleSheets[i].CSSInJS) {
      styleSheet = document.styleSheets[i];
      break;
    }
  }
  if (!styleSheet) {
    const style = document.createElement("style");
    document.head.appendChild(style);
    styleSheet = style.sheet;
    styleSheet.CSSInJS = true;
  }
  // ...
}

если вы используетеESMИли любую другую модульную систему JS, вы можете безопасно создавать экземпляры таблиц стилей вне функций, не беспокоясь о том, что другие получат к ним доступ. Однако для примера будемstylesheetВверх.CSSInJSСвойство задается в виде флага, который используется для определения необходимости его использования.

А что, если вам также нужно создать новую таблицу стилей? Лучший вариант - создать новый<style/>тег и добавьте его в HTML-документ<head/>начальство. Это автоматически добавит новую таблицу стилей вdocument.styleSheetsсписок и позволяет нам пройти<style/>отмечен.sheetсвойства для доступа к нему, разве это не умно?

function createRandomName() {
  const code = Math.random().toString(36).substring(7);
  return `css-${code}`;
}

function phraseStyle(style) {
  const keys = Object.keys(style);
  const keyValue = keys.map(key => {
    const kebabCaseKey = 
        key.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
    const value = 
        `${style[key]}${typeof style[key] === "number" ? "px" : ""}`;
    
    return `${kebabCaseKey}:${value};`;
  });
  
  return `{${keyValue.join("")}}`;
}

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

function createClassName(style) {
  const className = createRandomName();
  let styleSheet;
  // ...
  styleSheet.insertRule(`.${className}${phraseStyle(style)}`);
  return className;
}

Полный код выглядит следующим образом:

HTML

<div id="el"></div>

JS

function createRandomName() {
  const code = Math.random().toString(36).substring(7);
  return `css-${code}`;
}

function phraseStyle(style) {
  const keys = Object.keys(style);
  const keyValue = keys.map(key => {
    const kebabCaseKey = key.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
    const value = `${style[key]}${typeof style[key] === "number" ? "px" : ""}`;
    return `${kebabCaseKey}:${value};`;
  });
  return `{${keyValue.join("")}}`;
}

function createClassName(style) {
  const className = createRandomName();
  let styleSheet;
  for (let i = 0; i < document.styleSheets.length; i++) {
    if (document.styleSheets[i].CSSInJS) {
      styleSheet = document.styleSheets[i];
      break;
    }
  }
  if (!styleSheet) {
    const style = document.createElement("style");
    document.head.appendChild(style);
    styleSheet = style.sheet;
    styleSheet.CSSInJS = true;
  }
  styleSheet.insertRule(`.${className}${phraseStyle(style)}`);
  return className;
}

const el = document.getElementById("el");

const redRect = createClassName({
  width: 100,
  height: 100,
  backgroundColor: "red"
});

el.classList.add(redRect);

текущий результат:

Суммировать

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

оригинал:Cs-tricks.com/press-intro Гратериалы C ...

Ошибки, которые могут быть в редактировании, нельзя узнать в режиме реального времени.Чтобы решить эти ошибки потом, много времени тратится на отладку журнала.Кстати, всем рекомендую полезный инструмент мониторинга BUG.Fundebug.


общаться с

Статья постоянно обновляется каждую неделю. Вы можете выполнить поиск «Big Move to the World» в WeChat, чтобы прочитать и обновить ее как можно скорее (на одну или две статьи раньше, чем в блоге). Эта статья находится на GitHub.GitHub.com/QQ449245884…Он был включен, и многие мои документы были разобраны. Добро пожаловать в Звезду и совершенство. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Кроме того, обратите внимание на паблик-аккаунт и ответьте в фоновом режиме.Благосостояние, вы можете увидеть преимущества, вы знаете.