Получить вычисленный стиль и опустить значения по умолчанию
Я пытаюсь получить текущий стиль выполнения элемента и отфильтровать свойства, которые имеют значения по умолчанию. Например, с разметкой следующим образом:
<style>
.foo { background: red }
span { font-size:30px }
</style>
<div style="color: blue">
<span id="bar" class="foo">hello</span>
</div>
Я бы хотел, чтобы результат был:
background-color: red;
color: blue;
font-size: 30px;
Я пробовал window.getComputedStyle
, но он возвращает много вещей, и я не уверен, как отфильтровывать значения по умолчанию. Любые указатели будут оценены.
Ответы
Ответ 1
там вы идете,
Я сделал это, добавив новый элемент DOM DOM, чтобы узнать, какие стили по умолчанию для любого элемента.
/**
* IE does not have `getComputedStyle`
*/
window.getComputedStyle = window.getComputedStyle || function( element ) {
return element.currentStyle;
}
/**
* get computed style for an element, excluding any default styles
*
* @param {DOM} element
* @return {object} difference
*/
function getStylesWithoutDefaults( element ) {
// creating an empty dummy object to compare with
var dummy = document.createElement( 'element-' + ( new Date().getTime() ) );
document.body.appendChild( dummy );
// getting computed styles for both elements
var defaultStyles = getComputedStyle( dummy );
var elementStyles = getComputedStyle( element );
// calculating the difference
var diff = {};
for( var key in elementStyles ) {
if(elementStyles.hasOwnProperty(key)
&& defaultStyles[ key ] !== elementStyles[ key ] )
{
diff[ key ] = elementStyles[ key ];
}
}
// clear dom
dummy.remove();
return diff;
}
/**
* usage
*/
console.log( getStylesWithoutDefaults( document.getElementById( 'bar' ) ) );
Примечания:
- результат будет иметь некоторые дополнительные свойства, а не только те, которые вы упомянули.
демонстрационная консоль должна быть открыта
Ответ 2
Здесь более надежное решение, используя iframe
. Это решение неэффективно для более чем одного элемента за раз, и в этом случае вы захотите использовать фрагмент для вставки пакетного элемента и передать массив имен тегов.
var getDefaultStyling = function(tagName){
if(!tagName) tagName = "dummy-tag-name";
// Create dummy iframe
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
// Create element within the iframe document
var iframeDocument = iframe.contentDocument;
var targetElement = iframeDocument.createElement(tagName);
iframeDocument.body.appendChild(targetElement);
// Grab styling (CSSStyleDeclaration is live, and all values become "" after element removal)
var styling = iframe.contentWindow.getComputedStyle(targetElement);
var clonedStyling = {};
for(var i = 0, len = styling.length; i < len; i++){
var property = styling[i];
clonedStyling[i] = property;
clonedStyling[property] = styling[property];
}
// Remove iframe
document.body.removeChild(iframe);
// Return cloned styling
return clonedStyling;
};
var getUniqueUserStyling = function(element){
var allStyling = window.getComputedStyle(element);
var defaultStyling = getDefaultStyling(element.tagName);
var userStyling = {};
for(var i = 0, len = allStyling.length; i < len; i++){
var property = allStyling[i];
var value = allStyling[property];
var defaultValue = defaultStyling[property];
if(value != defaultValue){
userStyling[property] = value;
}
}
return userStyling;
};
Использование: getUniqueUserStyling(myElement)
.
Ответ 3
Я построил то, что я считаю более современным, полным и эффективным решением, основанным на ответе Mattsven.
Все, что вам нужно сделать, это вызвать метод getUserStyles с узлом в качестве параметра, например: Styles.getUserStyles(document.querySelector('#bar'))
Очевидно, этот фрагмент не был создан с учетом поддержки более старых браузеров, поэтому необходимо внести некоторые изменения, если вы хотите использовать его на общедоступном веб-сайте.
class Styles {
// Returns a dummy iframe with no styles or content
// This allows us to get default styles from the browser for an element
static getStylesIframe() {
if (typeof window.blankIframe != 'undefined') {
return window.blankIframe;
}
window.blankIframe = document.createElement('iframe');
document.body.appendChild(window.blankIframe);
return window.blankIframe;
}
// Turns a CSSStyleDeclaration into a regular object, as all values become "" after a node is removed
static getStylesObject(node, parentWindow) {
const styles = parentWindow.getComputedStyle(node);
let stylesObject = {};
for (let i = 0; i < styles.length; i++) {
const property = styles[i];
stylesObject[property] = styles[property];
}
return stylesObject;
}
// Returns a styles object with the browser default styles for the provided node
static getDefaultStyles(node) {
const iframe = Styles.getStylesIframe();
const iframeDocument = iframe.contentDocument;
const targetElement = iframeDocument.createElement(node.tagName);
iframeDocument.body.appendChild(targetElement);
const defaultStyles = Styles.getStylesObject(targetElement, iframe.contentWindow);
targetElement.remove();
return defaultStyles;
}
// Returns a styles object with only the styles applied by the user CSS that differ from the browser default styles
static getUserStyles(node) {
const defaultStyles = Styles.getDefaultStyles(node);
const styles = Styles.getStylesObject(node, window);
let userStyles = {};
for (let property in defaultStyles) {
if (styles[property] != defaultStyles[property]) {
userStyles[property] = styles[property];
}
}
return userStyles;
}
};
Ответ 4
Здесь опция, если вам нужно использовать getPropertyValue впоследствии, как здесь
var computedStyles = getComputedStyles(document.body);
var propertyValue = computedStyles.getPropertyValue("prop-name");
Используйте эту функцию:
function getDefaultComputedStyles(el)
{
var temp = document.createElement("div");
document.body.appendChild(temp);
var defaultStyles = getComputedStyle(temp);
var extraStyles = getComputedStyle(el);
var foundStyles = [];
for(var i=0; i<defaultStyles.length; i++)
{
var extraStyleIndex = extraStyles[i];
var extraStyleValue = extraStyles.getPropertyValue(extraStyles[i]);
if(defaultStyles.getPropertyValue(defaultStyles[i]) !== extraStyleValue)
{
foundStyles.push(JSON.parse('{"${extraStyleIndex}":"${extraStyleValue}"}'));
}
}
foundStyles.getPropertyValue = function(ind){
var result = this.filter(el => ('${ind}' in el));
return result[0]!=undefined ? result[0][Object.keys(result[0])] : null;
}
return foundStyles;
}
Ответ 5
Вы можете использовать, например:
window.getComputedStyle(document.getElementById('bar'))
Это вернет объект, содержащий все вычисленные стили для элемента с id
'bar.
Итак, например, вы могли бы сделать:
var styles = window.getComputedStyle(document.getElementById('bar'));
styles = "background-color:" + styles['background-color'] + ";color:" + styles['color'] + ";font-size:" + styles['font-size'] + ";";
console.log(styles);
Обратите внимание, что значения цвета будут возвращены в формате RGBA.
Ответ 6
Вот он.. с использованием чистого javscript.. Я только добавил jquery к скрипту, чтобы установить событие document.ready.
Вот код:
$(document).ready(function () {
var div = document.getElementById('output');
var x = document.getElementById('frame').contentWindow.document.createElement('x');
document.getElementById('frame').contentWindow.document.body.appendChild(x);
var defautlStyles = window.getComputedStyle(x);
var barStyles = window.getComputedStyle(document.getElementById('bar'));
for (i = 0; i < defautlStyles.length; i++) {
if (defautlStyles["" + defautlStyles[i]] != barStyles["" + barStyles[i]]) {
var p = document.createElement('p');
p.innerText += barStyles[i] + ": " + barStyles["" + barStyles[i]];
div.appendChild(p);
}
}
});
Я использовал iframe для добавления к нему элемента, поэтому стиль добавленного элемента не будет зависеть от стилей по умолчанию для документа.
И вот FIDDLE
Надеюсь, что это поможет...