> All in One 586

Ads

Thursday, December 4, 2025

Mostly Clear today!



With a high of F and a low of 18F. Currently, it's 19F and Clear outside.

Current wind speeds: 9 from the Southwest

Pollen: 0

Sunrise: December 4, 2025 at 07:55PM

Sunset: December 5, 2025 at 05:28AM

UV index: 0

Humidity: 92%

via https://ift.tt/jZD8hFv

December 5, 2025 at 10:02AM

Getting Creative With “The Measure”

I spend an unhealthy amount of time on the typography in my designs, and if you’ve read any traditional typography books, you might remember “the measure.” If not, it’s simply the length of a line of text. But measure means more than that, and once you understand what it represents, it can change how you think about layout entirely.

But why’s it called the measure?

Closeup photo of a hand holding a metal type template for lettering.
Photo: Wilhei, via Wikipedia (CC BY 3.0)

Before desktop publishing, typesetters worked with physical metal type. They set lines of text within a composing stick, and the width of the stick was called the measure. It was literally the space you could fit type into, and everything else on the page — from column widths to margins and gutters — was designed around it.

A good measure makes reading text comfortable, while a bad one makes it more difficult.

A heading and three paragraphs of text in white against a black background.
An uncomfortable measure makes reading more difficult. See this example in my lab.

And when the measure is correct, the rest of the layout falls into place. So, rather than allowing layout to dictate the measure, doesn’t it make more sense for the measure to inform layout decisions?

Turning the measure into a custom property

In my CSS, I start by defining a custom property:

:root {
  --measure: 60ch;
}

ch units are ideal for this because they relate to the width of the zero (0) character in a chosen font. Somewhere between 60–70 characters per line is a comfortable reading length, so 65 characters feels natural.

60ch is a solid starting point, but it isn’t universal. Different typefaces produce different real-world line lengths, even when the character count stays the same. Typefaces with a large x-height appear visually larger, so 60ch can feel longer than it really is. Condensed faces make 60ch feel too short. Wider faces can make it feel too long. Even small tracking changes stretch or compress the perceived measure.

The point is simple: treat 60ch as a baseline, then adjust by eye. Once the measure becomes a variable, you can use it across your layout to keep everything connected.

Keeping text readable

I suspect most developers have used the max-width property. Although it took time to retrain my muscle memory, I now use CSS logical properties, replacing max-width with max-inline-size:

article {
  max-inline-size: var(--measure);
  margin-inline: auto;
}
A heading and three paragraphs of text in a white contained in a narrow column against a black background.
Well considered measure makes reading more comfortable. See this example in my lab.

That prevents long-line syndrome, which afflicts too many websites when viewed on large screens.

Designing multi-column text

Multi-column layout is one of the most underrated CSS layout tools. Instead of specifying the number of columns, defining the column width lets the browser decide how many columns fit along the inline axis. The measure can also define the widths of those columns:

article {
  column-width: var(--measure);
}
A heading and three paragraphs of text in white against a background and split into two equal-sized columns.
The measure can define multi columns widths. See this example in my lab.

When the columns’ parent container becomes wide enough, a browser flows text into as many readable columns as will fit. When there’s not enough space for multiple columns, the layout falls back to a single column, all without breakpoints and media queries.

Letting the measure influence a grid

The measure also helps me design grids which feel connected to my content. For example, when I’m implementing a layout with a column containing long-form content, plus another flexible column, I can lock the text content to the measure:

.layout {
  display: grid;
  grid-template-columns: minmax(0, var(--measure)) 1fr;
}
A heading and three paragraphs of text in white against a black background on the left next to an image of a woman in a cowgirl hat and denim shirt staring directly ahead.
The measure also creates grids which feel connected to content. See this example in my lab.

That first column ensures that reading text remains comfortable, while the second adjusts to whatever horizontal space remains.

Measure-driven container queries

For years, developers learned to think of screen sizes in terms of specific breakpoints (320px, 48em, 64em, and so on) and media queries. It’s a hard habit to break and one which, to be honest, I haven’t always managed myself.

Those numbers don’t come from content; devices define them. They really should be called “guesspoints” because we mostly never know which numbers work for most people. Instead of dictating that a layout switches at, say, 48em and 64em, I can let my content decide when a layout should change by using the measure.

A heading and three paragraphs of text in white against a black background on the right. An image of a woman in cowgirl hat and denim shirt is staring straight ahead on the left.

Measure makes a better breakpoint. A measure-driven breakpoint, combined with container queries, responds to text content. So, when a column becomes narrower than a readable line length, a layout can collapse. But when it becomes wide enough to support more structure, the layout can expand.

A CSS container query checks the width of the component’s container instead of a screen or the viewport. For instance, when a component is narrower than 65 characters, I can apply specific styles:

/* When the container is no wider than the --measure */
@container (max-width: var(--measure)) {
  /* Styles */
}

My design might include multiple columns, perhaps a wider column for the main content and a narrower one for supporting information:

[data-layout="yogi"] {
  display: grid;
  grid-template-columns: 3fr 1fr;
}

If the container can’t support a text column equal to the measure, this query replaces the two columns with a single column layout:

@container (max-width: var(--measure)) {
  [data-layout="yogi"] {
    grid-template-columns: 1fr;
  }
}

This feels more natural because the composition is connected to the content rather than the device’s width, creating a comfortable reading environment.

Making a measure system

Depending on the variety of content I need to present, on certain projects, I define several variations of the measure:

:root {
  --measure: 60ch;
  --measure-s: 55ch;
  --measure-l: 80ch;
}

This gives me a variety of line lengths for use in different situations:

  • Small for captions and other shorter text blocks
  • Regular for body copy
  • Large for introductions, headings, and hero sections

When type, spacing, and layout all share the same underlying rhythm, the result can feel more coherent and more intentional.

Considering the measure can change how you design

When you design with the measure in mind, layout stops being guesswork and becomes a conversation between content and composition. Reading becomes more comfortable, and the page feels more deliberate. It’s a small shift, but once you start anchoring your design decisions to the measure, it changes how you approach layout entirely.

Further reading


Getting Creative With “The Measure” originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.



from CSS-Tricks https://ift.tt/da0tAHb
via IFTTT

Wednesday, December 3, 2025

Snow Showers Early today!



With a high of F and a low of 21F. Currently, it's 27F and Cloudy outside.

Current wind speeds: 5 from the Northeast

Pollen: 0

Sunrise: December 3, 2025 at 07:54PM

Sunset: December 4, 2025 at 05:28AM

UV index: 0

Humidity: 94%

via https://ift.tt/1T2NOyc

December 4, 2025 at 10:02AM

Tuesday, December 2, 2025

Snow Showers today!



With a high of F and a low of 24F. Currently, it's 34F and Showers in the Vicinity outside.

Current wind speeds: 4 from the North

Pollen: 0

Sunrise: December 2, 2025 at 07:53PM

Sunset: December 3, 2025 at 05:28AM

UV index: 0

Humidity: 53%

via https://ift.tt/0gVyCDK

December 3, 2025 at 10:02AM

Scrollytelling on Steroids With Scroll-State Queries

Read you a story? What fun would that be? I’ve got a better idea: let’s tell a story together.

Photopia by Adam Cadre

Do you think of scrolling as a more modern way of reading than turning pages in a book? Nope, the concept originated in ancient Egypt, and it’s older than what we now classify as books. It’s based on how our ancestors read ancient physical scrolls, the earliest form of editable text in the history of writing. I am Jewish, so I remember my earliest non-digital scrolling experience was horizontally scrolling the Torah, which can be more immersive than traditionally scrolling a webpage. The physical actions to navigate texts have captured the imagination of many a storyteller, leading authors to gamify the act of turning pages and to create stories that incorporate the physical actions of opening a book and turning pages as part of the narrative. However, innovative experiences using non-standard scrolling haven’t been explored as thoroughly.

Photo of an ancient scroll partially unrolled inside a glass case on a wooden desk.
Photo by Taylor Flowe on Unsplash

I can sympathize with those who dismiss scrollytelling as a gimmick: it can be an annoyance if it’s just for the sake of cleverness, but my favorite examples I’ve seen over the years tell stories we couldn’t otherwise. There’s something uniquely immersive about stories driven by a mechanic that has lived in our species’ collective muscle memory since ancient days.

Still unconvinced of the value of scrollytelling? Alright, hypothetical annoying skeptic, let’s first warm up with some common use cases for scroll-based styling.

It’s awesome that Chrome has solid support for native scroll-driven animations without requiring JavaScript, and we see that both Safari and Firefox are actively working on support for the new scroll-driven standards. These new features facilitate optimized, smooth scroll-driven animations. The support via pure CSS syntax makes scroll-driven animation a more approachable option for designers who may be more comfortable with CSS than with the equivalent JavaScript.

Indeed, even though I am a full-stack developer who is supposed to know everything, I found having scroll-driven animation built into the browser and available with a few lines of CSS gets my creativity flowing, inspiring me to experiment more than if I had to go through hoops of a proprietary library and writing JavaScript, which in the past might include messing with intersection observer and fiddly code.

If animation timelines weren’t enough, Chrome has now introduced support for CSS carousel, scroll-initial-target, and scroll-state queries—all of which provide opportunities to control scrolling behaviors in CSS and style all the things based on scrolling.

In my opinion, scroll-state is more of an evolutionary than revolutionary addition to the growing range of scroll-related CSS features. Animation timelines are so powerful that they can be hacked to achieve many of the same effects we can implement with scroll-state queries. Therefore, think of scroll-state as a highly convenient, simplified subset of what we can do in more verbose hacky ways with animation timelines and/or view timelines.

Some examples of effects scroll-state simplifies are:

  1. Before scroll-state queries existed, you could hack view progress timelines to create scroll-triggered animations, but we now have snapped scroll-state queries to achieve similar effects.
  2. Before snappped queries existed, Bramus demonstrated a hack to simulate a hypothetical :snappped selector using scroll-driven animations.
  3. Before scrollable queries existed, Bramus showed how we could do similar things using scroll-timeline.

Take a moment to appreciate that Bramus is from the future, and to reflect on how scroll-state can simplify common UI patterns, such as scroll shadows, which Chris Coyier said might be his “favorite CSS trick of all time.” This year, Kevin Hamer showed how scroll-timeline can achieve scroll shadows in CSS with fewer tricks. It’s excellent, but the only thing better than clever CSS tricks is that scroll shadows no longer require a trick at all. Hacking CSS is fun, but there is something to be said for that warm fuzzy feeling that CSS was made just for your use case. This demo from the Chrome blog shows how scroll shadows and other visual affordances are easy to implement with scroll-state.

But the popularity of Kevin’s article suggests that normal, sane people will gravitate to practical use cases for the new CSS scroll-based features. In fact, a normal and sane author might end the article here. Unfortunately, as I revealed in a previous article, I have been cursed by a spooky shopkeeper who sells CSS tricks at a haunted carnival, so I now roam the earth attempting the unthinkable with pure CSS.

Decision time

As you reach this paragraph in the article, you realize that when you scroll, it fast-forwards reality. Therefore, after we end the discussion of scroll shadows, the shadows swallow the world outside your window, except for two glowing words hovering near your house: CSS TRICKS. You wander out through your front door and meet a street vendor standing beneath the neon sign. The letters give her multiple shadows as if she has thrown them down like discarded masks, undecided about which shade of night to wear. On the table before her lies a weathered scroll. It unrolls on its own, whispering misremembered fragments from a forgotten CSS-Tricks article: “A scroll trigger is a point of no return, like a trap sprung once the hapless user scrolls past a certain point.”

The neon flickers like a glitch, revealing another of the shopkeeper’s faces: a fire demon doppleganger of yourself who is the villain of the CodePen we’ll descend into if you scroll further.

“Will you continue?” the fire demon hisses. “Will you scroll deeper into the madness at the far edges of CSS?

Non-linear scrollytelling

Evidently, you are game to play with fire, so check out the pure CSS experiment below, which demonstrates a technique I call “nonlinear scrollytelling,” in which the user controls the outcome of a visual story by deciding which direction to scroll next. It’s a scrolling Choose Your Own Adventure. But if your browser is less adventurous than you are, watch the screen recording instead. The experiment will only work on Chromium-based browsers for now, because it relies on scroll-state, animation-timeline, scroll-initial-target and CSS inline conditionals.

I haven’t seen this technique in the wild, so let me know in the comments if you have seen other examples of the idea. For now, I’ll claim credit for pioneering the mechanics — but I give credit to the talented Dead Revolver for creating the awesome, affordable pixel art bundle I used for most of the graphics. The animated lightsaber icon was ripped from this cool CodePen by Ujjawal Anand, and I used ChatGPT to draw the climbable building. To make the bad guy, I reused the same spritesheet from the player character, but I implemented the Mirror Match trope from Mortal Kombat, using color shifting to create a “new” character who I evilized by casting the following spell in CSS:

.evil-twin {
  transform: rotateY(180deg);
  filter: invert(24%) sepia(99%) saturate(5431%) hue-rotate(354deg) brightness(93%) contrast(122%);
  background-image: url(/* same spritesheet as the player character */);
}

It’s cool that CSS helps recycle existing assets for those like me who are drawing-challenged. I also wanted to make sure that well-supported CSS features like transform and filter didn’t feel left out of the fun in an experiment filled with newer, emergent CSS features.

But if you’ve come this far, you’re probably eager to understand the scroll-related CSS logic.

Our story begins in the middle of the end

You may have noticed our experiment earns extra crazy points as soon as it loads, by starting at the middle of the bottom of the page so that the player can choose whether to scroll left to run away, or scroll right to walk unarmed towards the bad guy if the player wants to compete with the madness level of the game’s creator.

This explainer for the emergent scroll-initial-target property shows that controlling scroll position on load was previously possible by hacking CSS animations and the scroll-snap-align property. However, similar to what we discussed above about the value proposition of scroll-state, a feature like scroll-initial-target is exciting because it simplifies something that previously required verbose, fragile hacks, which can now be replaced with more succinct and reliable CSS:

.spawn-point {
  position: absolute;
  left: 400vw;
  scroll-initial-target: nearest;
}

As cool as this is, we should only subvert expectations for how a webpage behaves if we have a sufficient reason. For instance, CSS like the above could have simplified my pure CSS swiper experiment, but Chrome only added scroll-initial-target in February 2025, the month after I wrote that article. Using scroll-initial-target would be justified in the swiper scenario, since the crux of that design was that the user started in the middle with the option to swipe left or right.

A similar dilemma is central to the opening of our scrollytelling narrative. The disorienting experience of finding ourselves in an unexpected scroll position with only the option to scroll horizontally heightens the drama, as the user has to adapt to an unusual way of interacting while the bad guy rapidly approaches. I’m feeling generous, so let’s give the user 20 seconds to figure it out, but you can experiment with different timeframes by editing the --chase-time custom property at the top of the source file.

We’re going to create a CSS implementation of the slasher movie trope in which a walking aggressor can’t be outrun. We do that by marking the bad guy as position: fixed, then adding an infinite walk-cycle animation and another animation that moves him relentlessly from right to left across the screen. Meanwhile, we give the player character a running animation and position him based on a horizontal animation timeline. He can run, but he can’t hide.

body {
  .idle {
    animation: idleAnim 1s steps(6) infinite;
  }

    /* --scroll-direction is populated using the clever property Bramus demonstrates 
  here https://www.bram.us/2023/10/23/css-scroll-detection */

  .sprite {
    transform: rotateY(calc(1deg * min(0, var(--scroll-direction) * 180)));
  }

  @container not style(--scroll-direction: 0) {
    .sprite {
      animation: runAnim 0.8s steps(8) infinite;
    }
  }

  .evil-twin-wrapper {
    position: fixed;
    bottom: 5px;
    z-index: 1000;
    margin-left: var(--enemy-x-offset);
    /* we'll explain later how we detect the way the game should end */
    --follow: if(style(--game-state: ending): paused; else: running); 
    animation: var(--chase-time) forwards linear evil-twin-chase var(--follow);
  }
}

He can’t hide, but we’ll next introduce a second scroll-based decision point using scroll-state to detect when our hero has been backed into a corner and see if we can help him.

How scroll-state could save your life

As our hero runs away to the left, the buildings and sky in the cityscape background show off a few layers of parallax scrolling by assigning each layer an anonymous animation timeline and an animation that moves each layer faster than the layer behind it.

.sky, .buildings-back, .buildings-mid, .sky-vertical, .buildings-back-vertical, .buildings-mid-vertical {
  position: fixed;
  top: 0;
  left: 0;
  width: 800%;
  height: max(100vh, 300px);
  background-size: auto max(100vh, 300px);
  background-repeat: repeat-x;
  animation-timing-function: linear;
  animation-timeline: scroll(x);
}

/*...repetitively assign the corresponding animations to each layer...*/

@keyframes move-sky {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-2.5%);
  }
}

@keyframes move-back {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-6.25%);
  }
}

@keyframes move-mid {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-12.5%);
  }
}

This usage of animation timelines is what they were designed for, which is why the code is straightforward. If we had to, we could push the boundaries and use the same technique to set a Houdini variable in an animation timeline to detect when the player reaches the left corner of the screen — but thanks to scroll-state queries, we have a cleaner option.

@container scroll-state((scrollable: left)) {
  body {
    overflow-y: hidden;
  }
}

@container scroll-state((scrollable: bottom)) {
  body {
    width: 0;
  }
}

That’s all we need to toggle vertical and horizontal scrolling based on position! This is the basis that allows the player to escape from being slashed by the bad guy. Now we can scroll up and down to climb the ladder only when the player reaches the left corner where the ladder is, and disallow horizontal scrolling while he is climbing.

I could have made the game detect reaching the left of the screen using animation timelines, but that would involve custom property toggles, which are more verbose and error-prone.

When the player climbs to the top of the ladder to collect the lightsaber, we do need one toggle property so the game will remember we have collected the weapon, but it’s simpler than if we had used animation timelines.

@keyframes collect-saber {
  from {
    --player-has-saber: false;
  }
  to {
    --player-has-saber: true;
  }
}

body {
  animation: .25s forwards var(--saber-collection-state, paused) collect-saber;
}

@container scroll-state(not (scrollable: top)) {
  body {
    --saber-collection-state: running;
  }
}


@container style(--player-has-saber: true) {
  .sprite {
    background-image: url(/*combat spritesheet*/);
  }

  .lightsaber {
    visibility: hidden;
  }
}

Contrariwise, the animation cycle while the sprite is climbing the ladder is a job for animation-timeline used to assign an anonymous vertical timeline to the player sprite. This is applied conditionally when our scroll-state query detects that the player is between the bottom and the top of the ladder. It’s a nice example of how animation timelines and scroll-state queries are good at different things, and work well together.

@container scroll-state((scrollable: top) and ((scrollable: bottom))) {
  .player-wrapper {
    .sprite {
      animation: climbAnim 1s steps(8);
      animation-timeline: scroll(root y);
      animation-iteration-count: 10;
    }
  }
}

Finish him with fatal conditionality

We apply the techniques I discovered in my CSS collision detection article to detect when the two characters meet for their showdown. At that point, we want to disable scrolling entirely and display the appropriate non-interactive endgame cutscene depending on the choices our user made. Notice that if we detect the good guy won, he only strikes with the sword once, whereas the bad guy will continue to slash infinitely, even after the good guy is dead. What can I say — I was working on this CodePen around Halloween.

In the past, I wrote an article questioning the need for inline CSS conditionals — but now that they’ve landed in Chrome, I find them addictive, especially when creating a heavily conditional CSS experiment like nonlinear scrollytelling. I like to imagine that the new if() function stands for Interactive Fiction. Below is how I detect the endgame conditions and choose which animations to play in the final cutscene. I am not sure of the most readable way to space out if() code in CSS, so feel free to start holy wars on that topic in the comments.

body {
  --min-of-player-and-enemy-x: min(var(--player-x-offset), var(--enemy-x-offset) - 10px);
  --max-of-player-and-enemy-y: max(var(--player-y-offset, 5px));
  --game-state:
    if(
      style(--min-of-player-and-enemy-x: calc(var(--enemy-x-offset) - 10px)) and style(--max-of-player-and-enemy-y: 5px): 
        ending; 
      else: 
        playing
    );
  overflow:
    if(
      style(--game-state: ending): 
        hidden; 
      else: 
        scroll
    );
}

@container style(--player-has-saber: true) and style(--game-state: ending) {
  .player-wrapper {
    .sprite {
      animation: attack 0.7s steps(4) forwards;
    }

  .speech-bubble {
    animation: show-endgame-message 3s linear 1s forwards;

    &::before {
      content: 'Refresh the page to play again';
    }
  }
    
  .evil-twin-wrapper {
    .evil-twin {
      evil-twin-die 0.8s steps(4) .7s forwards;
    }
  }
}

@container style(--player-has-saber: false) and style(--game-state: ending) {
  .player-wrapper {
    .sprite {
      animation: player-die .8s steps(6) .7s forwards;
    }
  }

  .evil-twin-wrapper {
    .speech-bubble {
      animation: show-endgame-message 3s linear 1s forwards;
      display: block;

      &::before {
        content: 'Baha! Refresh the page to fight me again';
      }
      .evil-twin {
        attack 0.8s steps(4) infinite;
      }
    }
  }
}

Should we non-linearly scrollytell all the things?

I am glad you asked, hypothetical troll who wrote that heading. Of course, even putting the technical challenges aside, you know that this won’t always be the right approach for a website. As Andy Clarke recently pointed out here on CSS-Tricks, design is storytelling. The needs of every story are different, but I found my little pixel art guy’s emotional story arc requires non-linear scrollytelling.

I think this particular example isn’t a gimmick and is a legitimate form of web design expression. The demo tells a simple story, but my wife pointed out that a personal situation I am dealing with has strong analogies to the pixel guy’s journey. He finds himself in a situation where the only sane option is to allow himself to be backed into a corner, but when all seems lost, he finds a way to rise above the adversity. Then he learns that the moral high ground is its own form of trap, so he must put his own spin on the wisdom of Sun Tzu that “to know your enemy, you must become your enemy.” He apparently lowers himself back to the aggressor’s level — but he only does what is necessary. The bitterwseet moral is that survival sometimes requires taking a leaf out of the enemy’s book — but the user has been guiding the hero through this story, which helps the audience to understand that the good guy’s motivations are not comparable to those of his adversary. While testing the CodePen, I found the story moving and even suspenseful in an 8-bit nostalgia kind of way, even if some of that suspense was my uncertainty about whether I would get it working.

From a technical point of view, I think building a full-scale website based on this idea would require a mix of CSS and JavaScript, because storing state in CSS currently requires hacks (like this one, which is cool but also highly experimental). The paused animation approach to remember that the player collected the sword can glitch due to timer drift, so there is a small chance the dude will start the game with the lightsaber already in his hand! If you resize the window during the endgame, you can glitch the game, and then things get really weird. By contrast, something like the scroll snap events — already supported in Chrome — would allow us to store state and even play sounds using a script that fires based on scroll interactions.

It seems like we already have enough in CSS to build a site like this one, which uses horizontal multimedia scrollytelling to raise awareness that interpersonal violence exists on a continuum and tends to escalate if the target is unable to recognize the early warning signs. That’s a worthy topic I unfortunately have some experience with, and the usage of horizontal scrollytelling to address it demonstrates that a wide variety of stories can be told engagingly through scrollytelling.

I leave to the various futures (not to all) my garden of forking paths.

Jorge Luis Borges

Scrollytelling on Steroids With Scroll-State Queries originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.



from CSS-Tricks https://ift.tt/gyhlvnq
via IFTTT

Monday, December 1, 2025

Mostly Clear today!



With a high of F and a low of 17F. Currently, it's 18F and Clear outside.

Current wind speeds: 8 from the Southwest

Pollen: 0

Sunrise: December 1, 2025 at 07:52PM

Sunset: December 2, 2025 at 05:29AM

UV index: 0

Humidity: 65%

via https://ift.tt/5x4SKAU

December 2, 2025 at 10:02AM

Prevent a page from scrolling while a dialog is open

Bramus:

Chrome 144 features a small change to overscroll-behavior: it now also works on non-scrollable scroll containers. While this change might seem trivial, it fixes an issue developers have been dealing with for ages: prevent a page from scrolling while a (modal) <dialog> is open.

YES! Way back in 2019, I worked on “Prevent Page Scrolling When a Modal is Open” with Brad Wu about this exact thing. Apparently this was mere months before we got our hands on the true HTML <dialog> element. In any case, you can see the trouble with active scrolling when a “dialog” is open:

The problem is that the dialog itself is not a scroll container. If it was, we could slap overscroll-behavior: contain on it and be done with it. Brad demoed his solution that involved a JavaScript-y approach that sets the <body> to fixed positioning when the dialog is in an open state:

That’s the tweak Bramus is talking about. In Chrome 144, that’s no longer the case. Going back to that first demo, we can do a couple of things to avoid all the JS mumbo-jumbo.

First, we declare overscroll-behavior on both the dialog element and the backdrop and set it to contain:

body {
  overscroll-behavior: contain;
}

#dialog {
  overscroll-behavior: contain;
}

You’d think that would do it, but there’s a super key final step. That dialog needs to be a scroll container, which we can do explicitly:

#dialog {
  overscroll-behavior: contain;
  overflow: hidden;
}

Chrome 144 needed, of course:

The demo that Bramus provided is much, much better as it deals with the actual HTML <dialog> element and its ::backdrop:


Prevent a page from scrolling while a dialog is open originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.



from CSS-Tricks https://ift.tt/h03GJ6m
via IFTTT

Showers Late today!

With a high of F and a low of 51F. Currently, it's 60F and Showers in the Vicinity outside. Current wind speeds: 5 from the East P...