Изучение CSS через CSS OM

Изучение CSS через CSS OM

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

Но я знала, что если бы мы собирались делать это вручную, очень легко пропустить несколько менее популярных свойств, и правило именования, в котором сокращенные обозначения являются префиксом их полных свойств, не удалось стандартизировать. А теперь исключений даже больше, чем раньше. И даже если мы проделаем невероятно тщательную работу, в следующем году структура данных будет неточной, потому что CSS и его реализации быстро развиваются. Браузер знает, что такое сокращения, конечно же, мы сможем получить от него информацию… верно? Затем мы могли бы использовать его напрямую, если это клиентская библиотека, или в случае с Альманахом, где код должен быть быстрым, потому что он будет работать на миллионах веб-сайтов, вставить предварительно вычисленный результат в любой скрипт, который мы запускаем.

По сути, для этого есть два этапа:

Получить список всех свойств CSS

Выяснить, как проверить, является ли данное свойство сокращенным, и как получить его полное обозначение, если это так.

Я решил рассказать эту историю в обратном порядке. В моем исследовании я сначала сосредоточился на выяснении сокращений (2), потому что я много раз кодировал получение списка свойств, но поскольку (1) полезен сам по себе (и, вероятно, в большем количестве случаев использования), я почувствовал, что имеет смысл сначала изучить это.

Примечание: document.body в этих примерах я использую вместо фиктивного элемента, потому что мне нравится экспериментировать на about:blank, и он просто есть, и потому, что таким образом вы можете легко скопировать вещи в консоль и применить их где угодно, даже прямо здесь, читая этот пост. Однако, если вы используете это как часть кода, работающего на реальном веб-сайте, само собой разумеется, что вы должны вместо этого создавать и тестировать что-то на фиктивном элементе!

Получение списка всех свойств CSS из браузера

В Chrome и Safari это так же просто, как Object.getOwnPropertyNames(document.body.style). Однако в Firefox это не работает. Почему? Чтобы понять это (и как это обойти), нам нужно копнуть немного глубже.

В Chrome и Safari element.style — это экземпляр CSSStyleDeclaration. Однако в Firefox это экземпляр, наследуемый от экземпляра CSS2Properties — это более старый интерфейс, определенный в спецификации DOM 2, которая теперь устарела. В текущей соответствующей спецификации CSS2Properties удалено и объединено с CSSStyleDeclaration. Однако Firefox еще до этого не дошел.

Изучение CSS через CSS OM

Firefox слева, Safari справа. Chrome ведет себя так же, как Safari

Поскольку свойства включены в CSSStyleDeclaration, они не являются собственными свойствами element.style, поэтому он не может их вернуть. Однако мы можем извлечь экземпляр CSSStyleDeclaration с помощью __proto__ или Object.getPrototypeOf (), а затем Object.getOwnPropertyNames(Object.getPrototypeOf(document.body.style)) даст нам то, что мы хотим!

Таким образом, мы можем объединить два этих метода, чтобы получить список свойств независимо от браузера:

let properties = Object.getOwnPropertyNames( style.hasOwnProperty("background")? style : style.__proto__
);

А затем мы просто отбрасываем не-свойства и переводим из camelCase:

properties = properties.filter(p => style[p] === "") // drop functions etc .map(prop => { // de-camelCase prop = prop.replace(/[A-Z]/g, function($0) { return '-' + $0.toLowerCase() }); if (prop.indexOf("webkit-") > -1) { prop = "-" + prop; } return prop; });

Вы можете увидеть код с результатом здесь:

Проверка того, является ли свойство сокращенным, и получение списка полных обозначений

Главное отметить:

Когда вы устанавливаете сокращение для встроенного стиля элемента, вы, по сути, устанавливаете все его полные свойства.

element.style на самом деле подобен массиву, с числовыми свойствами, и .length дает вам количество установленных для него свойств. Это означает, что вы можете использовать оператор распространения.

> document.body.style.background = "red";
> [...document.body.style]
< [ "background-image", "background-position-x", "background-position-y", "background-size", "background-repeat-x", "background-repeat-y", "background-attachment", "background-origin", "background-clip", "background-color"
]

Интересно, что document.body.style.cssText сериализует в background: red, а не все полные свойства. Существует одно исключение: свойство all. В Chrome это работает не совсем так:

> document.body.style.all = "inherit";
> [...document.body.style]
< ["all"]

Тогда как в Safari и Firefox это фактически возвращает каждое свойство, которое не является сокращением!

Изучение CSS через CSS OM

Firefox и Safari расширяют all буквально до всех не сокращенных свойств

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

Итак, резюмируя, мы можем легко получить длинную форму данного сокращения:

function getLonghands(property) { let style = document.body.style; style[property] = "inherit"; // a value that works in every property let ret = [...style]; style.cssText = ""; // clean up return ret;
}

Собираем все вместе

Вы можете увидеть, как все части сочетаются друг с другом (и результат!) В этом коде:

Сколько из этих сокращений вы уже знали?

Автор: Lea Verou

Источник: https://lea.verou.me

Редакция: Команда webformyself.