Jhey ʕ·ᴥ· ʔ

Jhey ʕ·ᴥ· ʔ

@jhey.dev

designing interfaces. engineering experiences. many can build it. few can explain it. @shopify brand design studio 👰‍♀️ @seaotta.dev

10.2K followers28 following820 posts

had to repost because i posted the wrong video, missing a detail 🤦‍♂️ i would rather lose the "likes" and have the correct video on my timeline 🙏 the spotlight is meant to reveal the password, so here's a darker version with the shader tweaked 🤙

super easy CSS sticky scroll hide/reveal 🧑‍🍳 .sticky-atc { position: fixed; inset: auto 0 0 0; transition: translate 0.26s cubic-bezier(.55,0,.67,1.25); /* hide when scrolling down */ @container scroll-state(scrolled: bottom) { translate: 0 100%; transition-delay: 0.5s; } }

Bramus@bram.us

There’s a new type of CSS scroll-state query coming: “scrolled”. This one remembers the last direction you scrolled into, which you can use to build “hidey bars”: when scrolling down (or having scrolled down), the hidey bar hides itself. When then scrolling back up, the hidey bar reveals itself.

small details that matter 🧑‍🍳 use CSS pseudoelements to bridge the :hover gap w/ :has() + inset a:has(+ .dots) a::after, .dots + a::after { position: absolute; content: ''; } a:has(+ .dots) a::after { inset: 0 -50% 0 100%; } .dots + a::after { inset: 0 100% 0 -50%; }

progressive css-only pagination indicators w/ anchor positioning 👨‍🍳 nav::before { position-anchor: --h; } nav::before { left: anchor(left); } a:hover { anchor-name: --h; } use the nav pseudoelements, ::before for intent, ::after for current 🤙

apple-style disclosure w/ CSS details + summary 👨‍🍳 ::details-content { interpolate-size: allow-keywords; transition: content-visibility, height; transition-behavior: allow-discrete; } [open]::details-content { height: fit-content; } CSS :has() handling the image swaps 🤙

easing is everything use different CSS timing functions per axis for motion paths 👨‍🍳 .p { animation: x .8s var(--x-time), y .8s var(--y-time); animation-composition: accumulate; 👈 } @​keyframes x { to { translate: var(--x) 0 } @​keyframes y { to { translate: 0 var(--y) }

progressive css-only pagination indicators w/ anchor positioning 👨‍🍳 nav::before { position-anchor: --h; } nav::before { left: anchor(left); } a:hover { anchor-name: --h; } use the nav pseudoelements, ::before for intent, ::after for current 🤙

Jhey ʕ·ᴥ· ʔ reposted

Putting CSS Anchor Positioning to the test by throwing dropdown menus around 💪 [popover].dropdown { top: anchor(bottom); right: anchor(right); position-try-fallbacks: flip-block,flip-inline; } That's it 👆 Keeps the menu tethered to the button (may as well bring over some hits from the other place)

Jhey ʕ·ᴥ· ʔ reposted

Opportunities will appear in the place you dedicate your energy to. The results will not always be immediate but dedication and perfecting whatever your craft is and showing up publicly does lead to new doors. You have to show up how you want to be perceived though.

responsive CSS pinned sidebar transition 📌 .layout:has(:popover-open) { grid-template-columns: var(--sidebar-width) 1fr; } aside:popover-open { translate: 0 var(--ctrl); height: var(--extend); } actual zero JS for the layout transition here so many details to play with! 🧑‍🍳

cursor tracking on 3D CSS surfaces 👨‍🍳 inverse projection mappin' to calculate proximity in 3D space and apply an eased 0-1 value 🤙 the key: measuring the 4 corners, check the reveal 👇 (ideal for 2D canvas w/ 3D transforms)

little details: hold to confirm signature ✍️ signature playback mirrors the timing of your strokes not just what you drew, but how you drew it, retaining the feel and personality

SVG filters provide a basic lighting system you can sync with a little JavaScript and use in your web apps 💡 ... not as powerful as MacOS implementation but pretty cool

CSS picture-in-picture video transition using container queries + position: sticky 🧑‍🍳 .container { container-type: scroll-state; } @​container scroll-state(stuck: top) { video { translate: calc(50vw - 100%) calc(100vh - 100%); } }

no support? use a thin "sentinel" element that you watch with IntersectionObserver to toggle attribute styling 🤙 if (!CSS.supports('container-type: scroll-state')) { new IntersectionObserver(([e]) => { root.dataset.stuck = !e.isIntersecting }).observe(sentinel) }

dynamic toggle with CSS :has() 🎁 .control:not(:has(:first-of-type:checked)) .indicator { translate: 100% 0; } leverage [type=radio]:checked with :has() to set the visuals 🤙

<table> highlighting with CSS :has() 💡 td:has(~ td:hover), /* previous sibling cells */ table:has(td:nth-of-type(3):hover) /* column cells */ tr:not(:first-of-type):has(~ tr:hover) td:nth-of-type(3) { background: var(--highlighted); }