Skip to content

Instantly share code, notes, and snippets.

@louy
Created May 24, 2023 08:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save louy/94dd002eb62d30e4d8ff624730b4b6cd to your computer and use it in GitHub Desktop.
Save louy/94dd002eb62d30e4d8ff624730b4b6cd to your computer and use it in GitHub Desktop.
Fresha Search Layout
<div id="header">
Fresha
</div>
<div id="grid">
<div id="map-placeholder">
<div id="map">
<!-- sticky -->
<div id="map-inner">
<!-- relative -->
<div id="map-canvas">
<h1>
Map
</h1>
</div>
<div id="map-actions">
<button id="geolocation-button">Geolocation</button>
</div>
</div>
</div>
</div>
<div id="list">
<div id="list-map-cover"></div>
<div id="filters">
<h2>
Filters
</h2>
</div>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
</div>
</div>
function preventDefault(e) {
e.preventDefault();
e.stopPropagation();
return false;
}
// modern Chrome requires { passive: false } when adding event
var supportsPassive = false;
try {
window.addEventListener(
"test",
null,
Object.defineProperty({}, "passive", {
get: function () {
supportsPassive = true;
}
})
);
} catch (e) {}
var wheelOpt = supportsPassive
? {
passive: false
}
: false;
var wheelEvent =
"onwheel" in document.createElement("div") ? "wheel" : "mousewheel";
// call this to Disable
function disableScroll(el) {
el.addEventListener("DOMMouseScroll", preventDefault, false); // older FF
el.addEventListener(wheelEvent, preventDefault, wheelOpt); // modern desktop
el.addEventListener("touchmove", preventDefault, wheelOpt); // mobile
/* el.addEventListener('keydown', preventDefaultForScrollKeys, false) */
}
/* disableScroll(document.getElementById('map')) */
disableScroll(document.getElementById("map-placeholder"));
/* disableScroll(window) */
// When the user scrolls down 50px from the top of the document, resize the header's font size
window.onscroll = onScroll;
function onScroll() {
document.documentElement.style.setProperty(
"--scroll-y",
Math.max(0, window.scrollY)
);
}
// When the user scrolls down 50px from the top of the document, resize the header's font size
window.onresize = onResize;
function onResize() {
document.documentElement.style.setProperty(
"--inner-height",
document.documentElement.clientHeight
);
}
onResize();
:root {
/* Set by js */
--scroll-y: 0;
--inner-height: 0;
--header-height: 120;
--header-height-collapsed: var(--header-height);
--header-margin: 0;
--inset-top: calc(var(--header-margin) * 2 + var(--header-height-collapsed));
--list-width: 400px;
--filters-height: 100;
--scroll-y-px: calc(var(--scroll-y) * 1px);
--header-margin-px: calc(var(--header-margin) * 1px);
--header-height-px: calc(var(--header-height) * 1px);
--header-height-collapsed-px: calc(var(--header-height-collapsed) * 1px);
--inset-top-px: calc(var(--inset-top) * 1px);
--filters-height-px: calc(var(--filters-height) * 1px);
}
/* apply a natural box layout model to all elements, but allowing components to change */
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body,
html,
ul,
li {
padding: 0;
margin: 0;
}
#map {
background: cyan;
opacity: 1;
display: flex;
align-items: center;
justify-content: center;
}
#list ul {
padding: 20px;
background: white;
}
#header {
background: white;
border: 1px solid grey;
--height-shrink-max-px: calc(
var(--header-height-px) - var(--header-height-collapsed-px)
);
height: calc(
var(--header-height-px) -
min(var(--scroll-y-px), var(--height-shrink-max-px))
);
width: auto;
display: flex;
align-items: center;
justify-content: center;
position: sticky;
top: 0;
left: 0;
right: 0;
}
#grid {
display: grid;
grid-template-columns: var(--list-width) 1fr;
}
#map-placeholder {
grid-column: 2;
}
#map {
position: fixed;
top: var(--inset-top-px);
right: 0;
left: var(--list-width);
bottom: 0;
}
#map-canvas {
display: flex;
align-items: center;
justify-content: center;
}
#map-actions {
position: absolute;
bottom: 10px;
right: 10px;
}
#filters {
position: sticky;
padding: 20px;
top: var(--inset-top-px);
background-color: white;
border-bottom: 1px solid white;
--border-opacity: calc(min(1, var(--scroll-y) / 5));
border-bottom-color: rgba(25, 25, 25, var(--border-opacity));
transition: border-color 0.2s ease-out;
height: var(--filters-height-px);
}
@media (max-width: 600px) {
:root {
--header-height: 80;
--header-height-collapsed: 50;
--header-margin: 20;
--card-border-radius: 20;
--card-border-radius-px: calc(var(--card-border-radius) * 1px);
--map-placeholder-color: #ccc;
scroll-snap-type: y proximity;
}
#header {
position: fixed;
border-radius: 50px;
margin: var(--header-margin-px);
z-index: 10;
}
#grid {
grid-template-columns: auto;
grid-template-rows: auto auto;
z-index: 7;
}
#map-placeholder {
grid-column: 1;
grid-row: 1;
height: 100svh;
margin-bottom: calc(-1px * var(--filters-height));
/* filters size */
background-color: var(--map-placeholder-color);
}
#list {
grid-column: 1;
grid-row: 2;
}
#list-map-cover {
height: calc(var(--inset-top-px) + var(--card-border-radius-px));
margin-bottom: calc(
-1 * (var(--inset-top-px) + var(--card-border-radius-px))
);
position: sticky;
top: 0;
z-index: 1;
background-color: var(--map-placeholder-color);
opacity: calc(
/* set to 0 at exactly window height - scroll - header height - filters height*/ -1 *
(
var(--inner-height) - var(--scroll-y) - var(--inset-top) -
var(--filters-height)
) - 10 /* Give it some grace transition to allow for scroll bounciness */
);
}
#map {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: auto;
height: 100svh;
/* z-index: -1; */
scroll-snap-align: start;
opacity: calc(
/* set to 0 at exactly window height - scroll - header height - filters height*/
var(--inner-height) - var(--scroll-y) - var(--inset-top) -
var(--filters-height)
);
transition: opacity 0.2s ease-out;
}
#filters {
position: sticky;
top: calc(var(--header-height-collapsed-px) + var(--header-margin-px) * 2);
background: white;
border-radius: var(--card-border-radius-px) var(--card-border-radius-px) 0 0;
z-index: 2;
scroll-snap-align: start;
scroll-margin-top: calc(
var(--header-height-collapsed-px) + var(--header-margin-px) * 2
);
--border-opacity: calc(
/* set to 0 at exactly window height - scroll - header height - filters height*/ -1 *
(
var(--inner-height) - var(--scroll-y) - var(--inset-top) -
var(--filters-height)
)
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment