获取计算样式并省略默认值
Get the computed style and omit defaults
我正在尝试获取元素的当前运行时样式并过滤掉具有默认值的属性。例如,使用如下标记:
<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
,但它返回了很多东西,我不确定如何过滤掉默认值。任何指示将不胜感激。
你去,我通过添加新的虚拟 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' ) ) );
笔记:
- 结果将具有一些额外的属性,而不仅仅是您提到的属性。
演示 - 应打开控制台
这是一个更强大的解决方案,使用 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's 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)
。
我已经根据 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's 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's CSS that differ from the browser's 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;
}
};
如果你之后需要使用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;
}
试试这个大小:
-
把它们放在某个地方。
<textarea id="t1"> </textarea>
<textarea id="t2"> </textarea>
<textarea id="t3"> </textarea>
<textarea id="t4"> </textarea>
-
下一个
function test() {
let arr = [];
let elem = _("right-Sidebar");
let cStyl = window.getComputedStyle(elem);
let txt1;
for (x of cStyl) { txt1 += x + "=" + cStyl[x] + "'n"; }
_("t1").value = txt1;
let ss = document.getElementsByTagName("Style");
const sstext = ss[0].innerHTML;
ss[0].innerHTML = "";
let elem2 = _("right-Sidebar");
let cStyl2 = window.getComputedStyle(elem2);
let txt2;
for (x2 of cStyl2) { txt2 += x2 + "=" + cStyl2[x2] + "'n"; }
_("t2").value = txt2;
let div = _el(elem.tagName);
let dfrag = new DocumentFragment();
dfrag.appendChild(div);
document.body.appendChild(dfrag);
let cStyl3 = window.getComputedStyle(div);
let txt3;
for (x3 of cStyl3) { txt3 += x3 + "=" + cStyl3[x3] + "'n"; }
_("t3").value = txt3;
alert(_("t3").value === _("t2").value);
let val1 = _("t2").value.split("'n");
let val2 = _("t1").value.split("'n");
let i = 0;
while (i < val1.length) {
if (val1[i] !== val2[i]) {
arr.push(val1[i] + "'n" + val2[i] + "'n'n'n");
}
i++;
}
_("t4").value = "";
_("t4").value = arr.join("'n");
}
这里是..使用纯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 向其添加元素,因此添加元素的样式不会受到文档默认样式的影响。这是小提琴
希望对你有帮助...
您可以使用,例如:
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 格式返回。
演示小提琴
- 我的shareService在angular 2中发送值工作正常,但当我渲染我的另一个组件时,会获得默认值
- jquerydatetimepicker日期和时间应在框默认值中,而无需单击框
- 如果值为空,如何设置输入的默认值?jQuery
- 骨干模型默认值-todos.js示例中不必要的代码
- jquery日期选择器年份范围默认值
- Html5输入属性的默认值,如最小值、最大值、大小等
- 根据两个下拉列表的默认值禁用按钮
- 如何创建具有默认值的JavaScript对象字段?(AngularJS模型相关)
- Angularjs-设置不带ng选项的select的默认值
- jQuery Datepicker从日期开始设置默认值
- 如何设置浏览器打开的文件对话框的文件名(一些默认值)
- 如何从范围滑块动态值计算输入值
- JQuery BlockUI鼠标加载光标没有't在Google Chrome中返回默认值
- Selectize选择默认值
- 如何修改或类似@model.count的内容,根据单元格值计算行数
- 在KeystoneJS中为Types.Money设置默认值
- 是否可以同时为一个元素的所有事件指定阻止默认值
- 防止在IE7中按回车键时出现默认值
- 如何覆盖jqGrid's语言默认值
- 获取计算样式并省略默认值