Skip to content

Commit

Permalink
report: avoid paint storms on scrolly header (#5207)
Browse files Browse the repository at this point in the history
* and shrink the header height by 41px
  • Loading branch information
paulirish authored May 21, 2018
1 parent 5d366d5 commit 804e9b8
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 60 deletions.
74 changes: 34 additions & 40 deletions lighthouse-core/report/html/renderer/report-ui-features.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ class ReportUIFeatures {
this.headerBackground; // eslint-disable-line no-unused-expressions
/** @type {HTMLElement} */
this.lighthouseIcon; // eslint-disable-line no-unused-expressions
/** @type {HTMLElement} */
this.scoresShadowWrapper; // eslint-disable-line no-unused-expressions
/** @type {HTMLElement} */
/** @type {!HTMLElement} */
this.scoresWrapperBg; // eslint-disable-line no-unused-expressions
/** @type {!HTMLElement} */
this.productInfo; // eslint-disable-line no-unused-expressions
/** @type {HTMLElement} */
this.toolbar; // eslint-disable-line no-unused-expressions
Expand Down Expand Up @@ -126,7 +126,7 @@ class ReportUIFeatures {
this.headerSticky = this._dom.find('.lh-header-sticky', this._document);
this.headerBackground = this._dom.find('.lh-header-bg', this._document);
this.lighthouseIcon = this._dom.find('.lh-lighthouse', this._document);
this.scoresShadowWrapper = this._dom.find('.lh-scores-wrapper__shadow', this._document);
this.scoresWrapperBg = this._dom.find('.lh-scores-wrapper__background', this._document);
this.productInfo = this._dom.find('.lh-product-info', this._document);
this.toolbar = this._dom.find('.lh-toolbar', this._document);
this.toolbarMetadata = this._dom.find('.lh-toolbar__metadata', this._document);
Expand Down Expand Up @@ -210,49 +210,43 @@ class ReportUIFeatures {

animateHeader() {
const collapsedHeaderHeight = 50;
const animateScrollPercentage = Math.min(1, this.latestKnownScrollY /
(this.headerHeight - collapsedHeaderHeight));
const headerTransitionHeightDiff = this.headerHeight - collapsedHeaderHeight +
this.headerOverlap;

this.headerSticky.style.transform = `translateY(${headerTransitionHeightDiff *
animateScrollPercentage *
-1}px)`;
this.headerBackground.style.transform = `translateY(${animateScrollPercentage *
this.headerOverlap}px)`;
const heightDiff = this.headerHeight - collapsedHeaderHeight + this.headerOverlap;
const scrollPct = Math.min(1,
this.latestKnownScrollY / (this.headerHeight - collapsedHeaderHeight));

const scoresContainer = /** @type {HTMLElement} */ (this.scoresWrapperBg.parentElement);

this.headerSticky.style.transform = `translateY(${heightDiff * scrollPct * -1}px)`;
this.headerBackground.style.transform = `translateY(${scrollPct * this.headerOverlap}px)`;
this.lighthouseIcon.style.transform =
`translate3d(calc(var(--report-content-width) / 2),` +
` calc(-100% - ${animateScrollPercentage * this.headerOverlap * -1}px), 0) scale(${1 -
animateScrollPercentage})`;
this.lighthouseIcon.style.opacity = Math.max(0, 1 - animateScrollPercentage).toString();
this.scoresShadowWrapper.style.opacity = (1 - animateScrollPercentage).toString();
const scoresContainer = /** @type {HTMLElement} */ (this.scoresShadowWrapper.parentElement);
scoresContainer.style.borderRadius = (1 - animateScrollPercentage) * 8 + 'px';
scoresContainer.style.boxShadow =
`0 4px 2px -2px rgba(0, 0, 0, ${animateScrollPercentage * 0.2})`;
` calc(-100% - ${scrollPct * this.headerOverlap * -1}px), 0) scale(${1 - scrollPct})`;
this.lighthouseIcon.style.opacity = Math.max(0, 1 - scrollPct).toString();

// Switch up the score background & shadows
this.scoresWrapperBg.style.opacity = (1 - scrollPct).toString();
this.scoresWrapperBg.style.transform = `scaleY(${1 - scrollPct * 0.2})`;
const scoreShadow = this._dom.find('.lh-scores-wrapper__shadow', scoresContainer);
scoreShadow.style.opacity = scrollPct.toString();
scoreShadow.style.transform = `scaleY(${1 - scrollPct * 0.2})`;

// Fade & move the scorescale
const scoreScalePositionDelta = 32;
const scoreScale = this._dom.find('.lh-scorescale', scoresContainer);
scoreScale.style.opacity = `${1 - animateScrollPercentage}`;
const scoreHeader = this._dom.find('.lh-scores-header', scoresContainer);
const delta = 32 * animateScrollPercentage;
scoreHeader.style.paddingBottom = `${32 - delta}px`;
scoresContainer.style.marginBottom = `${delta}px`;
this.toolbar.style.transform = `translateY(${headerTransitionHeightDiff *
animateScrollPercentage}px)`;
this.exportButton.style.transform = `scale(${1 - 0.2 * animateScrollPercentage})`;
// fix stacking context
scoreScale.style.opacity = `${1 - scrollPct}`;
scoreScale.style.transform = `translateY(${scrollPct * -scoreScalePositionDelta}px)`;

// Move the toolbar & export
this.toolbar.style.transform = `translateY(${heightDiff * scrollPct}px)`;
const exportParent = this.exportButton.parentElement;
if (exportParent) {
exportParent.style.transform = `translateY(${headerTransitionHeightDiff *
animateScrollPercentage}px)`;
exportParent.style.transform = `translateY(${heightDiff * scrollPct}px)`;
}
// start showing the productinfo when we are at the 50% mark of our animation
const opacity = animateScrollPercentage < 0.5 ? 0 : (animateScrollPercentage - 0.5) * 2;
this.exportButton.style.transform = `scale(${1 - 0.2 * scrollPct})`;
// Start showing the productinfo when we are at the 50% mark of our animation
const opacity = scrollPct < 0.5 ? 0 : (scrollPct - 0.5) * 2;
this.productInfo.style.opacity = this.toolbarMetadata.style.opacity = opacity.toString();
this.env.style.transform = `translateY(${Math.max(
0,
headerTransitionHeightDiff * animateScrollPercentage - 6
)}px)`;

this.env.style.transform = `translateY(${Math.max(0, heightDiff * scrollPct - 6)}px)`;

this.isAnimatingHeader = false;
}
Expand Down
7 changes: 4 additions & 3 deletions lighthouse-core/report/html/report-styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
--display-value-gray: hsl(216, 5%, 39%);
--report-width: calc(60 * var(--body-font-size));
--report-content-width: calc(var(--report-width));
--report-header-height: 202px;
--report-header-height: 161px;
--report-header-color: #202124;
--navitem-font-size: var(--body-font-size);
--navitem-line-height: var(--body-line-height);
Expand Down Expand Up @@ -656,7 +656,7 @@
justify-content: center;
overflow-x: hidden;
position: relative;
padding-bottom: calc(var(--section-indent) * 2);
padding: var(--section-indent) calc(var(--section-indent) / 2) calc(var(--section-indent) * 2);
}
.lh-scores-header__solo {
padding: 0;
Expand All @@ -665,9 +665,10 @@

.lh-scorescale {
color: var(--medium-75-gray);
padding: 0 var(--section-indent) 0 0;
padding: 0 calc(var(--section-indent) * 1.5) 0;
text-align: right;
transform-origin: bottom right;
will-change: opacity; /* opacity is changed on scroll */
}

.lh-scorescale-range {
Expand Down
72 changes: 55 additions & 17 deletions lighthouse-core/report/html/templates.html
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@
height: var(--report-header-height);
max-width: 100%; /* support text-overflow on url */
position: relative;
padding-top: var(--section-indent);
}
.lh-metadata {
flex: 1 1 0;
padding-right: calc(var(--default-padding) / 2);
padding: calc(var(--section-padding) / 2);
padding-left: var(--section-indent);
line-height: 20px;
color: var(--report-header-color);
z-index: 1;
Expand All @@ -149,22 +149,27 @@
margin-top: -30px;
transform: translateZ(1px);
}
.lh-scores-wrapper__background,
.lh-scores-wrapper__shadow {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: white;
box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.1);
opacity: 1;
border-radius: 8px;
will-change: opacity;
will-change: opacity, transform;
transform-origin: top;
}
.lh-scores-wrapper__shadow {
opacity: 0;
border-radius: 4px;
box-shadow: rgba(0, 0, 0, 0.2) 0px 4px 2px -2px;
}
.lh-scores-container {
background: #fff;
border-bottom: 1px solid #ebebeb;
border-radius: 8px;
padding: var(--section-indent) calc(var(--section-indent) / 2) calc(var(--section-indent) / 2);
padding-bottom: calc(var(--section-indent) / 2);
position: relative;
width: 100%;
}
Expand All @@ -178,6 +183,7 @@
position: absolute;
top: 50%;
transform: translateY(-50%);
will-change: opacity;
}
.lh-product-info__icon {
height: 20px;
Expand All @@ -191,8 +197,7 @@
will-change: transform;
}
.lh-toolbar__metadata {
left: 50%;
transform: translate(-50%, -50%);
left: 25%;
}
.lh-toolbar__url {
color: currentColor;
Expand Down Expand Up @@ -285,9 +290,8 @@
position: absolute;
width: 100%;
background-color: var(--header-bg-color);
border-top: 1px solid var(--report-secondary-border-color);
border-bottom: 1px solid var(--report-secondary-border-color);
font-size: 12px;
box-shadow: inset var(--report-border-color) 0px -1px 0px 1px;
}
.lh-env__items {
margin: var(--default-padding) 0 0 0;
Expand All @@ -312,27 +316,60 @@
right: 0;
left: initial;
}
.lh-header {
padding: 0 var(--default-padding);
margin-left: 0;
}
}
@media print {
.lh-header {
position: static;
margin-left: 0;
}
}
/*
TODO: Enable animating the clouds
.lh-lighthouse__clouds {
animation: panacross 30s linear infinite;
animation-play-state: paused;
}
@keyframes panacross {
0% { transform: translateX(0px); }
77% { transform: translateX(-680px); }
77.0001% { transform: translateX(195px); }
100% { transform: translateX(0px); }
} */
</style>
<div class="lh-header-bg"></div>
<div class="lh-lighthouse"><svg width="217" height="189" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path id="a" d="M0 0h284v202H0z"/><linearGradient x1="0%" y1="50%" x2="93.17%" y2="50%" id="c"><stop stop-color="#F1F3F4" offset="0%"/><stop stop-color="#FFF" offset="100%"/></linearGradient></defs><g transform="translate(-56 -13)" fill="none" fill-rule="evenodd"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><g mask="url(#b)"><g transform="translate(56 70)"><path fill="#EC5548" d="M95 31h24v2H95z"/><path fill="#FBC21B" d="M98 33h18v11H98z"/><path fill="#EC5548" d="M95 43h24v7H95z"/><path fill="#FFF" d="M97.63 50h19.74L120 97H95z"/><path d="M107 22a10 10 0 0 1 10 10v1H97v-1a10 10 0 0 1 10-10zM96.77 66.23l20.97-10.7.63 11.87-22.28 11.87zM95 94.8L119.1 82l.9 14H95z" fill="#EC5548"/><path d="M0 132a177.07 177.07 0 0 1 108.5-37c40.78 0 78.38 13.78 108.5 37H0z" fill="#E8EAED"/><rect fill="#FEF0C8" x="98" y="33" width="10" height="10" rx="5"/><path fill="url(#c)" d="M7 0l91 33.18v10.05L7 77z"/></g></g><g mask="url(#b)" fill="#FFF"><g transform="translate(96 86)"><circle cx="87.5" cy=".5" r="1"/><circle cx="86" cy="20" r="1"/><circle cx="96" cy="40" r="1"/><circle cx="27" cy="68" r="1"/><circle cx="15" cy="44" r="1"/><circle cx="127" cy="64" r="1"/><circle cx="109.5" cy="44.5" r="1"/><circle cx="14.5" cy="54.5" r="1"/><circle cx="8.5" cy="57.5" r="1"/><circle cx=".5" cy="78.5" r="1"/><circle cx="27.5" cy="39.5" r="1"/><circle cx="134.5" cy="41.5" r="1"/><circle cx="97.5" cy="65.5" r="1"/><circle cx="161.5" cy="69.5" r="1"/></g></g><g mask="url(#b)" fill="#FFF"><path d="M101.2 34H70.21A7.42 7.42 0 0 1 69 29.91a7.31 7.31 0 0 1 8.54-7.26v-.11c0-5.27 4.2-9.54 9.39-9.54a9.44 9.44 0 0 1 9.24 7.83 7.24 7.24 0 0 1 7.83 7.35 7.4 7.4 0 0 1-2.8 5.82zM193.53 54h-17.9a4.3 4.3 0 0 1-.63-2.25 4.2 4.2 0 0 1 4.88-4.18v-.07c0-3.04 2.4-5.5 5.36-5.5a5.4 5.4 0 0 1 5.28 4.51l.33-.01a4.2 4.2 0 0 1 4.15 4.25c0 1.3-.57 2.47-1.47 3.25zM219.01 116h-24.16a5.1 5.1 0 0 1-.85-2.81c0-2.94 2.5-5.31 5.6-5.31.33 0 .67.02.99.08v-.08c0-3.8 3.24-6.88 7.24-6.88a7.15 7.15 0 0 1 7.13 5.64l.44-.02c3.1 0 5.6 2.38 5.6 5.32a5.2 5.2 0 0 1-1.99 4.06z"/></g></g></svg></div>
<div class="lh-lighthouse">
<svg width="217" height="148" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<mask id="a" x="-56" y="-54" width="284" height="202" maskUnits="userSpaceOnUse">
<path d="M-56-54h284v202H-56z" fill="#fff"/>
</mask>
<linearGradient id="b" x1="-525.16" y1="560.08" x2="-524.23" y2="560.08" gradientTransform="matrix(91 0 0 -77 47797 43181)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#f1f3f4"/>
<stop offset="1" stop-color="#fff"/>
</linearGradient>
</defs>
<g mask="url(#a)">
<path d="M95 47h24v2H95z" fill="#ec5548"/>
<path d="M98 49h18v11H98z" fill="#fbc21b"/>
<path d="M95 59h24v7H95z" fill="#ec5548"/>
<path d="M97.63 66h19.74l2.63 47H95z" fill="#fff"/>
<path d="M107 38a10 10 0 0 1 10 10v1H97v-1a10 10 0 0 1 10-10zM96.77 82.23l21-10.7.63 11.87-22.31 11.87zM95 110.8L119.1 98l.9 14H95z" fill="#ec5548"/>
<path d="M0 148a177.58 177.58 0 0 1 217 0z" fill="#e8eaed"/>
<path d="M103 49a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5z" fill="#fef0c8"/>
<path d="M7 16l91 33.18v10L7 93z" fill="url(#b)"/>
</g>
<g mask="url(#a)" class="lh-lighthouse__clouds">
<path d="M60 .19A9.77 9.77 0 0 1 61.93 0a9.44 9.44 0 0 1 9.24 7.83A7.24 7.24 0 0 1 79 14.45v.73A7.37 7.37 0 0 1 76.2 21h-31a7.44 7.44 0 0 1-1.2-4.09 7.31 7.31 0 0 1 7.26-7.36 6.84 6.84 0 0 1 1.28.1v-.11A9.51 9.51 0 0 1 60 .19m79.78 22.31h-17.9a4.37 4.37 0 0 1-.63-2.25 4.2 4.2 0 0 1 4.16-4.25 4.37 4.37 0 0 1 .72.06V16a5.35 5.35 0 0 1 10.64-1h.33a4.2 4.2 0 0 1 4.15 4.25 4.29 4.29 0 0 1-1.47 3.25zM163 62h-24.15a5.1 5.1 0 0 1-.85-2.81 5.65 5.65 0 0 1 6.59-5.19v-.08a7.07 7.07 0 0 1 7.24-6.92 7.15 7.15 0 0 1 7.17 5.64h.44a5.46 5.46 0 0 1 5.6 5.32A5.19 5.19 0 0 1 163 62z" fill="#fff"/>
</g>
</svg>
</div>

<div class="lh-header-container">
<div class="lh-header">
<div class="lh-metadata">
<div class="lh-metadata__results"><a href="" class="lh-metadata__url" target="_blank" rel="noopener"></a></div>
<div class="lh-config">
<span class="lh-config__timestamp"></span> &bullet;
<span class="lh-config__timestamp"></span>
<details class="lh-config__settings-toggle">
<summary>
<span>Runtime settings</span>
Expand All @@ -359,6 +396,7 @@

<div class="lh-scores-wrapper">
<div class="lh-scores-container">
<div class="lh-scores-wrapper__background"></div>
<div class="lh-scores-wrapper__shadow"></div>
</div>
</div>
Expand Down

0 comments on commit 804e9b8

Please sign in to comment.