Created
February 5, 2026 22:34
-
-
Save santaklouse/0cb2d2a2b973038ddc68838b3140afd6 to your computer and use it in GitHub Desktop.
Paste into devtools and element selector appears where you could click and you get screenshot of the scrolled content
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (() => { | |
| async function loadScript(filePath, cacheBuster = `?bust=${new Date().getTime()}`) { | |
| return await new Promise((resolve, reject) => { | |
| const scriptTag = document.createElement('script'); | |
| scriptTag.onload = () => console.log('loaded'); | |
| scriptTag.type = 'text/javascript'; | |
| scriptTag.src = `${filePath}${cacheBuster}`; | |
| scriptTag.onload = resolve; | |
| scriptTag.onerror = reject; | |
| document.querySelector('head').appendChild(scriptTag); | |
| }); | |
| } | |
| if (window.__hoverInspectorCleanup) return window.__hoverInspectorCleanup(); | |
| const makeScreenshot = async (elem) => { | |
| const SCROLL_SELECTOR = "body"; // <-- поменяй на нужный контейнер, например ".main-scroll" | |
| const scrollEl = elem || (SCROLL_SELECTOR === "body" | |
| ? document.documentElement | |
| : document.querySelector(SCROLL_SELECTOR) | |
| ); | |
| if (!scrollEl) { | |
| throw new Error("Scroll element not found: " + SCROLL_SELECTOR); | |
| } | |
| if (!window.html2canvas) { | |
| await loadScript("https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"); | |
| } | |
| // Временно убираем oklch, чтобы html2canvas не падал | |
| const override = document.createElement("style"); | |
| override.id = "__html2canvas_safe_colors__"; | |
| override.textContent = ` | |
| * { | |
| color: rgb(0,0,0) !important; | |
| background-color: transparent !important; | |
| border-color: transparent !important; | |
| outline-color: transparent !important; | |
| box-shadow: none !important; | |
| text-shadow: none !important; | |
| caret-color: rgb(0,0,0) !important; | |
| -webkit-text-fill-color: rgb(0,0,0) !important; | |
| } | |
| `; | |
| document.head.appendChild(override); | |
| const totalHeight = scrollEl.scrollHeight; | |
| const viewportHeight = scrollEl.clientHeight; | |
| const totalWidth = scrollEl.scrollWidth; | |
| const viewportWidth = scrollEl.clientWidth; | |
| const shots = []; | |
| const originalScrollTop = scrollEl.scrollTop; | |
| for (let y = 0; y < totalHeight; y += viewportHeight) { | |
| scrollEl.scrollTop = y; | |
| await new Promise(r => setTimeout(r, 120)); // дать странице перерисоваться | |
| const canvas = await html2canvas(scrollEl, { | |
| useCORS: true, | |
| allowTaint: true, | |
| scale: window.devicePixelRatio || 1, | |
| width: viewportWidth, | |
| height: viewportHeight, | |
| }); | |
| shots.push({ canvas, y }); | |
| } | |
| // Собираем общий холст | |
| const finalCanvas = document.createElement("canvas"); | |
| const scale = window.devicePixelRatio || 1; | |
| finalCanvas.width = totalWidth * scale; | |
| finalCanvas.height = totalHeight * scale; | |
| const ctx = finalCanvas.getContext("2d"); | |
| for (const shot of shots) { | |
| ctx.drawImage(shot.canvas, 0, shot.y * scale); | |
| } | |
| scrollEl.scrollTop = originalScrollTop; | |
| override.remove(); | |
| const link = document.createElement("a"); | |
| link.download = `screenshot-full-${Date.now()}.png`; | |
| link.href = finalCanvas.toDataURL("image/png"); | |
| link.click(); | |
| } | |
| const label = document.createElement('div'); | |
| label.style.cssText = ` | |
| position: fixed; z-index: 2147483647; | |
| padding: 2px 6px; font: 11px/1.3 monospace; | |
| background: rgba(0,0,0,.75); color: #fff; border-radius: 3px; | |
| pointer-events: none; white-space: nowrap; | |
| transform: translate(-1px, -100%); margin-top: -1px; | |
| border-width: 1px 1px medium; | |
| border-style: solid solid none; | |
| border-color: rgb(255, 106, 0) rgb(255, 106, 0) currentcolor; | |
| border-image: none; | |
| padding: 10px; | |
| border-bottom-left-radius: 0; | |
| border-bottom-right-radius: 0; | |
| `; | |
| document.body.appendChild(label); | |
| const style = document.createElement('style'); | |
| style.textContent = `.__hover_inspect { outline: 1px solid #ff6a00 !important; }`; | |
| document.head.appendChild(style); | |
| let last; | |
| const getXPath = (el) => { | |
| if (el.id) return `//*[@id="${el.id}"]`; | |
| const parts = []; | |
| while (el && el.nodeType === 1) { | |
| let i = 1, sib = el.previousSibling; | |
| while (sib) { if (sib.nodeType === 1 && sib.tagName === el.tagName) i++; sib = sib.previousSibling; } | |
| parts.unshift(`${el.tagName.toLowerCase()}[${i}]`); | |
| el = el.parentNode; | |
| } | |
| return '/' + parts.join('/'); | |
| }; | |
| const onMove = (e) => { | |
| const el = e.target; | |
| if (last && last !== el) last.classList.remove('__hover_inspect'); | |
| if (el && el.nodeType === 1) { | |
| el.classList.add('__hover_inspect'); | |
| const cls = el.className && typeof el.className === 'string' | |
| ? '.' + el.className.trim().split(/\s+/).join('.') | |
| : ''; | |
| label.textContent = (cls ? cls : getXPath(el)).replace('.__hover_inspect', ''); | |
| const r = el.getBoundingClientRect(); | |
| label.style.left = Math.max(0, Math.min(r.left, window.innerWidth - label.offsetWidth - 4)) + 'px'; | |
| label.style.top = Math.max(0, r.top) + 'px'; | |
| last = el; | |
| } | |
| }; | |
| document.addEventListener('mouseover', onMove, true); | |
| document.body.addEventListener('click', function(event) { | |
| if (event.target.matches('.__hover_inspect')) { | |
| console.log('element clicked:', event.target.classList); | |
| makeScreenshot(event.target); | |
| } | |
| }); | |
| window.__hoverInspectorCleanup = () => { | |
| document.removeEventListener('mouseover', onMove, true); | |
| if (last) last.classList.remove('__hover_inspect'); | |
| label.remove(); style.remove(); | |
| delete window.__hoverInspectorCleanup; | |
| }; | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment