3

Background: I'm using a tool to take an automated, "full page" screenshot of a webpage. It does this, by scrolling through a web page, taking screenshots, and stitching them together. (no prizes for guessing which tool).

The problem: sticky and fixed html elements ruin the stitching of the images. (essentially every screenshot "snippet" has a banner/footer included in it). See below...

enter image description here


Question: Is there a way I can instruct a webpage to treat fixed and sticky css as fixed? (Or negate their effect, by setting up scrolling within a sub element?)

Interim solutions...

Solution 1: I can crop the images as it goes (e.g. crop 200px top & bottom). BUT that requires knowing(/assuming) the height of the elements beforehand.

Solution 2: Load the website in an iframe, and set the iframe height to the height of the inner page. This works perfectly, EXCEPT I run into CSP issues accessing other websites.

Assumptions:

  • we can execute Javascript in the browser (e.g. modify dom, css, etc)
  • only for Firefox and Chrome
  • using native Javascript (no libraries)
  • automated (no human involved)

For example, I've attempted setting fixed and sticky css elements to relative (/absolute), which works for 90% (but not 100% correct).

var elems = document.body.getElementsByTagName("*");
for (var i=0;i<elems.length;i++) {
    const pos = window.getComputedStyle(elems[i],null).getPropertyValue('position')
    if (pos == 'sticky' || pos == 'fixed') {
        elems[i].style = "position:relative !important;"
    }
}

I'm using the following page for testing: https://digitalocean.com/pricing/

Update: I'd be happy with making the sticky/fixed objects transparent. (Note to self: investigate)

Similar (but different) questions:

  1. Capture full webpage screenshot in selenium that has sticky header - suggests using other library and aforementioned (discounted) suggested solutions
  2. Take full localhost webpage screenshot (Firefox, Windows)? - manual solution
  3. Full WebPage screenshot using javascript - suggested solution is to use html2canvas library
Nick Grealy
  • 24,216
  • 9
  • 104
  • 119
  • Wrong tool? https://www.utilitylog.com/full-page-screenshot-chrome/ The assumptions are not clear. Do you have to be able to automate this? – Capsule Jul 08 '19 at 02:27
  • 2
    Just an idea, as far as I remember, sticky elements must have either a top, left... attribute. If you could just remove those, sticky will not be sticky anymore. – djnose Jul 08 '19 at 02:39
  • @Capsule - yes, automating the solution (fyi using `selenium-webdriver`) – Nick Grealy Jul 08 '19 at 03:13
  • @djnose - No luck, same effect as setting `position:relative;` - thanks though! – Nick Grealy Jul 08 '19 at 04:14
  • @NickGrealy thats a pitty :(. What is the effect? Did you check if they are really removed? (like all, bottom, top, left, right) – djnose Jul 08 '19 at 04:21
  • @djnose - using `elems[i].style = "top:auto !important;left:auto !important;right:auto !important;bottom:auto !important;"`, the `position:fixed;` still scrolls with the window (in Chrome). (I assume it worked for sticky though). Give it a go... -> https://digitalocean.com/pricing/ – Nick Grealy Jul 08 '19 at 04:39
  • @NickGrealy, a bit hardcore, but that works for me :D `var elems = document.body.getElementsByTagName("*"); for (var i=0;i – djnose Jul 08 '19 at 04:49

1 Answers1

0

For fixed element you can rely on transform or filter to change the containing block and disable the fixed behavior (explained here: CSS-Filter on parent breaks child positioning)

Here is a basic example. Generally we need to apply this to body.

.fixed {
  position:fixed;
  bottom:0;
  left:0;
  right:0;
  background:red;
  height:56px;
}

body {
  margin:0;
  height:220vh;
  filter:blur(0); /* OR transform:translate(0) */
}
<div class="fixed"></div>

Of course, the trick is to apply a null filter or transform to avoid any visual change.


For sticky element you need to consider the overflow property to disable the effect. Here it is a bit tricky as it will depend on the HTML but in most of the case you need to apply overflow with a value other than visible on the parent element (Full details here: What are `scrolling boxes`?)

Here is a basic example:

.fixed {
  position:sticky;
  top:0;
  background:red;
  height:56px;
}

body {
  margin:0;
  height:220vh;
  overflow:auto;
}
html {
  overflow-y:scroll;
}
<div class="fixed"></div>

The above example is a bit trick because we also face the overflow propagation from body to html that's why I need to explicitely set overflow for HTML too or it won't work.

Here is another example with a container other than the body:

.sticky {
  position: sticky;
  top: 0;
  background: red;
  height: 56px;
}

.container {
  height: 220vh;
  overflow: auto;
}
<div class="container">
  <div class="sticky"></div>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415