Notes:
- Version 3* due to misreading question
- Copying to clipboard does not work in StackOverflow snippet, try offline
We can use getComputedStyle()
to get all the computed styling for an element.
We can map this to inline css and add it to the DOM using setAttribute
Since getComputedStyle()
literally returns all the styling, most of them won't be needed. I'd recommend using a whitelist style. (See second snippet below)
Small demo, press the button to copy the text.
All the div
style's will be inline, somewhere in that huge list will be border
etc.
function getOuterHTMLWithInlineStyle(el) {
let s = getComputedStyle(el);
let i = []
for (let key in s) {
if (!Number.isInteger(+key)) {
let prop = key.replace(/\-([a-z])/g, v => v[1].toUpperCase());
i.push(`${key}: ${s[key]}`);
}
}
el.setAttribute('style', i.join("; "));
return el.outerHTML;
}
function copy() {
const e = document.querySelector('div')
const html = getOuterHTMLWithInlineStyle(e)
navigator.clipboard.writeText(html).then(() => {
console.log('Succesfully copied HTML to clipboard');
}, function(err) {
console.error('Could not copy text.\nTried to copy the following:\n', html);
});
}
div {
padding: 5px 25px;
border: 1px solid red;
}
<div>Hello World!</div>
<br>
<button onClick='copy()'>Click me to copy</button>
Second answer, using a whitelist
Same demo as above, but with the whitelist added:
Will copy the following HTML:
<div style="border: 1px solid rgb(255, 0, 0); padding: 5px 25px">Hello World!</div>
function getOuterHTMLWithInlineStyle(el, whitelist = [ 'border', 'padding' ]) {
let s = getComputedStyle(el);
let i = []
for (let key in s) {
if (whitelist.includes(key)) {
let prop = key.replace(/\-([a-z])/g, v => v[1].toUpperCase());
i.push(`${key}: ${s[key]}`);
}
}
el.setAttribute('style', i.join("; "));
return el.outerHTML;
}
function copy() {
const e = document.querySelector('div')
const html = getOuterHTMLWithInlineStyle(e)
navigator.clipboard.writeText(html).then(() => {
console.log('Succesfully copied HTML to clipboard');
}, function(err) {
console.error('Could not copy text.\nTried to copy the following:\n', html);
});
}
div {
padding: 5px 25px;
border: 1px solid red;
}
<div>Hello World!</div>
<br>
<button onClick='copy()'>Click me to copy</button>
Oke, v3, based on this SO answer where the user uses document.styleSheets
to get only the css from stylesheets and filter that on those who are non-default.
Using a map()
and regex, we can get a string with just containing the CSS values you need.
Note this might not work 100%, the regex does not take into account that CSS values might contain {
's. You should improve the regex if you have very complex values.
The (collapsed) snippet below will output/copy the following HTML:
<div style="padding: 5px 25px; border: 1px solid red;">Hello World!</div>
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);
var elementMatchCSSRule = function(element, cssRule) {
return matches(element, cssRule.selectorText);
};
var cssRules = slice(document.styleSheets).reduce(function(rules, styleSheet) {
return rules.concat(slice(styleSheet.cssRules));
}, []);
var getAppliedCss = function(elm) {
var elementRules = cssRules.filter(elementMatchCSSRule.bind(null, elm));
var rules =[];
if (elementRules.length) {
for (i = 0; i < elementRules.length; i++) {
rules.push(elementRules[i].cssText)
}
}
return rules.map(r => /\{(.+)\}/g.exec(r)[1].trim()).join("; ");
}
function getOuterHTMLWithInlineStyle(el) {
el.setAttribute('style', getAppliedCss(el));
return el.outerHTML;
}
function copy() {
const e = document.querySelector('div')
const html = getOuterHTMLWithInlineStyle(e)
navigator.clipboard.writeText(html).then(() => {
console.log('Succesfully copied HTML to clipboard');
}, function(err) {
console.error('Could not copy text.\nTried to copy the following:\n', html);
});
}
div {
padding: 5px 25px;
border: 1px solid red;
}
<div>Hello World!</div>
<br>
<button onClick='copy()'>Click me to copy</button>