refactor: wrap content in zoom-wrapper to fix footer gap issue
- Created zoom-wrapper div around cv-container - Zoom now applies to wrapper only, footer adjusts naturally below - Footer no longer scaled, stays at normal size - Fixes gap between content and footer at low zoom levels - Reduced back-to-top button size (35px default, grows to 50px on hover) - Cleaner separation of concerns for zoom functionality
This commit is contained in:
+10
-9
@@ -491,6 +491,13 @@ iconify-icon {
|
|||||||
100% { transform: rotate(360deg); }
|
100% { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Zoom Wrapper - wraps cv-container for zoom functionality */
|
||||||
|
.zoom-wrapper {
|
||||||
|
transform-origin: top center; /* Scale from top center */
|
||||||
|
transition: transform 0.08s linear; /* Smooth zoom response */
|
||||||
|
will-change: transform; /* Optimize for transforms */
|
||||||
|
}
|
||||||
|
|
||||||
/* Main CV Container */
|
/* Main CV Container */
|
||||||
.cv-container {
|
.cv-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -498,9 +505,6 @@ iconify-icon {
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px 0 0 0; /* Top padding to prevent sticky action bar overlap */
|
padding: 20px 0 0 0; /* Top padding to prevent sticky action bar overlap */
|
||||||
display: block; /* Changed from flex */
|
display: block; /* Changed from flex */
|
||||||
transform-origin: top center; /* Scale from top center - container stays anchored at top */
|
|
||||||
transition: transform 0.08s linear; /* Smooth, immediate zoom response */
|
|
||||||
will-change: transform; /* Hint browser to optimize for transforms */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clean theme - no sidebars, centered content */
|
/* Clean theme - no sidebars, centered content */
|
||||||
@@ -1700,9 +1704,6 @@ a:focus {
|
|||||||
padding: 20px 0;
|
padding: 20px 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
grid-column: 1 / -1; /* Span all columns */
|
grid-column: 1 / -1; /* Span all columns */
|
||||||
transform-origin: top center; /* Scale from top center - footer stays anchored at top */
|
|
||||||
transition: transform 0.08s linear; /* Smooth, immediate zoom response */
|
|
||||||
will-change: transform; /* Hint browser to optimize for transforms */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-content {
|
.footer-content {
|
||||||
@@ -2578,8 +2579,8 @@ html {
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 2rem;
|
bottom: 2rem;
|
||||||
right: 2rem;
|
right: 2rem;
|
||||||
width: 50px;
|
width: 35px; /* Smaller default size */
|
||||||
height: 50px;
|
height: 35px;
|
||||||
background: var(--black-bar);
|
background: var(--black-bar);
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -2596,7 +2597,7 @@ html {
|
|||||||
|
|
||||||
.back-to-top:hover {
|
.back-to-top:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(-3px);
|
transform: translateY(-3px) scale(1.43); /* Grow to ~50px on hover */
|
||||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
|
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
|
||||||
background: #3a3a3a;
|
background: #3a3a3a;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-11
@@ -273,9 +273,9 @@
|
|||||||
function initZoomControl() {
|
function initZoomControl() {
|
||||||
const slider = document.getElementById('zoom-slider');
|
const slider = document.getElementById('zoom-slider');
|
||||||
const resetBtn = document.getElementById('zoom-reset');
|
const resetBtn = document.getElementById('zoom-reset');
|
||||||
const cvPaper = document.querySelector('.cv-paper');
|
const zoomWrapper = document.getElementById('zoom-wrapper');
|
||||||
|
|
||||||
if (!slider || !cvPaper) return;
|
if (!slider || !zoomWrapper) return;
|
||||||
|
|
||||||
// On mobile, always use 100% zoom (zoom control is hidden anyway)
|
// On mobile, always use 100% zoom (zoom control is hidden anyway)
|
||||||
if (isMobileView()) {
|
if (isMobileView()) {
|
||||||
@@ -347,20 +347,15 @@
|
|||||||
* @param {boolean} saveToStorage - Whether to persist to localStorage
|
* @param {boolean} saveToStorage - Whether to persist to localStorage
|
||||||
*/
|
*/
|
||||||
function applyZoom(zoomValue, saveToStorage = true) {
|
function applyZoom(zoomValue, saveToStorage = true) {
|
||||||
const cvContainer = document.querySelector('.cv-container');
|
const zoomWrapper = document.getElementById('zoom-wrapper');
|
||||||
const cvFooter = document.querySelector('.cv-footer');
|
if (!zoomWrapper) return;
|
||||||
if (!cvContainer) return;
|
|
||||||
|
|
||||||
// Convert percentage to scale factor (100 = 1.0, 150 = 1.5, etc.)
|
// Convert percentage to scale factor (100 = 1.0, 150 = 1.5, etc.)
|
||||||
const scale = zoomValue / 100;
|
const scale = zoomValue / 100;
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
// Use transform: scale() for true visual zoom without constraints
|
// Apply zoom to wrapper - footer adjusts naturally below it
|
||||||
// This allows zoom to extend beyond viewport at >100%
|
zoomWrapper.style.transform = `scale(${scale})`;
|
||||||
cvContainer.style.transform = `scale(${scale})`;
|
|
||||||
if (cvFooter) {
|
|
||||||
cvFooter.style.transform = `scale(${scale})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update display
|
// Update display
|
||||||
updateZoomDisplay(zoomValue);
|
updateZoomDisplay(zoomValue);
|
||||||
|
|||||||
@@ -344,8 +344,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!-- CV Content Container -->
|
<!-- Zoom Wrapper (for zoom functionality) -->
|
||||||
<div class="cv-container">
|
<div id="zoom-wrapper" class="zoom-wrapper">
|
||||||
|
<!-- CV Content Container -->
|
||||||
|
<div class="cv-container">
|
||||||
<main id="cv-content"
|
<main id="cv-content"
|
||||||
class="cv-paper"
|
class="cv-paper"
|
||||||
role="main"
|
role="main"
|
||||||
@@ -432,7 +434,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> <!-- End cv-container -->
|
||||||
|
</div> <!-- End zoom-wrapper -->
|
||||||
|
|
||||||
<!-- PDF Export Modal -->
|
<!-- PDF Export Modal -->
|
||||||
<div id="pdf-modal" class="info-modal no-print" onclick="closePdfModalOnBackdrop(event)">
|
<div id="pdf-modal" class="info-modal no-print" onclick="closePdfModalOnBackdrop(event)">
|
||||||
|
|||||||
Reference in New Issue
Block a user