We are specialists at taking automated screenshots. We've been rendering for more than 10 years and have extensive experience ironing out tricky edge cases, often with E-Commerce sites.
This time we found a visual quirk when rendering a website with Puppeteer that ended up displaying a shopping cart drawer element across the entire page.
The Problem
When trying to render this page, we got a strange side effect:

The first thing I noticed when I visit the site using chrome, was that the shopping cart doesn't come up by default. Something in our rendering engine must have thought it an element which needed clicking or re-styling. I also noticed that the shopping cart opens to the right, but the screenshot shows it snapped to the left...
The Urlbox rendering engine has a few mechanisms for clicking elements on the page. These are performed in order to hide modals, click on cookie banners, and, for full page screenshots, hide fixed elements or make them absolute on the page while scrolling. We use more heuristic logic to find these elements that have characteristics of the elements we look for.
Here's the element in question:


And it's computed style:

We take some position: fixed;
elements and make them position:absolute;
. This allows those elements like a navbar/menu or chatbot to stay on the page but not scroll with the page as the screenshot is taken, causing them to appear duplicated rather than at the top/bottom of the page. This logic was finding this drawer element and accidentally including it in a list of elements that needed position:absolute
, causing the element to stick to the left of the DOM. If it included this type of element in the list for this site, then it could possibly do the same for other sites!
The Solution
I noticed that when closing the shopping cart, the computed style would add an X transformation to the element to place it out of the viewport, so to fix this and sites like it, we added some simple logic as a filter, to identify when a fixed element is likely to be a drawer, and not position it differently.
Here's an example:
function isTransformedOutOfView(elem: HTMLElement): boolean {
// Get the Element and viewport width
const width = elem.clientWidth;
const viewportWidth =
window.innerWidth || document.documentElement.clientWidth;
// Find out if there's a transform on the element
const transform = getComputedStyle(elem).transform;
// If there's no transform, or it's 'none', the element is not transformed out of view
if (!transform || transform === "none") {
return true;
}
// Check if the transform is a matrix transformation
// The matrix CSS method is as such: matrix(scaleX(), skewY(), skewX(), scaleY(), translateX(), translateY())
const matrixMatch = transform.match(/matrix\(([^)]+)\)/);
if (matrixMatch) {
// Extract the matrix values and parse them as numbers
const values = matrixMatch[1].split(",").map(Number);
const transformX = values[4];
// Get the element's position relative to the viewport
const rect = elem.getBoundingClientRect();
// Return false if the element is fully translated off-screen horizontally
return !(
(rect.right === 0 && width === transformX) ||
(rect.left === 0 && width === -transformX) ||
rect.left === viewportWidth ||
rect.right === -viewportWidth
);
}
return true;
}
The purpose of this function is to check that the element has a transformation on it horizontally (X). If it does and the element is fixed to the right, it would likely be a closed drawer if it's been transformed by its width, or in other words if width === transformX
. Positive transformations are to the right and negative to the left. This is why if the element is fixed to the left of the viewport, we invert the X transformation width === -transformX
, because we need to turn a negative transformation number into a positive to compare the element's width to it.
This is a good starting point for detecting fixed elements on the page, but there are a number of things one could do to improve this:
- Add some room/play for rough pixel differences between the transformation and width instead of a direct
===
check. This would account for other attributes which unexpectedly affect the element's size (margin/border etc). - Check for vertical drawers too, like this.
- Don't just check for a drawer made with transform, but also check the other ways that a developer could code in a slide-over/drawer, such as setting width or top/right/left/bottom on click.
Taking Screenshots the easier and more reliable way
By taking care to identify and filter out drawer-like elements from our list of candidates for position: absolute
, we ensure a more accurate and visually correct rendering of full-page screenshots. This is just one of many niche quirks we come across every day to refine our engine, so it can continue to take the millions of reliable screenshots it already has.
At Urlbox, we've already worked through the headaches you might be facing when trying to take screenshots of websites, HTML, PDFs and other web content.
We have a whole host of options that make it easy to get going and easy to highly customise your rendering experience, including battle tested full page renders.
We also offer AI prompts, Cloud storage, No code integrations with Zapier, taking screenshots through proxies, and a range or other features that could save you time and hassle.
Sign up for our free trial and give our sandbox a try, or contact us directly, and we can help you find the answers you're looking for ✌️.