diff --git a/lighthouse-core/gather/gatherers/full-page-screenshot.js b/lighthouse-core/gather/gatherers/full-page-screenshot.js index 04cf1db6e7fe..d52112306b17 100644 --- a/lighthouse-core/gather/gatherers/full-page-screenshot.js +++ b/lighthouse-core/gather/gatherers/full-page-screenshot.js @@ -76,9 +76,9 @@ class FullPageScreenshot extends Gatherer { const data = 'data:image/jpeg;base64,' + result.data; return { + data, width, height, - data, }; } diff --git a/lighthouse-core/report/html/renderer/element-screenshot-renderer.js b/lighthouse-core/report/html/renderer/element-screenshot-renderer.js index e2f04d3d47dd..5da29fb3a41c 100644 --- a/lighthouse-core/report/html/renderer/element-screenshot-renderer.js +++ b/lighthouse-core/report/html/renderer/element-screenshot-renderer.js @@ -17,6 +17,14 @@ /** @typedef {LH.Artifacts.Rect} Rect */ /** @typedef {{width: number, height: number}} Size */ +/** + * @typedef InstallOverlayFeatureParams + * @property {DOM} dom + * @property {Element} el + * @property {ParentNode} templateContext + * @property {LH.Artifacts.FullPageScreenshot} fullPageScreenshot + */ + /** * @param {LH.Artifacts.FullPageScreenshot['screenshot']} screenshot * @param {LH.Artifacts.Rect} rect @@ -118,40 +126,29 @@ class ElementScreenshotRenderer { } /** - * Called externally and must be injected to the report in order to use this renderer. - * @param {DOM} dom + * Called by report renderer. Defines a css variable used by any element screenshots + * in the provided report element. + * Allows for multiple Lighthouse reports to be rendered on the page, each with their + * own full page screenshot. + * @param {HTMLElement} el * @param {LH.Artifacts.FullPageScreenshot['screenshot']} screenshot */ - static createBackgroundImageStyle(dom, screenshot) { - const styleEl = dom.createElement('style'); - styleEl.id = 'full-page-screenshot-style'; - styleEl.textContent = ` - .lh-element-screenshot__image { - background-image: url(${screenshot.data}) - }`; - return styleEl; + static installFullPageScreenshot(el, screenshot) { + el.style.setProperty('--element-screenshot-url', `url(${screenshot.data})`); } /** * Installs the lightbox elements and wires up click listeners to all .lh-element-screenshot elements. - * @param {DOM} dom - * @param {ParentNode} templateContext - * @param {LH.Artifacts.FullPageScreenshot} fullPageScreenshot + * @param {InstallOverlayFeatureParams} _ */ - static installOverlayFeature(dom, templateContext, fullPageScreenshot) { - const rootEl = dom.find('.lh-root', dom.document()); - if (!rootEl) { - console.warn('No lh-root. Overlay install failed.'); // eslint-disable-line no-console - return; - } - + static installOverlayFeature({dom, el, templateContext, fullPageScreenshot}) { const screenshotOverlayClass = 'lh-screenshot-overlay--enabled'; // Don't install the feature more than once. - if (rootEl.classList.contains(screenshotOverlayClass)) return; - rootEl.classList.add(screenshotOverlayClass); + if (el.classList.contains(screenshotOverlayClass)) return; + el.classList.add(screenshotOverlayClass); - // Add a single listener to the root element to handle all clicks within (event delegation). - rootEl.addEventListener('click', e => { + // Add a single listener to the provided element to handle all clicks within (event delegation). + el.addEventListener('click', e => { const target = /** @type {?HTMLElement} */ (e.target); if (!target) return; // Only activate the overlay for clicks on the screenshot *preview* of an element, not the full-size too. @@ -159,7 +156,7 @@ class ElementScreenshotRenderer { if (!el) return; const overlay = dom.createElement('div', 'lh-element-screenshot__overlay'); - rootEl.append(overlay); + el.append(overlay); // The newly-added overlay has the dimensions we need. const maxLightboxSize = { diff --git a/lighthouse-core/report/html/renderer/report-renderer.js b/lighthouse-core/report/html/renderer/report-renderer.js index 3f608125e607..a45b0cc2f8f0 100644 --- a/lighthouse-core/report/html/renderer/report-renderer.js +++ b/lighthouse-core/report/html/renderer/report-renderer.js @@ -208,9 +208,6 @@ class ReportRenderer { const detailsRenderer = new DetailsRenderer(this._dom, { fullPageScreenshot, }); - const fullPageScreenshotStyleEl = fullPageScreenshot && - ElementScreenshotRenderer.createBackgroundImageStyle( - this._dom, fullPageScreenshot.screenshot); const categoryRenderer = new CategoryRenderer(this._dom, detailsRenderer); categoryRenderer.setTemplateContext(this._templateContext); @@ -269,9 +266,13 @@ class ReportRenderer { reportFragment.appendChild(reportContainer); reportContainer.appendChild(headerContainer); reportContainer.appendChild(reportSection); - fullPageScreenshotStyleEl && reportContainer.appendChild(fullPageScreenshotStyleEl); reportSection.appendChild(this._renderReportFooter(report)); + if (fullPageScreenshot) { + ElementScreenshotRenderer.installFullPageScreenshot( + reportContainer, fullPageScreenshot.screenshot); + } + return reportFragment; } } diff --git a/lighthouse-core/report/html/renderer/report-ui-features.js b/lighthouse-core/report/html/renderer/report-ui-features.js index db281706c667..2e70d31320f0 100644 --- a/lighthouse-core/report/html/renderer/report-ui-features.js +++ b/lighthouse-core/report/html/renderer/report-ui-features.js @@ -91,7 +91,7 @@ class ReportUIFeatures { this._setupMediaQueryListeners(); this._dropDown.setup(this.onDropDownMenuClick); this._setupThirdPartyFilter(); - this._setupElementScreenshotOverlay(); + this._setupElementScreenshotOverlay(this._dom.find('.lh-container', this._document)); this._setUpCollapseDetailsAfterPrinting(); this._resetUIState(); this._document.addEventListener('keyup', this.onKeyUp); @@ -307,7 +307,10 @@ class ReportUIFeatures { }); } - _setupElementScreenshotOverlay() { + /** + * @param {Element} el + */ + _setupElementScreenshotOverlay(el) { const fullPageScreenshot = this.json.audits['full-page-screenshot'] && this.json.audits['full-page-screenshot'].details && @@ -315,8 +318,12 @@ class ReportUIFeatures { this.json.audits['full-page-screenshot'].details; if (!fullPageScreenshot) return; - ElementScreenshotRenderer.installOverlayFeature( - this._dom, this._templateContext, fullPageScreenshot); + ElementScreenshotRenderer.installOverlayFeature({ + dom: this._dom, + el, + templateContext: this._templateContext, + fullPageScreenshot, + }); } /** diff --git a/lighthouse-core/report/html/report-styles.css b/lighthouse-core/report/html/report-styles.css index 2093983398ba..1d29613c8696 100644 --- a/lighthouse-core/report/html/report-styles.css +++ b/lighthouse-core/report/html/report-styles.css @@ -1537,6 +1537,8 @@ overflow: hidden; } .lh-element-screenshot__image { + /* Set by ElementScreenshotRenderer.installFullPageScreenshotCssVariable */ + background-image: var(--element-screenshot-url); outline: 2px solid #777; background-color: white; background-repeat: no-repeat;