mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-06-05 23:00:16 +00:00
Add custom scrollbar and scroll behavior to sidebar
The changes add a custom scrollbar and enhanced scroll functionality to the sidebar, with cross-browser support, accessibility features, and device-specific optimizations.
This commit is contained in:
@@ -120,6 +120,241 @@ div {
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
/* Custom scrollbar for sidebar */
|
||||
.sidebar::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-track {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 4px;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb:active {
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
/* Firefox scrollbar styling */
|
||||
.sidebar {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(255, 255, 255, 0.3) rgba(255, 255, 255, 0.1);
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Enhanced scrollbar for better UX */
|
||||
.sidebar::-webkit-scrollbar-corner {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Scrollbar styles for different states */
|
||||
.sidebar:hover::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.sidebar:focus-within::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
|
||||
/* Theme-aware scrollbar styling */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.sidebar::-webkit-scrollbar-track {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
/* High contrast mode support */
|
||||
@media (prefers-contrast: high) {
|
||||
.sidebar::-webkit-scrollbar-track {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border: 1px solid rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduced motion support */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.sidebar {
|
||||
scroll-behavior: auto;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile and touch device enhancements */
|
||||
@media (max-width: 768px) {
|
||||
.sidebar::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.4);
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Touch scrolling improvements */
|
||||
.sidebar {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
/* iPad-specific scrollbar styling */
|
||||
@media (min-width: 768px) and (max-width: 1366px) {
|
||||
.sidebar::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-track {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border-radius: 5px;
|
||||
margin: 0.75rem 0;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.35) 0%, rgba(255, 255, 255, 0.25) 100%);
|
||||
border-radius: 5px;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb:hover {
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.55) 0%, rgba(255, 255, 255, 0.45) 100%);
|
||||
}
|
||||
}
|
||||
|
||||
/* Auto-hide scrollbar when not scrolling */
|
||||
.sidebar {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.sidebar:not(:hover):not(:focus-within) {
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.sidebar:not(:hover):not(:focus-within)::-webkit-scrollbar {
|
||||
width: 0px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* Show scrollbar on hover/focus */
|
||||
.sidebar:hover::-webkit-scrollbar,
|
||||
.sidebar:focus-within::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
transition: width 0.2s ease;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) and (max-width: 1366px) {
|
||||
.sidebar:hover::-webkit-scrollbar,
|
||||
.sidebar:focus-within::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Active scrolling visual feedback */
|
||||
.sidebar::-webkit-scrollbar-thumb:active {
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
transform: scale(1.1);
|
||||
transition: all 0.1s ease;
|
||||
}
|
||||
|
||||
/* Smooth scroll enhancements */
|
||||
.sidebar {
|
||||
scroll-padding-top: 1rem;
|
||||
scroll-padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Focus-visible scrollbar enhancement */
|
||||
.sidebar:focus-visible::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
/* Scrollbar animation on keyboard navigation */
|
||||
.keyboard-navigation .sidebar::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
/* Better scrollbar visibility during navigation */
|
||||
.sidebar-nav a:focus {
|
||||
scroll-margin-top: 2rem;
|
||||
scroll-margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
/* Initial scrollbar reveal animation */
|
||||
@keyframes scrollbarReveal {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(10px);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0.6;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
animation: scrollbarReveal 3s ease-out;
|
||||
}
|
||||
|
||||
/* Scrollbar accessibility improvements */
|
||||
.sidebar[aria-label] {
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
/* Better contrast for users with vision difficulties */
|
||||
@media (prefers-contrast: more) {
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: 1px solid rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-track {
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
border: 1px solid rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
}
|
||||
|
||||
/* Scrollbar size adjustment for different zoom levels */
|
||||
@media (min-resolution: 192dpi) {
|
||||
.sidebar::-webkit-scrollbar {
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar-thumb {
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
padding: 0 1rem 1.5rem;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
|
||||
|
||||
@@ -1116,9 +1116,80 @@
|
||||
setupKeyboardNavigation();
|
||||
}
|
||||
|
||||
// Enhanced scrollbar functionality
|
||||
function enhanceScrollbarExperience() {
|
||||
const sidebar = document.getElementById("sidebar");
|
||||
if (!sidebar) return;
|
||||
|
||||
// Add smooth scrolling to sidebar navigation links
|
||||
const navLinks = sidebar.querySelectorAll('.sidebar-nav a');
|
||||
navLinks.forEach(link => {
|
||||
link.addEventListener('click', (e) => {
|
||||
// Smooth scroll the link into view within sidebar
|
||||
setTimeout(() => {
|
||||
link.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'nearest',
|
||||
inline: 'nearest'
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
// Enhanced keyboard navigation with scrollbar awareness
|
||||
sidebar.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
||||
setTimeout(() => {
|
||||
const focusedElement = document.activeElement;
|
||||
if (focusedElement && sidebar.contains(focusedElement)) {
|
||||
focusedElement.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'nearest',
|
||||
inline: 'nearest'
|
||||
});
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
|
||||
// Add scroll position memory
|
||||
let scrollPosition = 0;
|
||||
sidebar.addEventListener('scroll', () => {
|
||||
scrollPosition = sidebar.scrollTop;
|
||||
});
|
||||
|
||||
// Restore scroll position on page reload
|
||||
const savedScrollPosition = sessionStorage.getItem('sidebar-scroll-position');
|
||||
if (savedScrollPosition) {
|
||||
sidebar.scrollTop = parseInt(savedScrollPosition);
|
||||
sessionStorage.removeItem('sidebar-scroll-position');
|
||||
}
|
||||
|
||||
// Save scroll position before page unload
|
||||
window.addEventListener('beforeunload', () => {
|
||||
sessionStorage.setItem('sidebar-scroll-position', sidebar.scrollTop.toString());
|
||||
});
|
||||
|
||||
// Add accessibility enhancements
|
||||
sidebar.setAttribute('aria-label', 'Main navigation sidebar');
|
||||
sidebar.setAttribute('role', 'navigation');
|
||||
|
||||
// Show scrollbar briefly on focus to indicate scrollability
|
||||
sidebar.addEventListener('focus', () => {
|
||||
sidebar.style.scrollbarWidth = 'thin';
|
||||
setTimeout(() => {
|
||||
if (!sidebar.matches(':hover')) {
|
||||
sidebar.style.scrollbarWidth = 'none';
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize on page load and handle layout changes
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initializeIPadSupport();
|
||||
enhanceScrollbarExperience();
|
||||
|
||||
// Force sidebar to be visible immediately
|
||||
const sidebar = document.getElementById("sidebar");
|
||||
if (sidebar && window.innerWidth > 767) {
|
||||
|
||||
Reference in New Issue
Block a user