Skip to content

Commit 6f367ac

Browse files
Adjust search bar for iPhone
1 parent c4a1157 commit 6f367ac

File tree

2 files changed

+82
-8
lines changed

2 files changed

+82
-8
lines changed

css/components/search.css

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
color: var(--color-light-text-primary);
1313
background-color: var(--color-light-bg-secondary);
1414
border: 1px solid var(--color-light-border);
15-
border-radius: var(--radius-full);
15+
border-radius: var(--radius-xl);
1616
outline: none;
1717
cursor: pointer;
1818
transition: all var(--duration-normal) var(--ease-out);
@@ -75,6 +75,14 @@
7575
}
7676
}
7777

78+
@media (max-width: 768px) {
79+
.site-header__search-trigger {
80+
max-width: none;
81+
width: 100%;
82+
flex: 1;
83+
}
84+
}
85+
7886
.search-modal {
7987
position: fixed;
8088
top: 0;
@@ -383,18 +391,21 @@
383391
max-width: 100%;
384392
width: 100%;
385393
height: auto;
386-
max-height: calc(100vh - 32px);
394+
max-height: calc(100dvh - 32px);
395+
max-height: calc(var(--vh, 1vh) * 100 - 32px); /* Fallback for browsers without dvh support */
387396
}
388397

389398
.search-modal__content {
390399
border-radius: var(--radius-lg);
391400
height: auto;
392-
max-height: calc(100vh - 32px);
401+
max-height: calc(100dvh - 32px);
402+
max-height: calc(var(--vh, 1vh) * 100 - 32px);
393403
}
394404

395405
/* When results are visible, expand to full height */
396406
.search-modal__content:has(.search-modal__results[style*="display: block"]) {
397-
height: calc(100vh - 32px);
407+
height: calc(100dvh - 32px);
408+
height: calc(var(--vh, 1vh) * 100 - 32px);
398409
}
399410

400411
.search-modal__input-wrapper {

static/search.js

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,54 @@ const searchResultsItems = document.getElementById("search-results__items");
1414
let searchItemSelected = null;
1515
let resultsItemsIndex = -1;
1616

17+
////////////////////////////////////
18+
// Viewport Height Handler for Mobile
19+
////////////////////////////////////
20+
21+
// Set CSS custom property for viewport height (for browsers without dvh support)
22+
function setViewportHeight() {
23+
// Get the actual viewport height (excludes keyboard on mobile)
24+
const vh = window.visualViewport ? window.visualViewport.height * 0.01 : window.innerHeight * 0.01;
25+
document.documentElement.style.setProperty('--vh', `${vh}px`);
26+
}
27+
28+
// Initialize and listen for viewport changes
29+
if (window.visualViewport) {
30+
setViewportHeight();
31+
window.visualViewport.addEventListener('resize', setViewportHeight);
32+
} else {
33+
// Fallback for browsers without visualViewport API
34+
setViewportHeight();
35+
window.addEventListener('resize', setViewportHeight);
36+
}
37+
1738
////////////////////////////////////
1839
// Modal Management
1940
////////////////////////////////////
2041

2142
function openSearchModal() {
2243
searchModal.setAttribute("aria-hidden", "false");
23-
document.body.style.overflow = "hidden";
44+
45+
// Detect iOS devices
46+
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
47+
48+
if (isIOS) {
49+
// iOS-specific scroll lock (position: fixed approach)
50+
const scrollY = window.scrollY;
51+
document.body.style.position = "fixed";
52+
document.body.style.top = `-${scrollY}px`;
53+
document.body.style.width = "100%";
54+
document.body.style.overflow = "hidden";
55+
document.body.setAttribute("data-scroll-y", scrollY.toString());
56+
} else {
57+
// Simple overflow: hidden for other browsers
58+
document.body.style.overflow = "hidden";
59+
}
2460

2561
// Focus the search input after a brief delay to ensure modal is visible
26-
// Longer delay for mobile devices to ensure proper focus
62+
// Longer delay for iOS to account for position: fixed layout changes
2763
const isMobile = window.innerWidth <= 768;
28-
const delay = isMobile ? 200 : 100;
64+
const delay = isIOS ? 300 : (isMobile ? 200 : 100);
2965

3066
// On mobile, hide results when input is empty (input stays visible)
3167
if (isMobile && searchResults) {
@@ -38,12 +74,39 @@ function openSearchModal() {
3874
if (isMobile) {
3975
searchInput.click();
4076
}
77+
78+
// iOS sometimes needs an additional nudge
79+
if (isIOS) {
80+
setTimeout(() => {
81+
searchInput.focus();
82+
searchInput.click();
83+
}, 50);
84+
}
4185
}, delay);
4286
}
4387

4488
function closeSearchModal() {
4589
searchModal.setAttribute("aria-hidden", "true");
46-
document.body.style.overflow = "";
90+
91+
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
92+
93+
if (isIOS) {
94+
// iOS-specific: restore scroll position
95+
const scrollY = document.body.getAttribute("data-scroll-y");
96+
document.body.style.position = "";
97+
document.body.style.top = "";
98+
document.body.style.width = "";
99+
document.body.style.overflow = "";
100+
document.body.removeAttribute("data-scroll-y");
101+
102+
if (scrollY) {
103+
window.scrollTo(0, parseInt(scrollY));
104+
}
105+
} else {
106+
// Simple overflow restore for other browsers
107+
document.body.style.overflow = "";
108+
}
109+
47110
searchInput.value = "";
48111
searchResults.style.display = "none";
49112
searchItemSelected = null;

0 commit comments

Comments
 (0)