mirror of
https://github.com/FreshRSS/FreshRSS.git
synced 2026-06-10 16:45:14 -04:00
Always jump article to top when header is offscreen, also when 'Stick the article to the top when opened' is disabled (#8870)
* Always jump article to top when header is offscreen Closes #4069. How to test the feature manually: 1. Disable 'Stick the article to the top when opened' 2. Open a very long article 3. No scrolling will occur if you close it again while the header is still onscreen 4. If the header left the screen, opening another article will scroll to it to top 5. Same for collapsing the current article, but then it'll put the current header at the top * Compensate for layout shift * Fix going back to previous article above viewport * clarify variable name: header_off_screen → header_above_viewport
This commit is contained in:
@@ -463,6 +463,20 @@ function toggleContent(new_active, old_active, skipping) {
|
||||
loadLazyImages(new_active);
|
||||
}
|
||||
|
||||
const relative_move = context.current_view === 'global';
|
||||
const box_to_move = relative_move ? document.getElementById('panel') : document.scrollingElement;
|
||||
|
||||
const old_scrollTop = box_to_move.scrollTop;
|
||||
const old_offsetTop = new_active.offsetTop;
|
||||
|
||||
const nav_menu = document.querySelector('.nav_menu');
|
||||
let nav_menu_height = 0;
|
||||
if (nav_menu && (getComputedStyle(nav_menu).position === 'fixed' || getComputedStyle(nav_menu).position === 'sticky')) {
|
||||
nav_menu_height = nav_menu.offsetHeight;
|
||||
}
|
||||
|
||||
const flux_header = new_active.querySelector('.flux_header');
|
||||
|
||||
if (old_active !== new_active) {
|
||||
if (!skipping) {
|
||||
new_active.classList.add('active');
|
||||
@@ -479,18 +493,22 @@ function toggleContent(new_active, old_active, skipping) {
|
||||
new_active.classList.toggle('active');
|
||||
}
|
||||
|
||||
const relative_move = context.current_view === 'global';
|
||||
const box_to_move = relative_move ? document.getElementById('panel') : document.scrollingElement;
|
||||
const new_offsetTop = new_active.offsetTop;
|
||||
const layout_shift = new_offsetTop - old_offsetTop;
|
||||
|
||||
if (context.sticky_post) { // Stick the article to the top when opened
|
||||
const prev_article = new_active.previousElementSibling;
|
||||
const nav_menu = document.querySelector('.nav_menu');
|
||||
let nav_menu_height = 0;
|
||||
const prev_article = new_active.previousElementSibling;
|
||||
|
||||
if (nav_menu && (getComputedStyle(nav_menu).position === 'fixed' || getComputedStyle(nav_menu).position === 'sticky')) {
|
||||
nav_menu_height = nav_menu.offsetHeight;
|
||||
let header_above_viewport = false;
|
||||
|
||||
if (!context.sticky_post) {
|
||||
// Compensate for layout shift to maintain visual position
|
||||
box_to_move.scrollTop = old_scrollTop + layout_shift;
|
||||
if (flux_header) {
|
||||
header_above_viewport = flux_header.getBoundingClientRect().top < nav_menu_height;
|
||||
}
|
||||
}
|
||||
|
||||
if (context.sticky_post || header_above_viewport) { // Stick the article to the top when opened, or when header is off-screen
|
||||
let new_pos = new_active.offsetParent.offsetTop + new_active.offsetTop - nav_menu_height;
|
||||
|
||||
if (prev_article && prev_article.offsetParent && new_active.offsetTop - prev_article.offsetTop <= 150) {
|
||||
@@ -506,6 +524,23 @@ function toggleContent(new_active, old_active, skipping) {
|
||||
}
|
||||
|
||||
box_to_move.scrollTop = new_pos;
|
||||
} else {
|
||||
// If the header is below the viewport, scroll down just enough to bring it fully into view
|
||||
if (flux_header) {
|
||||
let bottom = flux_header.getBoundingClientRect().bottom;
|
||||
const inner_header = new_active.querySelector('.flux_content header');
|
||||
if (inner_header) {
|
||||
bottom = Math.max(bottom, inner_header.getBoundingClientRect().bottom);
|
||||
}
|
||||
let overflow = bottom - window.innerHeight;
|
||||
if (overflow > 0) {
|
||||
const max_overflow = flux_header.getBoundingClientRect().top - nav_menu_height;
|
||||
if (overflow > max_overflow) {
|
||||
overflow = max_overflow > 0 ? max_overflow : 0;
|
||||
}
|
||||
box_to_move.scrollTop += overflow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_active.classList.contains('active') && !skipping) {
|
||||
|
||||
Reference in New Issue
Block a user