Video wird geladen...

Video konnte nicht geladen werden

Zur Startseite

CSS sidebar tricks 🤌 transition expanded menu items to "auto" height using grid li > div[inert] { grid-template-rows: 0fr; } li > div { grid-template-rows: 1fr; transition: grid-template-rows .3s; }

117,489 Aufrufe • vor 1 Jahr •via X (Twitter)

10 Kommentare

Profilbild von Pavel Ivanov
Pavel Ivanovvor 1 Jahr

yeah :) I use something close to this in react-scan! The old min/max-height hacks are no more!

Profilbild von jhey ▲🐻🎈
jhey ▲🐻🎈vor 1 Jahr

yeah - solid solution until we get decent support for interpolate-size 🙏

Profilbild von MGSimard
MGSimardvor 1 Jahr

Oh man inert is a thing? yoink

Profilbild von jhey ▲🐻🎈
jhey ▲🐻🎈vor 1 Jahr

yep!🤙 so good for things where you need to hide from AT etc. but don't really want to use display none

Profilbild von Arthur
Arthurvor 1 Jahr

Bro is working on Vercel itself...

Profilbild von jhey ▲🐻🎈
jhey ▲🐻🎈vor 1 Jahr

🫡

Profilbild von Diogo
Diogovor 1 Jahr

Didn't know about this inert attribute. Cool.

Profilbild von jhey ▲🐻🎈
jhey ▲🐻🎈vor 1 Jahr

super useful 💯 being able to hide things without juggling display none makes transitions so much easier 🙌

Profilbild von Roo and Sashas Happy Days
Roo and Sashas Happy Daysvor 1 Jahr

how does inert effect accessibility when using keyboard with these buttons

Profilbild von Typzo
Typzovor 1 Jahr

Probably one of the best tricks grid has to offer!

Ähnliche Videos

CSS Tip! 🎠 You can create a responsive infinite marquee animation with container queries and no duplicate items 🤙 li{ animation: slide; } @​keyframes slide { to { translate: 0% calc(var(--i) * -100%);}} The trick is animating the items, not the list 😎 More tricks 👇 To get this one working, you need to animate the items and not the list (Watch the video first?). Each item needs to know its row index (--i) in the list and the parent needs to know how many rows are in the list: ul { --count: 12; } li:nth-of-type(1), li:nth-of-type(2) { --i: 0; } li:nth-of-type(3), li:nth-of-type(4) { --i: 1; } Once you have that, translate each item based on its row index in the list li { translate: 0% calc((var(--count) - var(--i)) * 100%); } Now for the animation. The key here is that each row has an animation-delay calculated from its index (--i). That number is offset to make it negative so the animation start is offset ✨ ul { --duration: 10s; } li { --delay: calc((var(--duration) / var(--count)) * (var(--i) - 8)); animation: slide var(--duration) var(--delay) infinite linear; } Make sure to wrap that animation in: @​media (prefers-reduced-motion: no-preference) { ... } Lastly, the fun parts! 🤓 To create the "vignette" mask. Use a layered mask on the container 😷 .scene { --buff: 3rem; height: 100%; width: 100%; mask: linear-gradient(transparent, white var(--buff) calc(100% - var(--buff)), transparent), linear-gradient(90deg, transparent, white var(--buff) calc(100% - var(--buff)), transparent); mask-composite: intersect; } To create the 3D skewed effect, use a chained transform (Try toggling it in the demo ⚡️): .grid { transform: rotateX(20deg) rotateZ(-20deg) skewX(20deg); } As for the responsive part, use container queries! 🔥 article { container-type: inline-size; } When the article (card) is narrower than 400px update the grid and animation settings 🤙 Double the rows means double the duration! @​container (width < 400px) { .grid { --count: 12; grid-template-columns: 1fr; } li:nth-of-type(1) { --i: 0; } li:nth-of-type(2) { --i: 1; } li:nth-of-type(3) { --i: 2; } li:nth-of-type(4) { --i: 3; } li { --duration: 20s; } } CSS has the magic to be able to update those animations at runtime based on your custom property values 😎 An added bonus in this demo is that it doesn't require any JavaScript at all, for any of it 🤯 We can use CSS :has() for those toggles that update the styles, even the theme toggle! 🫶 Any questions, let me know! Make sure to check out the video. Will do a walkthrough one to follow-up 🤙 CodePen.IO link below! 👇

jhey ʕ•ᴥ•ʔ

542,159 Aufrufe • vor 2 Jahren

As part of my assignment, I was tasked with designing a high-density data grid for an SEO platform. During development, our analysis of Google Analytics data revealed that the majority of our users access the platform on 13-inch display laptops. This insight necessitated optimizing the data grid for this screen size. A key challenge we encountered was the sidebar housing keyword filters, which occupied a significant portion of the available space. Since this feature was integral to the page, removing it was not an option. Even making it collapsible would have had minimal impact on the overall layout. Our initial approach involved implementing an inner horizontal scroll to accommodate additional columns. However, this solution introduced technical limitations due to the grid’s accordion UI pattern, which enables users to expand rows for detailed views. This functionality effectively split the table in half, making it difficult to synchronize scrolling across two separate grid sections within modern browsers. To address these constraints, I devised an alternative solution: implementing auto-expandable and collapsible columns based on content visibility. For instance, the "Flag" and "Performance" columns dynamically collapse by default and expand when hovered over, allowing users to access the necessary details when needed. This approach enabled us to fit all columns within a 13-inch display without relying on horizontal scrolling, ensuring a more efficient and user-friendly experience.

virgil pana

44,560 Aufrufe • vor 1 Jahr

CSS Tip! 🍬 You can create a CSS-only sticky CTA using position: sticky or scroll-driven animations 🤙 .cta { position: sticky; margin-top: 110vh; bottom: 2rem; /* 👈 Stick! */ } This is one way 👀 This first way relies on you setting a layout on the body and putting the CTA in a zero-space part of the layout body { display: grid; grid-template-columns: auto 0; } The children of the body are an element with your content and then the CTA. You could also use display:flex too. .content { flex: 1 0 100%; } .cta { place-self: end; } As you scroll the body, the CTA comes into view and sticks in position 🙌 That's one way. If you want to take it further and do something like flip between showing or not, maybe scale it up, or add some special easing, etc. an animation is another way 📜 First, change the styles for your CTA. Note the translate property that's powered by a custom property .cta { position: fixed; bottom: 2rem; right: 2rem; translate: 0 calc(20vh - (var(--show) * 20vh)); transition: translate 0.875s var(--elastic); } Next you need a custom property that you're going to animate @​property --show { inherits: true; initial-value: 0; syntax: ' '; } Lastly, you animate this value on the body. As the property value changes, the value will trickle down to the CTA @​supports (animation-timeline: scroll()) { body { animation: show-cta both steps(1); animation-timeline: scroll(root); animation-range: 0 10vh; } @​keyframes show-cta { to { --show: 1; } } } Using @​supports you can use this as a progressive enhancement. If scroll-driven animations are supported, use them. Otherwise fallback to using position: sticky 🤙 That's it! As always, any questions or requests, hit me up! 🙏 CodePen.IO link below! 👇

jhey ʕ•ᴥ•ʔ

133,020 Aufrufe • vor 2 Jahren

CSS Trick 🤙 You can create these tab bar controls by using :has() to count the number of tabs ⭐️ .tabs:has(input:nth-of-type(3)){--count: 3;} .tabs:has(:checked:nth-of-type(3)){--active: 200%;} .tabs::after{ translate:var(--active) 0;} Let's break it down in this ! 📼 Couple of CSS :has() tricks here combined with custom properties 😎 First things first, lay out the tabs using display: grid. This gives you a way to create equal-width tabs 🙏 .tabs { display: grid; grid-auto-flow: column; } Then you use :has() to count the number of tabs and store that in a custom property 🤓 .tabs:has(input:nth-of-type(3)) { --count: 3; } .tabs:has(input:nth-of-type(4)) { --count: 4; } Using the cascade, the last valid :has() gives you the number of tabs 🫶 Using the tab count, you can size the tab indicator. For the tab indicator, use the tabs pseudoelement: .tabs::after { content: ""; position: absolute; height: 100%; width: calc(100% / var(--count)); } See how you can use --count to determine its size 📏 Next, use :has() to determine which tab is active or :checked with input [type=radio] .tabs:has(:checked:nth-of-type(2)) { --active: 1; } .tabs:has(:checked:nth-of-type(3)) { --active: 2; } You can use a zero-indexed translation here. If the second input is :checked, set --active: 1, then translate the pseudoelement on the tabs to that position 👉 .tabs::after { translate: calc(var(--active, 0) * 100%) 0; } Or you could set active to the translation: .tabs:has(:checked:nth-of-type(2)) { --active: 100%; } Setting the custom property allows you to use the index elsewhere if you need it 🤙 The final piece is using mix-blend-mode 👀 The tabs have a black background-color, the pseudoelement is white, and the label text is white. When you use mix-blend-mode: difference on the pseudoelement it will give this effect that the text transitions from white to black sliding across 😎 .tabs::after { color: hsl(0 0% 100%); mix-blend-mode: difference; } You can totally mix up the colors here though and go with a different effect. The mechanics of how you can use CSS :has() is the main point here 🙏 As always, any questions, suggestions, etc. let me know CodePen.IO link below! 👇 (There's even a Tailwind CSS play for this one too 👀)

jhey ʕ•ᴥ•ʔ

70,730 Aufrufe • vor 2 Jahren

CSS Tip! 💫 You can create this responsive perspective warp animation with 3D CSS and container queries ✨ (Video reveals trick 👀) .warp { container-type: size; perspective: 100px; transform-style: preserve-3d; resize: both; overflow: hidden; } Couple of tricks in this one 🤓 The main idea is to create a tunnel (an open-ended cube). On each side of the tunnel, use linear-gradient to create the grid lines ✨ .side { background: linear-gradient(#​fff 0 1px, transparent 1px 5%) 50% 0 / 5% 5%, linear-gradient(90deg, #​fff 0 1px, transparent 1px 5%) 50% 50% / 5% 5%; } To position each side, you rotate on the x-axis by 90deg. Each side would become invisible at this point. So you give the scene perspective 😉 .warp__side--top { width: 100cqi; height: 100cqmax; transform-origin: 50% 0%; transform: rotateX(-90deg); } The cool part here is that you want to make each side the same height. But the container is responsive. So you can use a container query and make sure each side is 100cqmax tall 🫶 Then the "beams". Each side contains "beams". They have different colors, sizes, and positions, and move at different speeds ⚡️ We can control that through scoped custom properties. .beam { width: 5%; position: absolute; top: 0; left: calc(var(--x, 0) * 5%); aspect-ratio: 1 / 2; background: linear-gradient( hsl(var(--hue) 80% 60%), transparent ); translate: 0 100%; animation: warp calc(var(--speed, 0) * 1s) calc(var(--delay, 0) * -1s) infinite linear; } The magic here is though that a beam's animation is as basic as translating it from the top of the side to the bottom. And you can get that distance with a container query again 🔥 @​keyframes warp { 0% { translate: -50% 100cqmax; } 100% { translate: -50% -100%; } } And that is pretty much it! A cool warp animation effect using 3D CSS and container queries ⚡️ If you have any questions, let me know ᵔᴥᵔ CodePen.IO link below! 👇

jhey ʕ•ᴥ•ʔ

187,474 Aufrufe • vor 2 Jahren

CSS Tip! 🤯 You can create a CSS-only version of this balance slider using a scroll animation on the underlying input[type=range] 🚀 ::-webkit-slider-thumb { view-timeline: --thumb inline; } Scroll animation driven by the slider thumb animates a number between the "min" and "max" of the range 😅 @​property --value { inherits: true; initial-value: 0; syntax: ' '; } @​keyframes sync { to { --value: 100; }} Tie that up to the contain animation-range ⚡️ .control { animation: sync both linear reverse; animation-timeline: --thumb; animation-range: contain; } Hoist the view timeline so all the parts of the control can use it! .control { timeline-scope: --thumb; } Use that value in a counter which is used for the labels. Create a low and a high for each side 😇 .control__label { counter-reset: low var(--value) high calc(100 - var(--value)); } .control__label::before { content: "COFFEE " counter(low) "%"; } .control__label::after { content: counter(high) "% MILK"; } That's the magic of updating the label values ✨ For the big track, it's a fake track. You can make use of the same --value property and do some calc() to work out the width of each part. .control__track::before { width: calc(var(--value) * 1% - 0.5rem); background: var(--coffee); border-radius: 4px; transition: width 0.1s; } The width leaves a little gap for the indicator piece 🤙 The color calculation for --coffee isn't too wild but again you can use the same --value .control__track { --coffee: hsl(24 74% calc( 24% + (30% * ((100 - var(--value, 0)) / 100)) / 1 ) / 0.4); } Now for the last piece. Making the track change height. You could set up another custom property and animate its value using the --thumb timeline too 🔥 @​property --shift { initial-value: 0; inherits: true; syntax: ' '; } @​keyframes shift { 0%, 31%, 61%, 100% { --shift: 0; } 32%, 60% { --shift: 1; } } Then use that --shift to update the translation of the label and height of the track 🤓 .label { transform: translateY(calc(var(--shift) * 50%)); transition: transform var(--speed) var(--timing); } Cool part here is that you can use the control to work out the @​keyframes percentages 😅 Oh. And the timing for that little bounce? Use the linear() function 😎 :root { --timing: linear( 0, 0.5007 7.21%, 0.7803 12.29%, 0.8883 14.93%, 0.9724 17.63%, 1.0343 20.44%, 1.0754 23.44%, 1.0898 25.22%, 1.0984 27.11%, 1.1014 29.15%, 1.0989 31.4%, 1.0854 35.23%, 1.0196 48.86%, 1.0043 54.06%, 0.9956 59.6%, 0.9925 68.11%, 1 ); } Should probably do a video on this one. Lots of little custom property tricks for sure! 💯 It's not too far off the range slider with the tooltip that came up previously As always, any questions, let me know! Also, this one only works in Chrome currently ✅🥲 This one's a bit rocket science ha 🚀 CodePen.IO link below! 👇

jhey ʕ•ᴥ•ʔ

377,586 Aufrufe • vor 2 Jahren

CSS Tip! 💪 You can create these tab controls with CSS :has() + radio buttons ✨ .tabs:has(input:nth-of-type(3)) { --count: 3; } .tabs:has(:checked:nth-of-type(3)) { --active: 2; } .tabs::after { translate: calc(var(--active, 0) * 100%) 0; width: calc(100% / var(--count)); } Two CSS :has() tricks here combined with a rendering trick 🤙 The tab control is a container using display: grid. You can use :has() to count the number of tabs in the container: .tabs:has(input:nth-of-type(3)) { --count: 3; } .tabs:has(input:nth-of-type(4)) { --count: 4; } Using the cascade, the last valid :has() gives you the number of tabs 🫶 Once you know the number of tabs, you know how to size the indicator: .tabs::after { content: ""; position: absolute; height: 100%; width: calc(100% / var(--count)); } It's a pseudoelement that uses --count to determine its size 📏 The next :has() trick is determining which tab is active or :checked as it's an input [type=radio] .tabs:has(:checked:nth-of-type(2)) { --active: 1; } .tabs:has(:checked:nth-of-type(3)) { --active: 2; } You can use a zero-indexed translation here. If the second input is :checked, set --active: 1, then translate the pseudoelement on the tabs to that position 👉 .tabs::after { translate: calc(var(--active, 0) * 100%) 0; } The last rendering trick is using mix-blend-mode 👀 The tabs have a black background-color, the pseudoelement is white, and the label text is white. When you use mix-blend-mode: difference on the pseudoelement it will give this effect that the text transitions from white to black sliding across 😎 .tabs::after { color: hsl(0 0% 100%); mix-blend-mode: difference; } You can totally mix up the colors here though and go with a different effect. The mechanics of how you can use CSS :has() is the main point here 🙏 As always, any questions, suggestions, etc. let me know CodePen.IO link below! 👇 (There's even a Tailwind CSS play for this one too 👀)

jhey ʕ•ᴥ•ʔ

437,426 Aufrufe • vor 2 Jahren

How I turn my templates into real landing pages. Works for any vibe coding platform or site. This is my full guide. I start with Gemini 3. I copy the HTML code and paste to Cursor/v0/lovable and prompt "Create a new landing page /page-name using this design but adapted to {site_name}. Replace the header and footer with the ones from my site. Adapt the whole page, keep everything: {HTML_code}" Details that can to be adapted or improved: Fonts: "Use {font_name} Google font for headings and {font_name} for body text." Icons: "Use Iconify {icon_set} icons" Colors: "Change primary color to blue. Everything else should be monotone." Bonus: "Make the outlines subtle" for a cleaner design. Animation intro/on scroll: "Animate when in view observed, fade in, slide in, blur in, element by element. Use 'both' instead of 'forwards'. Don't use opacity 0." Static to animated: "Animate details with {animate_type} and decorations.". Example types: line, beam animation, noodles, grid, sonar, etc. Background animation: "Apply the background animation using Unicorn Studio {animation_code}" Details to make your layout stand out: "Add vertical container-size lines. Add 01 02 03 number details." Stand out from generic-looking: "Make this more upscale with large tall fonts, Newsreader font and black and white agency". Adapt content: "Adapt the content to {copy and paste site texts}". Buttons: "Change main button to {code}. Add a 1px border beam animation around the pill-shaped button on hover." Adding sections like testimonials: "Adapt a new section after {section} using this code: {component code}". You can copy the code from Codepen, 21st dev or Aura. Responsiveness: "Make this responsive. Add a hamburger menu for mobile. Hide this {element} for mobile." Making forms work: "Make the form send an email to {your_email}". Payments: "Link the buy button to {LemonSqueezy payment link}". I use composer-1 for quick fixes. I finish with Claude Opus 4.5 for code reviews "Please review the code for performance and robustness". The template HTML code should give you a blueprint for all these, but I think it's important to keep iterating for your specific site.

Meng To

41,015 Aufrufe • vor 7 Monaten

THE FACES ARE FAKE: Riccardo Bosi on the World Leaders Who Were Replaced FULL SHOW HERE: Look at a photograph of your national leader today. Now look at one from five years ago. They're not the same people. In this monologue, Riccardo Bosi reveals the hidden reality behind the global transition: the worst of the world's leaders were taken out years ago—replaced by actors, compromised puppets, or terrified figureheads doing what they're told. The average punter can't see it. But the white hats have been systematically decapitating the cabal's control grid while leaving familiar faces in place to maintain the illusion of continuity. Bosi pulls back the curtain on the strategy: Israel isn't run by Bibi Netanyahu—it's run by white hats. The real Bibi is a man named Ben Solomon who actually runs Saudi Arabia. Keir Starmer says stupid things because he's been told to say stupid things. The national leaders people believe are running the show are nothing more than actors in a TV series—one that's entering its final season. The war itself is reversed. Instead of grinding through waves of soldiers and stripping nations of their manhood, the white hats decapitate the leadership while leaving the machinery of governance intact. You can't replace an entire country's judiciary, constabulary, military, and bureaucracy overnight. You cut off the head and leave the body in place—under new direction. Venezuela is the model. Maduro is gone. His deputy remains, and the Venezuelan people see familiar faces while the tyranny evaporates. The same template applies globally. The war for the planet is won. The rats in the corner remain. But the world you knew is gone—and the one being born is built for you to stand on your own two feet. NOTICE: Many frauds weigh in as me (JMC). I NEVER promote or sell any QFS, Crypto, wallets etc. These people are reported as fraud and are banned, but new ones crop up every week. FOR MORE AMAZING JMC PROGRAMMING LIKE THIS, VIEW OUR FULL SCHEDULE HERE: 🚨 The Global Financial Reset Is HERE. 🚨 Don't just survive it—PROFIT from it. This is your gateway to explosive growth with Genesis Metals. 👉 CLICK NOW: BECOME A PREMIUM MEMBER TODAY! - Free Subscription BECOME A PREMIUM MEMBER: Visit for guaranteed income you cannot outlive! ALL NEW RUMBLE CHANNEL! SUBSCRIBE SO YOU DON’T MISS ANYTHING! Follow JMC Here NOTICE: Many frauds weigh in as me (JMC). I NEVER promote or sell any QFS, Crypto, wallets etc. These people are reported as fraud and are banned but new ones crop up every week.

JMC Broadcasting

28,486 Aufrufe • vor 3 Monaten