Reduced repaints for header and sidebars

This commit is contained in:
squidfunk 2017-03-03 21:57:15 +01:00 committed by Martin Donath
parent 0fa899fe0b
commit d12f17e520
13 changed files with 64 additions and 27 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -32,7 +32,7 @@
<script src="{{ base_url }}/assets/javascripts/modernizr-56ade86843.js"></script>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-2193a9b229.css">
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-248e5b02e7.css">
{% if config.extra.palette %}
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-892b79c5c5.palette.css">
{% endif %}
@ -154,7 +154,7 @@
{% endblock %}
</div>
{% block scripts %}
<script src="{{ base_url }}/assets/javascripts/application-30ac6a1727.js"></script>
<script src="{{ base_url }}/assets/javascripts/application-3873210def.js"></script>
<script>app.initialize({url:{base:"{{ base_url }}"}})</script>
{% for path in extra_javascript %}
<script src="{{ path }}"></script>

View File

@ -1,4 +1,4 @@
<header class="md-header">
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">

View File

@ -38,7 +38,7 @@ theme_dir: material
# Options
extra:
feature:
tabs: true
tabs: false
palette:
primary: indigo
accent: indigo

View File

@ -87,7 +87,9 @@ function initialize(config) { // eslint-disable-line func-style
new Material.Event.MatchMedia("(min-width: 1220px)",
new Material.Event.Listener(window, [
"scroll", "resize", "orientationchange"
], new Material.Header.Shadow("[data-md-component=container]")))
], new Material.Header.Shadow(
"[data-md-component=container]",
"[data-md-component=header]")))
/* Component: tabs visibility toggle */
if (document.querySelector("[data-md-component=tabs]"))
@ -99,18 +101,24 @@ function initialize(config) { // eslint-disable-line func-style
new Material.Event.MatchMedia("(min-width: 1220px)",
new Material.Event.Listener(window, [
"scroll", "resize", "orientationchange"
], new Material.Sidebar.Position("[data-md-component=navigation]")))
], new Material.Sidebar.Position(
"[data-md-component=navigation]",
"[data-md-component=header]")))
/* Component: sidebar with table of contents - register two separate
listeners, as the offset at the top might change */
new Material.Event.MatchMedia("(min-width: 960px) and (max-width: 1219px)",
new Material.Event.Listener(window, [
"scroll", "resize", "orientationchange"
], new Material.Sidebar.Position("[data-md-component=toc]")))
], new Material.Sidebar.Position(
"[data-md-component=toc]",
"[data-md-component=header]")))
new Material.Event.MatchMedia("(min-width: 1220px)",
new Material.Event.Listener(window, [
"scroll", "resize", "orientationchange"
], new Material.Sidebar.Position("[data-md-component=toc]")))
], new Material.Sidebar.Position(
"[data-md-component=toc]",
"[data-md-component=header]")))
/* Component: link blurring for table of contents */
new Material.Event.MatchMedia("(min-width: 960px)",

View File

@ -37,21 +37,24 @@ export default class Shadow {
* @property {boolean} active_ - Header shadow state
*
* @param {(string|HTMLElement)} el - Selector or HTML element
* @param {(string|HTMLElement)} header - Selector or HTML element
*/
constructor(el) {
const ref = (typeof el === "string")
constructor(el, header) {
let ref = (typeof el === "string")
? document.querySelector(el)
: el
if (!(ref instanceof HTMLElement) ||
!(ref.parentNode instanceof HTMLElement))
throw new ReferenceError
/* Grab parent and header */
this.el_ = ref.parentNode
if (!(this.el_.parentNode instanceof HTMLElement) ||
!(this.el_.parentNode.previousElementSibling instanceof HTMLElement))
/* Retrieve header */
ref = (typeof header === "string")
? document.querySelector(header)
: header
if (!(ref instanceof HTMLElement))
throw new ReferenceError
this.header_ = this.el_.parentNode.previousElementSibling
this.header_ = ref
/* Initialize height and state */
this.height_ = 0

View File

@ -33,22 +33,32 @@ export default class Position {
*
* @property {HTMLElement} el_ - Sidebar
* @property {HTMLElement} parent_ - Sidebar container
* @property {HTMLElement} header_ - Header
* @property {number} height_ - Current sidebar height
* @property {number} offset_ - Current page y-offset
*
* @param {(string|HTMLElement)} el - Selector or HTML element
* @param {(string|HTMLElement)} header - Selector or HTML element
*/
constructor(el) {
const ref = (typeof el === "string")
constructor(el, header) {
let ref = (typeof el === "string")
? document.querySelector(el)
: el
if (!(ref instanceof HTMLElement) ||
!(ref.parentNode instanceof HTMLElement))
throw new ReferenceError
this.el_ = ref
/* Initialize parent container and current height */
this.parent_ = ref.parentNode
/* Retrieve header */
ref = (typeof header === "string")
? document.querySelector(header)
: header
if (!(ref instanceof HTMLElement))
throw new ReferenceError
this.header_ = ref
/* Initialize current height */
this.height_ = 0
}
@ -56,7 +66,13 @@ export default class Position {
* Initialize sidebar state
*/
setup() {
this.offset_ = this.el_.offsetTop - 56
const top = Array.prototype.reduce.call(
this.parent_.children, (offset, child) => {
return Math.max(offset, child.offsetTop)
}, 0)
/* Set lock offset for element with largest top offset */
this.offset_ = top - this.header_.offsetHeight
this.update()
}
@ -68,15 +84,21 @@ export default class Position {
* by the height of the fixed header (56px). Depending on the page y-offset,
* the top offset of the sidebar must be taken into account, as well as the
* case where the window is scrolled beyond the sidebar container.
*
* @param {Event?} ev - Event
*/
update() {
update(ev) {
const offset = window.pageYOffset
const visible = window.innerHeight
/* Update offset, in case window is resized */
if (ev && ev.type === "resize")
this.setup()
/* Set bounds of sidebar container - must be calculated on every run, as
the height of the content might change due to loading images etc. */
const bounds = {
top: 56,
top: this.header_.offsetHeight,
bottom: this.parent_.offsetTop + this.parent_.offsetHeight
}

View File

@ -37,6 +37,8 @@
background-color: $md-color-primary;
color: $md-color-white;
z-index: 1;
// Hack: putting the header on the GPU avoids unnecessary repaints
backface-visibility: hidden;
// Always show shadow, in case JavaScript is not available
.no-js & {

View File

@ -88,6 +88,8 @@
// Align SVG, do not scale, as this will incur strange formatting bugs
// in Internet Explorer and Edge
svg {
width: 2.4rem;
height: 2.4rem;
margin-top: 1.2rem;
margin-left: 1.2rem;
}

View File

@ -21,7 +21,7 @@
-->
<!-- Application header -->
<header class="md-header">
<header class="md-header" data-md-component="header">
<!-- Top-level navigation -->
<nav class="md-header-nav md-grid">