function getStyles(el, results = []) { const styles = window.getComputedStyle(el) const css = Array.from(styles).map(prop => ` ${prop}: ${styles.getPropertyValue(prop)};`).join('\n') const selector = el.tagName.toLowerCase() + (el.id ? `#${el.id}` : '') + (el.className && typeof el.className === 'string' ? `.${el.className.trim().split(/\s+/).join('.')}` : '') results.push(`${selector} {\n${css}\n}`) for (const child of el.children) getStyles(child, results) return results.join('\n\n') } // shorter byt doesn't always get everything function getStyles(el, results = []) { const styles = window.getComputedStyle(el) const dummy = document.createElement(el.tagName) document.body.appendChild(dummy) const defaultStyles = window.getComputedStyle(dummy) const css = Array.from(styles) .filter(prop => styles.getPropertyValue(prop) !== defaultStyles.getPropertyValue(prop)) .map(prop => ` ${prop}: ${styles.getPropertyValue(prop)};`) .join('\n') document.body.removeChild(dummy) const selector = el.tagName.toLowerCase() + (el.id ? `#${el.id}` : '') + (el.className && typeof el.className === 'string' ? `.${el.className.trim().split(/\s+/).join('.')}` : '') if (css) results.push(`${selector} {\n${css}\n}`) for (const child of el.children) getStyles(child, results) const output = results.join('\n\n') const ta = document.createElement('textarea') ta.value = output document.body.appendChild(ta) ta.select() document.execCommand('copy') document.body.removeChild(ta) return output } getStyles(document.querySelector('section'))