От автора: для некоторых статистических данных, которые мы собираемся изучить для веб-альманаха этого года, нам может потребоваться список сокращений 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 еще до этого не дошел.
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 это фактически возвращает каждое свойство, которое не является сокращением!
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.