Skip to content

Instantly share code, notes, and snippets.

@dfkaye
Last active March 7, 2023 05:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dfkaye/1442ed44b629980e08a68203f66be659 to your computer and use it in GitHub Desktop.
Save dfkaye/1442ed44b629980e08a68203f66be659 to your computer and use it in GitHub Desktop.
style replace vs. style merge - differences between replacing vs. merging style attribute and style properties
// 3-6 March 2023
// style attributes vs. style properties
// differences between replace vs. merge
// replacing props vs. replacing attributes
// no surprises
// merging props vs. merging attributes
// at least one surprise, namely, that adding a style property
// creates a style attribute on elements without one initially.
// (which led to a weird test result, since corrected).
function replace(target, source) {
Array
.from(source.attributes)
.forEach(function (attr, i) {
target.setAttribute(attr.name, attr.value);
});
}
function merge(target, source) {
Array
.from(source.style)
.forEach(function (prop) {
target.style[prop] = source.style[prop];
});
}
/* test it out */
// helper
function parseElement(str) {
return new DOMParser()
.parseFromString(String(str).trim(), 'text/html')
.body.firstElementChild;
};
var target = parseElement(`
<p style="background-color: initial; color: initial; border: initial;">
content
</p>
`);
var target2 = target.cloneNode(true);
var target3 = target.cloneNode(true);
target3.removeAttribute("style")
target3.style.backgroundColor = "initial";
target3.style.color = "initial";
target3.style.border = "initial";
var target4 = target.cloneNode(true);
target4.removeAttribute("style")
target4.style.backgroundColor = "initial";
target4.style.color = "initial";
target4.style.border = "initial";
var source = parseElement(`
<p style="color: unset; border: unset; text-decoration: unset;">
content
</p>
`);
var source2 = source.cloneNode(true);
source2.removeAttribute("style");
source2.style.color = "unset";
source2.style.border = "unset";
source2.style.textDecoration = "unset";
// document.body.append(source, source2);
// replace target with style attribute using source with style attribute
replace(target, source);
console.warn(target.outerHTML);
/*
<p style="color: unset; border: unset; text-decoration: unset;">
content
</p>
*/
// merge source with style attribute over target with style attribute
merge(target2, source);
console.log(target2.outerHTML);
/*
<p style="background-color: initial; color: unset; border: unset; text-decoration: unset;">
content
</p>
*/
// replace target with style property using source with style property
replace(target3, source2);
console.warn(target3.outerHTML);
/*
<p style="color: unset; border: unset; text-decoration: unset;">
content
</p>
*/
// merge source with style property over target with style property
merge(target4, source2);
console.log(target4.outerHTML);
/*
<p style="background-color: initial; color: unset; border: unset; text-decoration: unset;">
content
</p>
*/
// replace target with style attribute using source with style property
var target5 = target.cloneNode(true);
replace(target5, source2);
console.warn(target5.outerHTML);
/*
<p style="color: unset; border: unset; text-decoration: unset;">
content
</p>
*/
// merge source with style property over target with style attribute
var target6 = parseElement(`
<p style="background-color: initial; color: initial; border: initial;">
content
</p>
`);
merge(target6, source2);
console.log(target6.outerHTML);
/*
<p style="background-color: initial; color: unset; border: unset; text-decoration: unset;">
content
</p>
*/
// replace target with style property using source with style attribute
var target7 = target.cloneNode(true);
target7.removeAttribute("style")
target7.style.backgroundColor = "initial";
target7.style.color = "initial";
target7.style.border = "initial";
replace(target7, source);
console.warn(target7.outerHTML);
/*
<p style="color: unset; border: unset; text-decoration: unset;">
content
</p>
*/
// merge source with style attribute over target with style property
var target8 = target.cloneNode(true);
target8.removeAttribute("style")
target8.style.backgroundColor = "initial";
target8.style.color = "initial";
target8.style.border = "initial";
merge(target8, source);
console.log(target8.outerHTML);
/*
<p style="background-color: initial; color: unset; border: unset; text-decoration: unset;">
content
</p>
*/
// Surprises
// Setting the style property creates a style attribute on elements without one.
var s = parseElement(`
<p>content</p>
`);
console.log(s.hasAttribute('style'))
// false
s.style.color = "red";
console.log(s.getAttribute('style') === "color: red;")
// true
// As a result, removing that style attribute removes the style property
console.log(s.style.length > 0)
// true
s.removeAttribute('style');
console.log(s.style.length > 0)
// false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment