Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                Source:
<div class="container" style="background: #CCC;">
  <div id="source" class="block">
    T説🧜pѬѬasѪ"§§)("!编/)$=?!°&%)?§"$(§sw汉字编码§"$(§sw汉字方法orФdpѬѬasѪ"§§)("!/)$=?!°&%)?编码方法orФd
    <div class="block-child"></div>
  </div>
</div>

Target (Copy without child and overloaded style):
<div class="container">
  <img id="target"/>
</div>
<!-- Actual usage in JS panel line 140+ -->

              
            
!

CSS

              
                html {
  background: #000;
  color: white;
}

.block {
  position: relative;
  width: 100px;
  height: 100px;
  background: #8888;
  border-radius: 33%;
  color: white;
  font-size: 10px;
}

.container {
  padding: 15px;
}

.block-child {
  position: absolute;
  left: 70px;
  top: 20px;
  width: 50px;
  height: 50px;
  background: #333;
  border-radius: 33%;
}
              
            
!

JS

              
                //---------------------------------------------------
// Library code
// Example is below

const prefix = '___';
const captureShowClass = `${prefix}capture-show`;
const captureHideClass = `${prefix}capture-hide`;
const forceOverflowClass = `${prefix}force-overflow`;
const defaultOptions = {
    customStyle: '',
    excludedNodes: [],
    returnType: 'dataUrl',
    targetNode: document.body
};
let config = defaultOptions;
function addClasses(node) {
    node.classList.add(captureShowClass);
    let nodeParent = node.parentElement;
    for (const excludedEl of config.excludedNodes) {
        excludedEl.classList.add(captureHideClass);
    }
    while (nodeParent) {
        nodeParent.classList.add(forceOverflowClass);
        nodeParent = nodeParent.parentElement;
    }
}
function removeClasses(node) {
    node.classList.remove(captureShowClass);
    let nodeParent = node.parentElement;
    for (const excludedEl of config.excludedNodes) {
        excludedEl.classList.remove(captureHideClass);
    }
    while (nodeParent) {
        nodeParent.classList.remove(forceOverflowClass);
        nodeParent = nodeParent.parentElement;
    }
}
function serializeHead(elBoundingClientRect) {
    const headClone = document.head.cloneNode(true);
    const captureStyle = document.createElement('style');
    // Only the styled from the head are releavant so we grab them
    for (const childElement of Array.from(headClone.childNodes)) {
        if (!(childElement instanceof HTMLStyleElement)) {
            childElement.remove();
        }
    }
    // These are the style we apply on the element to move the body out off the visible area.
    // The remaining element will be moved back to its original position so it can be rendere without any background.
    // Addition Hint: Lineabreaks are parsed as <br> by the XMLParser so i need to have that syle in one line
    captureStyle.innerText += `foreignObject>div {`;
    captureStyle.innerText += `position: fixed;`;
    captureStyle.innerText += `top: ${window.outerHeight}px;`;
    captureStyle.innerText += `overflow: visible;`;
    captureStyle.innerText += `}`;
    captureStyle.innerText += `.${captureShowClass} {`;
    captureStyle.innerText += `position: fixed;`;
    captureStyle.innerText += `left: 0;`;
    captureStyle.innerText += `top: 0;`;
    captureStyle.innerText += `width: ${elBoundingClientRect.width}px;`;
    captureStyle.innerText += `height: ${elBoundingClientRect.height}px;`;
    captureStyle.innerText += `}`;
    captureStyle.innerText += `.${captureHideClass} {display: none !important;}`;
    captureStyle.innerText += `.${forceOverflowClass} {overflow: visible !important;}`;
    captureStyle.innerText += config.customStyle;
    headClone.appendChild(captureStyle);
    let resultHtml = '';
    for (const styleElement of Array.from(headClone.querySelectorAll('style'))) {
        resultHtml += styleElement.outerHTML;
    }
    return resultHtml;
}
function serializeBody() {
    return (document.body.innerHTML.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/g, ''));
}
function combineToSvg(node, elBoundingClientRect) {
    // Add Temporary identification classes
    addClasses(node);
    const documentHead = serializeHead(elBoundingClientRect);
    const documentBody = serializeBody();
    const offesetX = -elBoundingClientRect.left;
    const offesetY = -elBoundingClientRect.top;
    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
    svg.setAttribute('height', elBoundingClientRect.height.toString());
    svg.setAttribute('width', elBoundingClientRect.width.toString());
    const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
    foreignObject.removeAttribute('xmlns');
    foreignObject.setAttribute('x', '0'); // offesetX.toString())
    foreignObject.setAttribute('y', '0'); // offesetY.toString())
    foreignObject.setAttribute('height', window.outerHeight.toString());
    foreignObject.setAttribute('width', window.outerWidth.toString());
    const innerHtml = document.createElement('div');
    innerHtml.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
    innerHtml.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
    innerHtml.setAttribute('class', document.body.className);
    // additional namespace for rendering
    innerHtml.innerHTML = documentBody;
    foreignObject.appendChild(innerHtml);
    svg.insertAdjacentHTML('afterbegin', documentHead);
    svg.appendChild(foreignObject);
    // Remove Temporary identification classes
    removeClasses(node);
    const svgString = new XMLSerializer().serializeToString(svg);
    return svgString;
}
function nodeToDataURL(userConfig) {
    config = Object.assign(Object.assign({}, defaultOptions), userConfig);
    const node = config.targetNode;
    const elBoundingClientRect = node.getBoundingClientRect();
    const svg = combineToSvg(node, elBoundingClientRect);
    // Build base64 data url
    const svgBase64 = encodeURIComponent(svg);
    const dataURL = `data:image/svg+xml,${svgBase64}`;
    const canvas = document.createElement('canvas');
    return new Promise((resolve, reject) => {
        if (!canvas) {
            reject();
            return;
        }
        // Load data URL into a Image
        const img = document.createElement('img');
        // In case the generated dataURL in invalid
        img.addEventListener('error', () => {
            canvas.remove();
            reject();
            return;
        });
        // Wait for the image to be loaded, otherwise the buffer is empty
        img.addEventListener('load', () => {
            // For debugging feel free to use this fiddle
            // https://jsfiddle.net/j0asnubp/9/
            // just paste in the base64URL
            canvas.width = elBoundingClientRect.width;
            canvas.height = elBoundingClientRect.height;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0);
            resolve(canvas.toDataURL());
            canvas.remove();
        });
        // only attach the data URL after all eventHandler are attached
        img.src = dataURL;
    });
}

//--------------------------------------------------
// Example code

const visualSource = document.getElementById('source')
const imageTarget = document.getElementById('target')
const excluded = document.querySelectorAll('.block-child')

nodeToDataURL({
  targetNode: visualSource,
  excludedNodes: excluded,
  customStyle: '.block { background: red; }'
})
  .then((url) => {
  imageTarget.setAttribute('src', url);
})
              
            
!
999px

Console