
Gjum Fuchs
Wie rufen Sie in JavaScript die Stile ab, die auf ein Element angewendet wurden, ausgenommen die Standardstile des Benutzeragenten (also nur Inline- und Stylesheet-Stile).
Grundsätzlich alle Benutzerstile, die Sie auf der Registerkarte „Berechnet“ Ihres bevorzugten Entwicklertools sehen können:

Bitte kein Framework, IE8+, Edge, Chrome und Firefox.
Ich erwarte, dass die Antwort das Ergebnis von sein wird getComputedStyle Minus- getDefaultComputedStyle, aber browserübergreifend. Da alle Entwicklertools dazu in der Lage sind, muss es eine Lösung geben 🙂

er-han
Es gibt eine schreibgeschützte Eigenschaft des Dokuments namens „styleSheets“.
var styleSheetList = document.styleSheets;
https://developer.mozilla.org/en-US/docs/Web/API/Document/styleSheets
Damit erreichen Sie alle Stile, die vom Autor verwendet werden.
Hier gibt es eine ähnliche Frage, aber kein Duplikat:
Ist es möglich, mit Javascript zu überprüfen, ob bestimmte CSS-Eigenschaften innerhalb des Style-Tags definiert sind?
Sie können den angewendeten Stil von einem Element erhalten, mit Ausnahme der Standardstile des Benutzeragenten, indem Sie die akzeptierte Antwort auf die Frage verwenden, die ich gerade erwähnt habe.
Diese Antwort lieferte nicht die des Elements style
Attributinhalt, also habe ich den Code ein wenig verbessert:
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({
order:i,
text:e.cssText
})
}
}
if(elm.getAttribute('style')) {
rules.push({
order:elementRules.length,
text:elm.getAttribute('style')
})
}
return rules;
}
function showStyle(){
var styleSheetList = document.styleSheets;
// get a reference to an element, then...
var div1 = document.getElementById("div1");
var rules = getAppliedCss(div1);
var str="";
for(i = 0; i < rules.length; i++) {
var r = rules[i];
str += '<br/>Style Order: ' + r.order + ' | Style Text: ' + r.text;
}
document.getElementById("p1").innerHTML = str;
}
#div1 {
float:left;
width:100px;
}
div {
text-align:center;
}
<div id="div1" style="font-size:14px;">
Lorem ipsum
</div>
<br/>
<br/>
<a href="https://stackoverflow.com/questions/42025329/javascript:;" onclick="showStyle()"> Show me the style. </a>
<p id="p1"><p>

Nur ein Student
Alle Entwicklertools können schummeln, weil sie Zugriff auf die Standardregeln haben, die der Browser anwendet, in den sie eingebaut sind.
Ich dachte, dass die folgenden Ansatz könnte funktionieren.
- Konstruieren Sie ein Element vom genau gleichen Typ (sagen wir a
div
oder p
) als derjenige, an dem wir interessiert sind.
- Hängen Sie dieses Element irgendwo auf der Seite an, sodass nur Standardbrowserregeln angewendet werden. Wir können dies tun, indem wir es in ein einfügen
iframe
.
Wenn Sie sicher sind, dass Sie keine Regeln haben, die darauf abzielen p
-Element, zum Beispiel, dann kann das Anhängen an den Körper effizienter sein.
- Überprüfen Sie die Unterschiede in den Stilen und geben Sie nur unterschiedliche Werte an.
- Temporäre Elemente bereinigen.
In der Praxis scheint es einigermaßen gut zu funktionieren. Ich habe dies nur in Firefox und Chrome getestet, aber ich denke, dass es auch in anderen Browsern funktionieren sollte – außer vielleicht der Tatsache, dass ich es verwendet habe für in und für … von, aber das könnte man leicht umschreiben. Beachten Sie, dass nicht Nur Die von Ihnen angegebenen Eigenschaften werden gemeldet, aber auch einige Eigenschaften, die von den von Ihnen angegebenen Eigenschaften beeinflusst werden. Beispielsweise entspricht die Rahmenfarbe der Textfarbe per Design und wird daher auch dann als unterschiedlich gemeldet, wenn Sie nur festlegen color: white
.
Zusammenfassend habe ich das Beispiel, das Sie in einem Ihrer Kommentare gepostet haben, genommen und a hinzugefügt getNonDefaultStyles
Funktion dazu, die meiner Meinung nach das tut, was Sie wollen. Es kann natürlich geändert werden, um Standardstile zu cachen, z. div
-Elemente und damit effizienter bei wiederholten Aufrufen (weil das Modifizieren der DOM ist teuer), aber es zeigt das Wesentliche.
Das folgende Snippet zeigt, wie die Version implementiert werden kann, die ein Element an den Körper anhängt. Aufgrund von Einschränkungen bei StackOverflow ist es nicht möglich, die anzuzeigen iframe
Version in einem Ausschnitt. Es ist auf möglich JSFiddle. Das folgende Snippet befindet sich auch in a Geige.
var textarea = document.getElementById("textarea"),
paragraph = document.getElementById("paragraph");
/**
* Computes applied styles, assuming no rules targeting a specific element.
*/
function getNonDefaultStyles(el) {
var styles = {},
computed = window.getComputedStyle(el),
notTargetedContainer = document.createElement('div'),
elVanilla = document.createElement(el.tagName);
document.body.appendChild(notTargetedContainer);
notTargetedContainer.appendChild(elVanilla);
var vanilla = window.getComputedStyle(elVanilla);
for (let key of computed) {
if (vanilla[key] !== computed[key]) {
styles[key] = computed[key];
}
}
document.body.removeChild(notTargetedContainer);
return styles;
}
var paragraphStyles = getNonDefaultStyles(paragraph);
for (let style in paragraphStyles) {
textarea.value += style + ": " + paragraphStyles[style] + "\n";
}
#paragraph {
background: red;
}
textarea {
width: 300px;
height: 400px;
}
<p id="paragraph" style="color: white">
I am a DIV
</p>
<p>
User styles:
</p>
<textarea id="textarea"></textarea>

Joe
Hier ist eine Funktion, die alle CSS-Regeln abruft, die auf ein Element angewendet wurden, entweder aus Inline-Stilen (HTML style
-Attribut) oder Stylesheets auf der Seite. Es erfasst auch relevante Keyframes für CSS-Animationen und die :active
, :hover
, ::before
und ::after
Selektoren.
function getAppliedCssData(el) {
// we create a unique id so we can generate unique ids for renaming animations
let uniqueId = "id" + Math.random().toString().slice(2) + Math.random().toString().slice(2);
let allRules = [...document.styleSheets].map(s => {
let rules = [];
try { rules.push(...s.cssRules) } catch(e) {} // we ignore cross-domain stylesheets with restrictive CORs headers
return rules;
}).flat();
let styleRules = allRules.filter(rule => rule.type === CSSRule.STYLE_RULE)
let fontFaceRules = allRules.filter(rule => rule.type === CSSRule.FONT_FACE_RULE);
let keyframesRules = allRules.filter(rule => rule.type === CSSRule.KEYFRAMES_RULE);
let matchingDefaultRules = styleRules.filter(rule => el.matches(rule.selectorText));
let nonMatchingRules = styleRules.filter(rule => !el.matches(rule.selectorText));
let matchingHoverRules = nonMatchingRules.filter(rule => el.matches(rule.selectorText.replace(/ :/g, " *:").replace(/([^(])(:hover)\b/g, "$1")));
let matchingActiveRules = nonMatchingRules.filter(rule => el.matches(rule.selectorText.replace(/ :/g, " *:").replace(/([^(])(:active)\b/g, "$1")));
let matchingBeforeRules = nonMatchingRules.filter(rule => el.matches(rule.selectorText.replace(/ :/g, " *:").replace(/::before\b/g, "")));
let matchingAfterRules = nonMatchingRules.filter(rule => el.matches(rule.selectorText.replace(/ :/g, " *:").replace(/::after\b/g, "")));
let allMatchingStyleRules = [...matchingActiveRules, ...matchingDefaultRules, ...matchingHoverRules, ...matchingBeforeRules, ...matchingAfterRules];
let matchingAnimationNames = allMatchingStyleRules.map(rule => rule.style.animationName).filter(n => n.trim());
let matchingKeyframeRules = keyframesRules.filter(rule => matchingAnimationNames.includes(rule.name));
// make name changes before actually grabbing the style text of each type
allMatchingStyleRules.forEach(rule => rule.style.animationName = rule.style.animationName+uniqueId);
matchingKeyframeRules.forEach(rule => rule.name = rule.name+uniqueId);
let matchingDefaultStyles = matchingDefaultRules.map(rule => rule.cssText).map(r => r.split(/[{}]/g)[1].trim()).join(" ") + (el.getAttribute('style') || ""); // important to add these last because inline styles are meant to override stylesheet styles (unless !important is used)
let matchingHoverStyles = matchingHoverRules.map(rule => rule.cssText).map(r => r.split(/[{}]/g)[1].trim()).join(" ");
let matchingActiveStyles = matchingActiveRules.map(rule => rule.cssText).map(r => r.split(/[{}]/g)[1].trim()).join(" ");
let matchingBeforeStyles = matchingBeforeRules.map(rule => rule.cssText).map(r => r.split(/[{}]/g)[1].trim()).join(" ");
let matchingAfterStyles = matchingAfterRules.map(rule => rule.cssText).map(r => r.split(/[{}]/g)[1].trim()).join(" ");
let matchingKeyframeStyles = matchingKeyframeRules.map(rule => rule.cssText).join(" ");
// undo the rule name changes because this actually affects the whole document:
matchingKeyframeRules.forEach(rule => rule.name = rule.name.replace(uniqueId, ""));
allMatchingStyleRules.forEach(rule => rule.style.animationName = rule.style.animationName.replace(uniqueId, ""));
let data = {
uniqueId,
defaultStyles: matchingDefaultStyles,
hoverStyles: matchingHoverStyles,
activeStyles: matchingActiveStyles,
keyframeStyles: matchingKeyframeStyles,
beforeStyles: matchingBeforeStyles,
afterStyles: matchingAfterStyles,
}
return data;
}
Das :focus
, :focus-within
und :visited
Selektoren sind nicht enthalten, könnten aber leicht hinzugefügt werden.

Josef238
Sie können die vom Benutzer angewendeten (nicht standardmäßigen) Stile berechnen, indem Sie sie mit einem „Standard“-HTML-Element mit demselben Tag-Namen vergleichen, das isoliert gerendert wird <iframe>
daher “lecken” keine Stile aus dem Dokument in das Standardelement.
Diese Lösung ist die gleiche wie @Just a student, fügt aber diese Verbesserungen hinzu:
- das
<iframe>
ist ein verstecktes HTML-Element, sodass der Benutzer es nicht sieht
- Für die Leistung werden Standardstile zwischengespeichert und wir warten, bis wir sie bereinigen
<iframe>
bis zum Ende, wenn wir anrufen removeSandbox
- es berücksichtigt die Vererbung (dh wenn Sie angeben
parentElement
es wird einen Stil auflisten, selbst wenn das übergeordnete Element ihn festlegt und das Element ihn auf den Standardwert zurücksetzt)
- Es berücksichtigt Situationen, in denen der Anfangswert und der berechnete Wert eines Standardstils nicht übereinstimmen (weitere Informationen finden Sie unter note [1] in diese PR)
// usage:
element = document.querySelector('div');
styles = getUserComputedStyles(element);
styles = getUserComputedStyles(element, parentElement);
// call this method when done to cleanup:
removeSandbox();
function getUserComputedStyles(element, parentElement = null) {
var defaultStyle = getDefaultStyle(element.tagName);
var computedStyle = window.getComputedStyle(element);
var parentStyle =
parentElement ? window.getComputedStyle(parentElement) : null;
var styles = {};
[...computedStyle].forEach(function(name) {
// If the style does not match the default, or it does not match the
// parent's, set it. We don't know which styles are inherited from the
// parent and which aren't, so we have to always check both.
// This results in some extra default styles being returned, so if you
// want to avoid this and aren't concerned about omitting styles that
// the parent set but the `element` overrides back to the default,
// call `getUserComputedStyles` without a `parentElement`.
const computedStyleValue = computedStyle[name];
if (computedStyleValue !== defaultStyle[name] ||
(parentStyle && computedStyleValue !== parentStyle[name])) {
styles[name] = computedStyleValue;
}
});
return styles;
}
var removeDefaultStylesTimeoutId = null;
var sandbox = null;
var tagNameDefaultStyles = {};
function getDefaultStyle(tagName) {
if (tagNameDefaultStyles[tagName]) {
return tagNameDefaultStyles[tagName];
}
if (!sandbox) {
// Create a hidden sandbox <iframe> element within we can create
// default HTML elements and query their computed styles. Elements
// must be rendered in order to query their computed styles. The
// <iframe> won't render at all with `display: none`, so we have to
// use `visibility: hidden` with `position: fixed`.
sandbox = document.createElement('iframe');
sandbox.style.visibility = 'hidden';
sandbox.style.position = 'fixed';
document.body.appendChild(sandbox);
// Ensure that the iframe is rendered in standard mode
sandbox.contentWindow.document.write(
'<!DOCTYPE html><meta charset="UTF-8"><title>sandbox</title><body>');
}
var defaultElement = document.createElement(tagName);
sandbox.contentWindow.document.body.appendChild(defaultElement);
// Ensure that there is some content, so properties like margin are applied
defaultElement.textContent=".";
var defaultComputedStyle =
sandbox.contentWindow.getComputedStyle(defaultElement);
var defaultStyle = {};
// Copy styles to an object, making sure that 'width' and 'height' are
// given the default value of 'auto', since their initial value is always
// 'auto' despite that the default computed value is sometimes an absolute
// length.
[...defaultComputedStyle].forEach(function(name) {
defaultStyle[name] = (name === 'width' || name === 'height')
? 'auto' : defaultComputedStyle.getPropertyValue(name);
});
sandbox.contentWindow.document.body.removeChild(defaultElement);
tagNameDefaultStyles[tagName] = defaultStyle;
return defaultStyle;
}
function removeSandbox() {
if (!sandbox) {
return;
}
document.body.removeChild(sandbox);
sandbox = null;
if (removeDefaultStylesTimeoutId) {
clearTimeout(removeDefaultStylesTimeoutId);
}
removeDefaultStylesTimeoutId = setTimeout(() => {
removeDefaultStylesTimeoutId = null;
tagNameDefaultStyles = {};
}, 20 * 1000);
}
Trotz dieser Verbesserungen werden für Blockelemente immer noch einige Standardstile aufgeführt, weil ihre anfänglichen und berechneten Werte nicht übereinstimmen, nämlich width
, height
, block-size
, inset-block
, transform-origin
und perspective-origin
(siehe Hinweis in Nr. 4). Diese Lösung im dom-to-image-mehr (das getUserComputedStyle
-Funktion) kann noch mehr davon wegschneiden, obwohl die Berechnung langsamer ist.
Ich habe diese Funktion in der Vergangenheit verwendet …
function get_style(obj,nam) { //obj = HTML element, nam = style property
var val = "";
if(document.defaultView && document.defaultView.getComputedStyle) {
nam = nam.replace(/[A-Z]/g,function(str) { //convert name into hypenated
return "-"+str.toLowerCase();
});
val = document.defaultView.getComputedStyle(obj,"").getPropertyValue(nam); //get current style
}
else if(obj.currentStyle) {
nam = nam.replace(/\-(\w)/g,function(str,p1) { //convert name into camel case
return p1.toUpperCase();
});
val = obj.currentStyle[nam]; //get current style
}
return val;
}
Es ermöglicht Ihnen, die Stileigenschaft entweder als Bindestrich (background-color
) oder Camel Case (backgroundColor
) und ersetzt es je nach verwendeter Methode.
Dies deckt auch ältere Browser ab, sogar alte IE!
10137200cookie-checkSo erhalten Sie den angewendeten Stil von einem Element, mit Ausnahme der Standardstile des Benutzeragentenyes
window.getComputedStyle() ?
– Alex K.
3. Februar 2017 um 13:23 Uhr
Mögliches Duplikat von Wie erhält man alle angewendeten Stile eines Elements, indem man einfach seine ID angibt?
– n_pflaume
3. Februar 2017 um 13:24 Uhr
@AlexK.: Nein, ich möchte nicht die Standardstile des Benutzeragenten: jsfiddle.net/701tg35d
– Gjum Fuchs
3. Februar 2017 um 13:33 Uhr
@n_palum Weder diese Frage noch ihre Antwort schließen den Standard-User-Agent-Stil für das Ergebnis aus
– Gjum Fuchs
3. Februar 2017 um 13:41 Uhr
getDefaultComputedStyle
ist kein Standard, also keine Option. Entwicklertools sind wahrscheinlich fest codiert, um zu wissen, was der Browser anwendet, daher ist dies möglicherweise nicht über Javascript möglich.– Rik Lewis
3. Februar 2017 um 13:56 Uhr