Как определить все CSS стилей, которые применяются непосредственно к элементу? - PullRequest
1 голос
/ 09 апреля 2020

Можно ли получить все стили CSS, которые применяются к данному элементу HTML, либо в его свойстве / атрибуте styles, либо с помощью селекторов CSS?

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

Вот пример того, что НЕ РАБОТАЕТ.

let span = document.querySelector('span') ;
let compStyles = getComputedStyle(span) ;

console.log('The desired result is: "color: blue; font-style: italic"' ) ;
console.log('But instead we get: ', compStyles.cssText ) ;
div {color: red; font-weight: bold}
span {color: blue}
<div>
Hello <span style="font-style: italic">world</span>
</div>

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

Например, DevTools показывает вверху ...
(1) эффективные стили, примененные к элементу, и ниже что он показывает ...
(2) стили, унаследованные от родителя. Затем на другой вкладке отображаются ...
(3) все вычисленные стили.

Я ищу только число (1).


Зачем мне это нужно.

Когда вы выбираете текст на странице и копируете этот текст, Chrome вставляет в буфер обмена HTML код, который выглядит следующим образом:

<span style="color: rgb(255, 0, 0); font-family: 'Times New Roman'; font-size: medium; font-style: normal; font-variant: normal; font-weight: bold; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; display: inline !important;">
    Hello
</span>
<span style="color: blue; font-family: 'Times New Roman'; font-size: medium; font-variant: normal; font-weight: bold; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; font-style: italic;">
    world
</span>

т. е. каждый элемент имеет все свои встроенные стили в своем атрибуте style. Таким образом, код HTML можно вставить в любое другое место, и он будет выглядеть одинаково.
Что делает Chrome, так это делает код HTML независимым от любых таблиц стилей, которые могут существовать на исходной странице.

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

Однако я хочу избежать того, что в результате получается HTML в итоге получается смехотворно большим.
Если я просто возьму результат getComputedStyle для каждого элемента, финальная HTML будет гигантской c строкой.

Chrome хорошо работа по внедрению «важных» стилей (тех, которые имеют значение), вместо того, чтобы встраивать буквально все возможные свойства стиля в каждый элемент HTML.

1 Ответ

1 голос
/ 09 апреля 2020

В целом это представляется возможным, однако это действительно создает впечатление, что это невозможно в Chrome.

TL; DR: с Chrome 64 вам нужно будет использовать локальный сервер разработки для тестирования функциональности, которая зависит от CSS объектной модели.

В этом фрагменте ниже используется этот код, с некоторыми небольшие изменения для случая ОП.

var proto = Element.prototype;
var slice = Function.call.bind(Array.prototype.slice);
var matches = Function.call.bind(proto.matchesSelector ||
  proto.mozMatchesSelector || proto.webkitMatchesSelector ||
  proto.msMatchesSelector || proto.oMatchesSelector);

// Returns true if a DOM Element matches a cssRule
var elementMatchCSSRule = function(element, cssRule) {
  return matches(element, cssRule.selectorText);
};

// Returns true if a property is defined in a cssRule
var propertyInCSSRule = function(prop, cssRule) {
  return prop in cssRule.style && cssRule.style[prop] !== "";
};

// Here we get the cssRules across all the stylesheets in one array
var cssRules = slice(document.styleSheets).reduce(function(rules, styleSheet) {
  return rules.concat(slice(styleSheet.cssRules));
}, []);

var getAppliedCss = function(elm) {
  // get only the css rules that matches that element
  var elementRules = cssRules.filter(elementMatchCSSRule.bind(null, elm));
  var rules = [];
  if (elementRules.length) {
    for (i = 0; i < elementRules.length; i++) {
      var e = elementRules[i];
      rules.push({
        text: e.cssText.match(/\w\s{\s(.*?)}/)[1]
      })
    }
  }

  if (elm.getAttribute('style')) {
    rules.push({
      text: elm.getAttribute('style')
    })
  }
  return rules;
}

var styleSheetList = document.styleSheets;

let span = document.querySelector('span');

var rules = getAppliedCss(span);

console.log(rules.map(r => r.text).join(''));
div {color: red; font-weight: bold}
span {color: blue}
<div>
  Hello <span style="font-style: italic">world</span>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...