Last active
March 7, 2023 05:39
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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