fix: Landscape mode photo layout and button backdrop improvements
Fixed two critical landscape mode issues on mobile devices: 1. Button backdrop blur bar now shows in landscape mode - Added iOS-style blur backdrop with 70px height for landscape - Consistent visual experience between portrait and landscape - Supports dark mode with appropriate theming 2. Photo positioned on the right in landscape with better sizing - Changed from stacked single-column to two-column grid layout - Photo now positioned on right side (180px vs previous 120px) - Text (name, experience, intro) on left, photo on right - Better use of horizontal space in landscape orientation - Left-aligned text for cleaner layout with photo on right Test results (iPhone SE & iPhone 12 landscape): ✅ Two-column layout with photo on right ✅ Photo properly sized and positioned (180px) ✅ Button backdrop visible with blur effect ✅ No horizontal scroll ✅ All landscape tests passing Test: tests/mjs/59-landscape-photo-and-backdrop-test.mjs
This commit is contained in:
@@ -701,6 +701,30 @@
|
|||||||
======================================== */
|
======================================== */
|
||||||
|
|
||||||
@media (max-width: 915px) and (orientation: landscape) {
|
@media (max-width: 915px) and (orientation: landscape) {
|
||||||
|
/* iOS-style blur backdrop for buttons in landscape */
|
||||||
|
@supports (backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px)) {
|
||||||
|
.fixed-buttons-backdrop {
|
||||||
|
display: block !important;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 70px; /* Slightly smaller for landscape */
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
backdrop-filter: blur(20px) saturate(180%);
|
||||||
|
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||||||
|
border-top: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 98;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-color-theme="dark"] .fixed-buttons-backdrop,
|
||||||
|
[data-color-theme="auto"] .fixed-buttons-backdrop {
|
||||||
|
background: rgba(30, 30, 30, 0.8);
|
||||||
|
border-top: 0.5px solid rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* CRITICAL: Prevent horizontal scroll in landscape */
|
/* CRITICAL: Prevent horizontal scroll in landscape */
|
||||||
* {
|
* {
|
||||||
max-width: 100vw !important;
|
max-width: 100vw !important;
|
||||||
@@ -783,33 +807,59 @@
|
|||||||
|
|
||||||
.cv-name {
|
.cv-name {
|
||||||
font-size: 1.4rem !important;
|
font-size: 1.4rem !important;
|
||||||
text-align: center;
|
text-align: left !important; /* Left-aligned with photo on right */
|
||||||
}
|
}
|
||||||
|
|
||||||
.years-experience {
|
.years-experience {
|
||||||
font-size: 1em !important;
|
font-size: 1em !important;
|
||||||
text-align: center;
|
text-align: left !important; /* Left-aligned with photo on right */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reduce photo size in landscape to ~50% width but keep visible */
|
/* Two-column layout in landscape: text left, photo right */
|
||||||
.cv-header-content {
|
.cv-header-left {
|
||||||
flex-direction: column;
|
display: grid !important;
|
||||||
align-items: center;
|
grid-template-columns: 1fr auto !important;
|
||||||
gap: 0.5rem;
|
grid-template-rows: auto auto auto !important;
|
||||||
|
gap: 0.5rem 1rem !important;
|
||||||
|
align-items: start !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Name spans column 1, row 1 */
|
||||||
|
.cv-name {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Experience years spans column 1, row 2 */
|
||||||
|
.years-experience {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 2;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Intro text spans column 1, row 3 */
|
||||||
|
.intro-text {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 3;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Photo on the right side, spans all 3 rows */
|
||||||
.cv-photo {
|
.cv-photo {
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 1 / 4;
|
||||||
position: static !important;
|
position: static !important;
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
max-width: 120px !important;
|
max-width: 180px !important; /* Bigger than before (was 120px) */
|
||||||
margin: 0.5rem auto !important;
|
margin: 0 !important;
|
||||||
text-align: center;
|
align-self: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cv-photo img {
|
.cv-photo img {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compact action bar - keep hamburger menu visible */
|
/* Compact action bar - keep hamburger menu visible */
|
||||||
|
|||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { chromium } from 'playwright';
|
||||||
|
|
||||||
|
const LANDSCAPE_VIEWPORT = { width: 667, height: 375 }; // iPhone SE landscape
|
||||||
|
const IPHONE_12_LANDSCAPE = { width: 844, height: 390 }; // iPhone 12 landscape
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const browser = await chromium.launch({ headless: true });
|
||||||
|
|
||||||
|
console.log('🧪 Testing Landscape Mode: Photo Layout & Button Backdrop\n');
|
||||||
|
|
||||||
|
// TEST 1: iPhone SE Landscape
|
||||||
|
console.log('📱 TEST 1: iPhone SE Landscape (667×375)\n');
|
||||||
|
const seContext = await browser.newContext({
|
||||||
|
viewport: LANDSCAPE_VIEWPORT,
|
||||||
|
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1',
|
||||||
|
hasTouch: true
|
||||||
|
});
|
||||||
|
const sePage = await seContext.newPage();
|
||||||
|
|
||||||
|
await sePage.goto('http://localhost:1999/?lang=en&view=extended');
|
||||||
|
await sePage.waitForLoadState('networkidle');
|
||||||
|
|
||||||
|
const seLayout = await sePage.evaluate(() => {
|
||||||
|
const headerLeft = document.querySelector('.cv-header-left');
|
||||||
|
const photo = document.querySelector('.cv-photo');
|
||||||
|
const backdrop = document.querySelector('.fixed-buttons-backdrop');
|
||||||
|
const cvName = document.querySelector('.cv-name');
|
||||||
|
|
||||||
|
const headerGrid = headerLeft ? window.getComputedStyle(headerLeft).gridTemplateColumns : 'N/A';
|
||||||
|
const twoColumns = headerGrid.includes(' '); // Has space = multiple columns
|
||||||
|
|
||||||
|
const photoRect = photo ? photo.getBoundingClientRect() : null;
|
||||||
|
const nameRect = cvName ? cvName.getBoundingClientRect() : null;
|
||||||
|
|
||||||
|
// Photo should be on the right side (higher x position than name)
|
||||||
|
const photoOnRight = photoRect && nameRect && photoRect.left > nameRect.left;
|
||||||
|
|
||||||
|
return {
|
||||||
|
viewport: `${window.innerWidth}×${window.innerHeight}`,
|
||||||
|
headerGrid: headerGrid,
|
||||||
|
twoColumns: twoColumns,
|
||||||
|
photoWidth: photoRect ? Math.round(photoRect.width) : 0,
|
||||||
|
photoLeft: photoRect ? Math.round(photoRect.left) : 0,
|
||||||
|
nameLeft: nameRect ? Math.round(nameRect.left) : 0,
|
||||||
|
photoOnRight: photoOnRight,
|
||||||
|
nameAlign: cvName ? window.getComputedStyle(cvName).textAlign : 'N/A',
|
||||||
|
backdropVisible: backdrop ? window.getComputedStyle(backdrop).display !== 'none' : false,
|
||||||
|
backdropHeight: backdrop ? window.getComputedStyle(backdrop).height : 'N/A',
|
||||||
|
hasHorizontalScroll: document.body.scrollWidth > window.innerWidth
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('iPhone SE Landscape Layout:');
|
||||||
|
console.log(` • Viewport: ${seLayout.viewport}`);
|
||||||
|
console.log(` • Header grid: ${seLayout.headerGrid}`);
|
||||||
|
console.log(` • Two-column layout: ${seLayout.twoColumns ? '✅' : '❌'}`);
|
||||||
|
console.log(` • Photo width: ${seLayout.photoWidth}px`);
|
||||||
|
console.log(` • Photo on right side: ${seLayout.photoOnRight ? '✅' : '❌'} (Photo: ${seLayout.photoLeft}px, Name: ${seLayout.nameLeft}px)`);
|
||||||
|
console.log(` • Name alignment: ${seLayout.nameAlign}`);
|
||||||
|
console.log(` • Button backdrop visible: ${seLayout.backdropVisible ? '✅' : '❌'}`);
|
||||||
|
console.log(` • Backdrop height: ${seLayout.backdropHeight}`);
|
||||||
|
console.log(` • Has horizontal scroll: ${seLayout.hasHorizontalScroll ? '❌ FAIL' : '✅'}\n`);
|
||||||
|
|
||||||
|
await sePage.screenshot({
|
||||||
|
path: 'tests/screenshots/landscape-photo-se.png',
|
||||||
|
fullPage: true
|
||||||
|
});
|
||||||
|
|
||||||
|
await seContext.close();
|
||||||
|
|
||||||
|
// TEST 2: iPhone 12 Landscape
|
||||||
|
console.log('📱 TEST 2: iPhone 12 Landscape (844×390)\n');
|
||||||
|
const iphone12Context = await browser.newContext({
|
||||||
|
viewport: IPHONE_12_LANDSCAPE,
|
||||||
|
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1',
|
||||||
|
hasTouch: true
|
||||||
|
});
|
||||||
|
const iphone12Page = await iphone12Context.newPage();
|
||||||
|
|
||||||
|
await iphone12Page.goto('http://localhost:1999/?lang=en&view=extended');
|
||||||
|
await iphone12Page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
|
const iphone12Layout = await iphone12Page.evaluate(() => {
|
||||||
|
const headerLeft = document.querySelector('.cv-header-left');
|
||||||
|
const photo = document.querySelector('.cv-photo');
|
||||||
|
const backdrop = document.querySelector('.fixed-buttons-backdrop');
|
||||||
|
const cvName = document.querySelector('.cv-name');
|
||||||
|
|
||||||
|
const headerGrid = headerLeft ? window.getComputedStyle(headerLeft).gridTemplateColumns : 'N/A';
|
||||||
|
const twoColumns = headerGrid.includes(' ');
|
||||||
|
|
||||||
|
const photoRect = photo ? photo.getBoundingClientRect() : null;
|
||||||
|
const nameRect = cvName ? cvName.getBoundingClientRect() : null;
|
||||||
|
const photoOnRight = photoRect && nameRect && photoRect.left > nameRect.left;
|
||||||
|
|
||||||
|
return {
|
||||||
|
viewport: `${window.innerWidth}×${window.innerHeight}`,
|
||||||
|
headerGrid: headerGrid,
|
||||||
|
twoColumns: twoColumns,
|
||||||
|
photoWidth: photoRect ? Math.round(photoRect.width) : 0,
|
||||||
|
photoLeft: photoRect ? Math.round(photoRect.left) : 0,
|
||||||
|
nameLeft: nameRect ? Math.round(nameRect.left) : 0,
|
||||||
|
photoOnRight: photoOnRight,
|
||||||
|
nameAlign: cvName ? window.getComputedStyle(cvName).textAlign : 'N/A',
|
||||||
|
backdropVisible: backdrop ? window.getComputedStyle(backdrop).display !== 'none' : false,
|
||||||
|
backdropHeight: backdrop ? window.getComputedStyle(backdrop).height : 'N/A',
|
||||||
|
hasHorizontalScroll: document.body.scrollWidth > window.innerWidth
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('iPhone 12 Landscape Layout:');
|
||||||
|
console.log(` • Viewport: ${iphone12Layout.viewport}`);
|
||||||
|
console.log(` • Header grid: ${iphone12Layout.headerGrid}`);
|
||||||
|
console.log(` • Two-column layout: ${iphone12Layout.twoColumns ? '✅' : '❌'}`);
|
||||||
|
console.log(` • Photo width: ${iphone12Layout.photoWidth}px`);
|
||||||
|
console.log(` • Photo on right side: ${iphone12Layout.photoOnRight ? '✅' : '❌'} (Photo: ${iphone12Layout.photoLeft}px, Name: ${iphone12Layout.nameLeft}px)`);
|
||||||
|
console.log(` • Name alignment: ${iphone12Layout.nameAlign}`);
|
||||||
|
console.log(` • Button backdrop visible: ${iphone12Layout.backdropVisible ? '✅' : '❌'}`);
|
||||||
|
console.log(` • Backdrop height: ${iphone12Layout.backdropHeight}`);
|
||||||
|
console.log(` • Has horizontal scroll: ${iphone12Layout.hasHorizontalScroll ? '❌ FAIL' : '✅'}\n`);
|
||||||
|
|
||||||
|
await iphone12Page.screenshot({
|
||||||
|
path: 'tests/screenshots/landscape-photo-iphone12.png',
|
||||||
|
fullPage: true
|
||||||
|
});
|
||||||
|
|
||||||
|
await iphone12Context.close();
|
||||||
|
|
||||||
|
const allPassed = seLayout.twoColumns && seLayout.photoOnRight && seLayout.backdropVisible && !seLayout.hasHorizontalScroll &&
|
||||||
|
iphone12Layout.twoColumns && iphone12Layout.photoOnRight && iphone12Layout.backdropVisible && !iphone12Layout.hasHorizontalScroll;
|
||||||
|
|
||||||
|
console.log(`${allPassed ? '✅' : '❌'} Tests ${allPassed ? 'PASSED' : 'FAILED'}\n`);
|
||||||
|
|
||||||
|
await browser.close();
|
||||||
|
process.exit(allPassed ? 0 : 1);
|
||||||
|
})();
|
||||||
Reference in New Issue
Block a user