hiding-header
Advanced tools
+4
-8
@@ -36,12 +36,8 @@ <!DOCTYPE html> | ||
| position: relative; | ||
| --hidingHeader-height: auto; | ||
| --hidingHeader-scrollCap: 0px; | ||
| --hidingHeader-topOffset: 0px; | ||
| --hidingHeader-height: 0px; | ||
| --hidingHeader-bounds-height: 0px; | ||
| z-index: 10; | ||
| height: calc( | ||
| var(--hidingHeader-scrollCap) + var(--hidingHeader-height) - | ||
| var(--hidingHeader-topOffset) | ||
| ); | ||
| height: var(--hidingHeader-bounds-height); | ||
| margin-bottom: calc( | ||
| var(--hidingHeader-topOffset) - var(--hidingHeader-scrollCap) | ||
| var(--hidingHeader-height) - var(--hidingHeader-bounds-height) | ||
| ); | ||
@@ -48,0 +44,0 @@ pointer-events: none; |
+30
-40
| export function hidingHeader(container) { | ||
| var DEFAULT_CONTENT_SELECTOR = '*'; | ||
| var DEFAULT_HEIGHT_PROPERTY_NAME = '--hidingHeader-height'; | ||
| var DEFAULT_SCROLL_CAP_PROPERTY_NAME = '--hidingHeader-scrollCap'; | ||
| var DEFAULT_TOP_OFFSET_PROPERTY_NAME = '--hidingHeader-topOffset'; | ||
| var DEFAULT_BOUNDS_HEIGHT_PROPERTY_NAME = '--hidingHeader-bounds-height'; | ||
| var contentSelector = DEFAULT_CONTENT_SELECTOR; | ||
| var heightPropertyName = DEFAULT_HEIGHT_PROPERTY_NAME; | ||
| var scrollCapPropertyName = DEFAULT_SCROLL_CAP_PROPERTY_NAME; | ||
| var topOffsetPropertyName = DEFAULT_TOP_OFFSET_PROPERTY_NAME; | ||
| var boundsHeightPropertyName = DEFAULT_BOUNDS_HEIGHT_PROPERTY_NAME; | ||
| var lastScrollTopPosition = 0; | ||
| var contentHeight = 0; | ||
| var lastScrollCap = 0; | ||
| var topOffset = 0; | ||
| var lastContentHeight = 0; | ||
| var paused = false; | ||
| var lastBoundsHeight = 0; | ||
| var content = container.querySelector(contentSelector); | ||
@@ -29,49 +26,42 @@ if (content === null) { | ||
| }; | ||
| var getTopOffset = function () { | ||
| var getGlobalTopOffset = function () { | ||
| return container.offsetTop; | ||
| }; | ||
| var getContainerOffset = function () { | ||
| return container.getBoundingClientRect().top; | ||
| var getRelativeTopOffset = function () { | ||
| var _a; | ||
| return getGlobalTopOffset() - (((_a = container.parentElement) === null || _a === void 0 ? void 0 : _a.offsetTop) || 0); | ||
| }; | ||
| var onScroll = function () { | ||
| var parentHeight = getParentHeight(); | ||
| var containerOffset = getContainerOffset(); | ||
| // Handle top offset | ||
| var currentTopOffset = getTopOffset(); | ||
| if (topOffset !== currentTopOffset) { | ||
| topOffset = currentTopOffset; | ||
| container.style.setProperty(topOffsetPropertyName, currentTopOffset + "px"); | ||
| } | ||
| var globalTopOffset = getGlobalTopOffset(); | ||
| // Handle content height | ||
| var currentContentHeight = getContentHeight(); | ||
| if (contentHeight !== currentContentHeight) { | ||
| contentHeight = currentContentHeight; | ||
| container.style.setProperty(heightPropertyName, contentHeight + "px"); | ||
| var contentHeight = getContentHeight(); | ||
| if (lastContentHeight !== contentHeight) { | ||
| lastContentHeight = contentHeight; | ||
| container.style.setProperty(heightPropertyName, lastContentHeight + "px"); | ||
| } | ||
| // Handle scroll cap | ||
| // Handle bounds height | ||
| var scrollTopPosition = window.scrollY; | ||
| var isScrollingDown = scrollTopPosition > lastScrollTopPosition; | ||
| if (!paused) { | ||
| // @TODO: fix offset variant on direction change | ||
| var scrollCap = Math.min(parentHeight - contentHeight, (function () { | ||
| var scrollCapBottomPosition = lastScrollTopPosition + | ||
| containerOffset + | ||
| lastScrollCap + | ||
| contentHeight; | ||
| var maxBoundsHeight = parentHeight - getRelativeTopOffset(); | ||
| var boundsHeight = Math.min(maxBoundsHeight, Math.max(contentHeight, (function () { | ||
| if (isScrollingDown) { | ||
| var newScrollCap = scrollTopPosition - contentHeight; | ||
| return scrollCapBottomPosition < scrollTopPosition | ||
| ? newScrollCap | ||
| : lastScrollCap; | ||
| var newBoundsHeight = scrollTopPosition - globalTopOffset; | ||
| if (lastBoundsHeight < newBoundsHeight) { | ||
| return newBoundsHeight; | ||
| } | ||
| return lastBoundsHeight; | ||
| } | ||
| else { | ||
| var newScrollCap = scrollTopPosition; | ||
| return newScrollCap < scrollCapBottomPosition - contentHeight | ||
| ? newScrollCap | ||
| : lastScrollCap; | ||
| var newBoundsHeight = scrollTopPosition - globalTopOffset + contentHeight; | ||
| if (lastBoundsHeight > newBoundsHeight) { | ||
| return newBoundsHeight; | ||
| } | ||
| return lastBoundsHeight; | ||
| } | ||
| })()); | ||
| if (scrollCap !== lastScrollCap) { | ||
| container.style.setProperty(scrollCapPropertyName, scrollCap + "px"); | ||
| lastScrollCap = scrollCap; | ||
| })())); | ||
| if (boundsHeight !== lastBoundsHeight) { | ||
| container.style.setProperty(boundsHeightPropertyName, boundsHeight + "px"); | ||
| lastBoundsHeight = boundsHeight; | ||
| } | ||
@@ -78,0 +68,0 @@ } |
+1
-1
| { | ||
| "name": "hiding-header", | ||
| "version": "0.0.4", | ||
| "version": "0.1.0", | ||
| "description": "Toggles header visibility on scroll.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
+4
-7
@@ -35,11 +35,8 @@ # Hiding Header [](https://www.npmjs.com/package/hiding-header) [](https://www.npmjs.com/package/hiding-header?activeTab=dependencies)  | ||
| position: relative; | ||
| --hidingHeader-height: auto; | ||
| --hidingHeader-scrollCap: 0px; | ||
| --hidingHeader-topOffset: 0px; | ||
| --hidingHeader-height: 0px; | ||
| --hidingHeader-bounds-height: 0px; | ||
| z-index: 10; | ||
| height: calc( | ||
| var(--hidingHeader-scrollCap) + var(--hidingHeader-height) - var(--hidingHeader-topOffset) | ||
| ); | ||
| height: var(--hidingHeader-bounds-height); | ||
| margin-bottom: calc( | ||
| var(--hidingHeader-topOffset) - var(--hidingHeader-scrollCap) | ||
| var(--hidingHeader-height) - var(--hidingHeader-bounds-height) | ||
| ); | ||
@@ -46,0 +43,0 @@ pointer-events: none; |
+43
-50
| export function hidingHeader(container: HTMLElement) { | ||
| const DEFAULT_CONTENT_SELECTOR = '*' | ||
| const DEFAULT_HEIGHT_PROPERTY_NAME = '--hidingHeader-height' | ||
| const DEFAULT_SCROLL_CAP_PROPERTY_NAME = '--hidingHeader-scrollCap' | ||
| const DEFAULT_TOP_OFFSET_PROPERTY_NAME = '--hidingHeader-topOffset' | ||
| const DEFAULT_BOUNDS_HEIGHT_PROPERTY_NAME = '--hidingHeader-bounds-height' | ||
| const contentSelector = DEFAULT_CONTENT_SELECTOR | ||
| const heightPropertyName = DEFAULT_HEIGHT_PROPERTY_NAME | ||
| const scrollCapPropertyName = DEFAULT_SCROLL_CAP_PROPERTY_NAME | ||
| const topOffsetPropertyName = DEFAULT_TOP_OFFSET_PROPERTY_NAME | ||
| const boundsHeightPropertyName = DEFAULT_BOUNDS_HEIGHT_PROPERTY_NAME | ||
| let lastScrollTopPosition = 0 | ||
| let contentHeight = 0 | ||
| let lastScrollCap = 0 | ||
| let topOffset = 0 | ||
| let lastContentHeight = 0 | ||
| let paused = false | ||
| let lastBoundsHeight = 0 | ||
@@ -36,8 +33,8 @@ const content = container.querySelector(contentSelector) | ||
| const getTopOffset = () => { | ||
| const getGlobalTopOffset = () => { | ||
| return container.offsetTop | ||
| } | ||
| const getContainerOffset = () => { | ||
| return container.getBoundingClientRect().top | ||
| const getRelativeTopOffset = () => { | ||
| return getGlobalTopOffset() - (container.parentElement?.offsetTop || 0) | ||
| } | ||
@@ -47,22 +44,12 @@ | ||
| const parentHeight = getParentHeight() | ||
| const containerOffset = getContainerOffset() | ||
| const globalTopOffset = getGlobalTopOffset() | ||
| // Handle top offset | ||
| const currentTopOffset = getTopOffset() | ||
| if (topOffset !== currentTopOffset) { | ||
| topOffset = currentTopOffset | ||
| container.style.setProperty( | ||
| topOffsetPropertyName, | ||
| `${currentTopOffset}px` | ||
| ) | ||
| } | ||
| // Handle content height | ||
| const currentContentHeight = getContentHeight() | ||
| if (contentHeight !== currentContentHeight) { | ||
| contentHeight = currentContentHeight | ||
| container.style.setProperty(heightPropertyName, `${contentHeight}px`) | ||
| const contentHeight = getContentHeight() | ||
| if (lastContentHeight !== contentHeight) { | ||
| lastContentHeight = contentHeight | ||
| container.style.setProperty(heightPropertyName, `${lastContentHeight}px`) | ||
| } | ||
| // Handle scroll cap | ||
| // Handle bounds height | ||
| const scrollTopPosition = window.scrollY | ||
@@ -72,27 +59,33 @@ const isScrollingDown = scrollTopPosition > lastScrollTopPosition | ||
| if (!paused) { | ||
| // @TODO: fix offset variant on direction change | ||
| const scrollCap = Math.min( | ||
| parentHeight - contentHeight, | ||
| (() => { | ||
| const scrollCapBottomPosition = | ||
| lastScrollTopPosition + | ||
| containerOffset + | ||
| lastScrollCap + | ||
| contentHeight | ||
| if (isScrollingDown) { | ||
| const newScrollCap = scrollTopPosition - contentHeight | ||
| return scrollCapBottomPosition < scrollTopPosition | ||
| ? newScrollCap | ||
| : lastScrollCap | ||
| } else { | ||
| const newScrollCap = scrollTopPosition | ||
| return newScrollCap < scrollCapBottomPosition - contentHeight | ||
| ? newScrollCap | ||
| : lastScrollCap | ||
| } | ||
| })() | ||
| const maxBoundsHeight = parentHeight - getRelativeTopOffset() | ||
| const boundsHeight = Math.min( | ||
| maxBoundsHeight, | ||
| Math.max( | ||
| contentHeight, | ||
| (() => { | ||
| if (isScrollingDown) { | ||
| const newBoundsHeight = scrollTopPosition - globalTopOffset | ||
| if (lastBoundsHeight < newBoundsHeight) { | ||
| return newBoundsHeight | ||
| } | ||
| return lastBoundsHeight | ||
| } else { | ||
| const newBoundsHeight = | ||
| scrollTopPosition - globalTopOffset + contentHeight | ||
| if (lastBoundsHeight > newBoundsHeight) { | ||
| return newBoundsHeight | ||
| } | ||
| return lastBoundsHeight | ||
| } | ||
| })() | ||
| ) | ||
| ) | ||
| if (scrollCap !== lastScrollCap) { | ||
| container.style.setProperty(scrollCapPropertyName, `${scrollCap}px`) | ||
| lastScrollCap = scrollCap | ||
| if (boundsHeight !== lastBoundsHeight) { | ||
| container.style.setProperty( | ||
| boundsHeightPropertyName, | ||
| `${boundsHeight}px` | ||
| ) | ||
| lastBoundsHeight = boundsHeight | ||
| } | ||
@@ -99,0 +92,0 @@ } |
11529
-7.07%207
-8%64
-4.48%