> All in One 586

Ads

Monday, April 6, 2026

Looking at New CSS Multi-Column Layout Wrapping Features

Multi-column layouts have not been used to their full potential, mostly because once content exceeded a limit, multi-column would force a horizontal scroll. It’s unintuitive and a UX no-no, especially on the modern web where the default scroll is vertical.

Take the following case for example:

The CSS code for that might look something like this:

body {
  max-width: 700px;
}

.article {
  column-gap: 10px;
  column-count: 3;
  height: 350px;
}

When the content size exceeds the body container, multi-column creates additional columns and a horizontal scroll. However, we finally have the tools that have recently landed in Chrome that “fix” this without having to resort to trickier solutions.

Chrome 145 introduces the column-height and column-wrap properties, enabling us to wrap the additional content into a new row below, creating a vertical scroll instead of a horizontal scroll. 

So, now we can do something like this in Chrome 145+:

body {
  max-width: 700px;
}

.article {
  column-gap: 10px;
  column-count: 3;
  column-wrap: wrap;
  height: 350px;
}

And we get this nice multi-column layout that maintains the column-count:

Multi-column layout example showing three columns from left to right.

This effectively transforms Multi-Column layouts into 2D Flows, helping us create a more web-appropriate scroll.

⚠️ Browser Support: As of April 2026, column-wrap and column-height are available in Chrome 145+. Firefox, Safari, and Edge do not yet support these properties.

What this actually solves

The new properties can be genuinely useful in several cases:

Fixed-height content blocks

This is probably one of the most useful use cases for these properties. If you’re working with content that has predictable or capped heights, like card grids where each card has a max-height, then this works beautifully. 

Toggle between column-wrap: wrap and column-wrap: nowrap in the following demo (Chrome 145+ needed) to check the difference.

In case you’re checking this in an unsupported browser, this is the nowrap layout:

Multi-column layout example of four cards components in a row with horizontal scrolling.

And this is the wrap layout:

Multi-column layout example of five cards components in a row that wraps to a second row.

Wrapping creates a much more seamless flow. 

However, in case the content-per-card is unbalanced, then even with wrapping, it can lead to unbalanced layouts:

A broken multi-column layout of card components. Some cards are split into multiple cards because the content is unbalanced.

Newspaper-style and Magazine-style layouts

Another real life use case is when designing newspaper-style layouts or sections where you’re willing to set explicit container and column heights. As can be seen in the earlier example, the combination of column-height and column-wrap helps make the layout responsive for different screen sizes, while retaining a more intuitive flow of information. 

Block-direction carousels

This is my personal favorite use case of the column-wrap feature! By setting the column height to match the viewport (e.g., 100dvh), you can essentially treat the multi-column flow as a pagination system, where your content fills the height of the screen and then “wraps” vertically. When combined with scroll-snap-type: y mandatory, you get a fluid, vertical page-flipping experience that handles content fragmentation without any manual clipping or JavaScript calculation.

Play around with the following demo and check it out for yourself. Unless you’re on Chrome 145+ you’ll get a horizontal scroll instead of the intended vertical.

There is a bit of a drawback to this though: If the content on a slide is too long, column-wrap will make it flow vertically, but the flow feels interrupted by that imbalance. 

What they don’t solve

While these properties are genuinely helpful, they are not one-stop solutions for all multi-column designs. Here are a few situations where they might not be the “right” approach.

Truly dynamic content

If the content height is unknown or unpredictable in advance (e.g., user-generated content, CMS-driven pages), then these properties are of little use. The design can still be wrapped vertically with the column-wrap property, however, the layout would remain unpredictable without a fixed column height.

It can lead to over-estimating the column height, leaving awkward gaps in the layout. Similarly, it can lead you to under-estimate the height, resulting in unbalanced columns. The fix here is then to use JS to calculate heights, which defeats the idea of a CSS-native solution.

Media-query-free responsiveness

For a truly “responsive” layout, we still need to use media queries to adjust column-count and column-height for different viewport sizes. While the wrapping helps and creates incremental benefits for a CSS-native solution, it can only help adjust the overflow behavior. Hence, the dependency on media query persists when supporting varying screen sizes.

Complex alignment needs

If you need precise control over where items sit in relation to each other, CSS Grid is still a better option. While multi-column with wrapping gives you flow, it still lacks positioning control.

Comparing alternatives

Let’s see how the multi-column approach compares with existing alternatives like CSS Grid, CSS Flexbox, and the evolving CSS Masonry, that offer similar layouts.

One key difference is that while grid and flexbox manage distinct containers, multi-column is the only system that can fragment a single continuous stream of content across multiple columns and rows. This makes it the best fit for presenting long-form content, like we saw in the newspaper layout example.

CSS Grid lets us control placement via the grid structure, making it great for complex layouts requiring precise positioning or following asymmetric designs, like dashboards or responsive image galleries that need to auto-fit according to the screen size.

Flexbox with wrapping is great for creating standard UI components like navigation bars and tag clouds that should wrap around on smaller screen sizes.

Multi-column layout showing a navigation of eight items where a second row wraps starting at the fifth items.

Note: Chrome is also experimenting with a new flex-wrap: balance keyword that could provide more wrapping control as well.

CSS Grid and Flexbox with wrapping are both good fits for layouts where each item is independent. They work well with content of dynamic heights and provide better alignment control compared to a multi-column approach. However, multi-column with the updated properties has an edge when it comes to fragmentation-aware layouts as we’ve seen.

CSS Masonry, on the other hand, will be useful for interlocking items with varying heights. This makes it perfect for creating style boards (like Pinterest) that pack items with varying heights in an efficient and aesthetic manner. Another good use case is e-commerce websites that use a masonry grid for product displays because descriptions and images can lead to differing card heights.

Conclusion

The new column-wrap and column-height properties supported in Chrome 145 could significantly increase the usability of multi-column layouts. By enabling 2D flows, we have a way to fragment content without losing the vertical scrolling experience.

That said, these features will not be a replacement for the structural precision of CSS Grid or the item-based flexibility of Flexbox. But they will fill a unique niche. As browser support continues to expand, the best way to approach multi-column layout is with an understanding of both its advantages and limitations. They won’t solve dynamic height issues or eliminate the need for media queries, but will allow flowing continuous content in a 2D space.


Looking at New CSS Multi-Column Layout Wrapping Features originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.



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

Sunday, April 5, 2026

Mostly Clear today!



With a high of F and a low of 30F. Currently, it's 48F and Clear outside.

Current wind speeds: 10 from the Southeast

Pollen: 0

Sunrise: April 5, 2026 at 06:29PM

Sunset: April 6, 2026 at 07:19AM

UV index: 0

Humidity: 35%

via https://ift.tt/R3kSTl4

April 6, 2026 at 10:02AM

Saturday, April 4, 2026

Mostly Clear today!



With a high of F and a low of 28F. Currently, it's 42F and Clear outside.

Current wind speeds: 4 from the Northeast

Pollen: 0

Sunrise: April 4, 2026 at 06:30PM

Sunset: April 5, 2026 at 07:18AM

UV index: 0

Humidity: 38%

via https://ift.tt/3bSXI6A

April 5, 2026 at 10:02AM

Friday, April 3, 2026

Clear today!



With a high of F and a low of 26F. Currently, it's 37F and Clear outside.

Current wind speeds: 13 from the Northwest

Pollen: 0

Sunrise: April 3, 2026 at 06:32PM

Sunset: April 4, 2026 at 07:17AM

UV index: 0

Humidity: 58%

via https://ift.tt/Kx7GgJS

April 4, 2026 at 10:02AM

Thursday, April 2, 2026

Mostly Clear/Wind today!



With a high of F and a low of 33F. Currently, it's 57F and Clear outside.

Current wind speeds: 18 from the South

Pollen: 0

Sunrise: April 2, 2026 at 06:34PM

Sunset: April 3, 2026 at 07:16AM

UV index: 0

Humidity: 32%

via https://ift.tt/7sOAMup

April 3, 2026 at 10:02AM

Making Complex CSS Shapes Using shape()

Creating rectangles, circles, and rounded rectangles is the basic of CSS. Creating more complex CSS shapes such as triangles, hexagons, stars, hearts, etc. is more challenging but still a simple task if we rely on modern features.

But what about those shapes having a bit of randomness and many curves?

Three rectangular shapes with jagged, non-creating edges. the first is blue, then orange, then green.

A lot of names may apply here: random wavy, wiggly, blob, squiggly, ragged, torn, etc. Whatever you call them, we all agree that they are not trivial to create, and they generally belong to the SVG world or are created with tools and used as images. Thanks to the new shape() function, we can now build them using CSS.

I won’t tell you they are easy to create. They are indeed a bit tricky as they require a lot of math and calculation. For this reason, I built a few generators from which you can easily grab the code for the different shapes.

All you have to do is adjust the settings and get the code in no time. As simple as that!

While most of you may be tempted to bookmark the CSS generators and leave this article, I advise you to continue reading. Having the generators is good, but understanding the logic behind them is even better. You may want to manually tweak the code to create more shape variations. We will also see a few interesting examples, so stay until the end!

Notice: If you are new to shape(), I highly recommend reading my four-part series where I explain the basics. It will help you better understand what we are doing here.

How does it work?

While many of the shapes you can create with my generators look different, all of them rely on the same technique: a lot of curve commands. The main trick is to ensure two adjacent curve create a smooth curvature so that the full shape appears as one continuous curve.

Here is a figure of what one curve command can draw. I will be using only one control point:

A normal curve with a control point in the very center. The second shows another curve with control point veering towards the left, contorting the curve.

Now, let’s put two curves next to each other:

A wavy curve with two control points, one point up and the other down forming a wave along three points.

The ending point of the first curve, E1, is the starting point of the second curve, S2. That point is placed within the segment formed by both the control points C1 and C2. That’s the criterion for having an overall smooth curve. If we don’t have that, we get a discontinued “bad” curve.

A wavy curve with two control points. The second point is moved down and toward the right, bending the curves second wav in an undesired way.

All we have to do is to randomly generate different curves while respecting the previous criterion between two consecutive curves. For the sake of simplicity, I will consider the common point between two curves to be the midpoint of the control points to have less randomness to deal with.

Creating the shapes

Let’s start with the easiest shape, a random wavy divider. A random curve on one side.

A long blue rectangle with a jagged bottom edge.

Two variables will control the shape: the granularity and the size. The granularity defines how many curves we will have (it will be an integer). The size defines the space where the curves will be drawn.

The same blue renctangle in two versions with two different jagged bottom edges, marked in red to show the shape. The first is labeled Granularity 8 and the second, with more and deeper jags, is labeled Granularity 18.

The first step is to create N points and evenly place them at the bottom of the element (N is the granularity).

A white rectangle with a black border and seven control points evenly spaced along the bottom edge.

Then, we randomly offset the vertical position of the points using the size variable. Each point will have an offset equal to a random value within the range [0 size].

A white rectangle with a black border and seven control points evenly spaced in a wavy formation along the bottom edge. A red label saying Size indicates the vertical height between the highest point and lowest point.

From there, we take two adjacent points and define their midpoint. We get more points.

A white rectangle with a black border and thirteen control points evenly spaced in a wavy formation along the bottom edge. A red label saying Size indicates the vertical height between the highest point and lowest point. Every even point is marked in blue.

Do you start to see the idea? A first set of points is randomly placed while a second set is placed in a way that meets the criterion we defined previously. From there, we draw all the curves, and we get our shape.

The CSS code will look like this:

.shape {
  clip-path: shape(from Px1 Py1,
    curve to Px2 Py2 with Cx1 Cy1,
    curve to Px3 Py3 with Cx2 Cy2,
    /* ... */
    curve to Pxi Pyi with Cx(i-1) Cy(i-1)
    /* ... */
  )
}

The Ci are the points we randomly place (the control points) and Pi are the midpoints.

From there, we apply the same logic to the different sides to get different variation (bottom, top, bottom-top, all sides, etc.).

A two-by-two grid of the same blue rectangle with different configurations of wavy edges. The first on the bottom, the second on the top, the third on the top and bottom, and the fourth all along the shape.

As for the blob, the logic is slightly different. Instead of considering a rectangular shape and straight lines, we use a circle.

Two white circles with black borders that contain a smaller circle with a dashed border. The first circle has eight black control points around the outer circle evenly spaced. The second has 15 control points around it, even other one in blue and positioned between the outer and inner circles to form a wavy shape.

We evenly place the points around the circle (the one formed by the element if it has border-radius: 50%). Then, we randomly offset them closer to the center. Finally, we add the midpoints and draw the shape.

A large green blob shape.

We can still go fancier and combine the first technique with the circular one to consider a rectangle with rounded corners.

A blue rounded rectangle next to another version of itself with a large number of jagged edges all around it.

This was the trickiest one to implement as I had to deal with each corner, each side, and work with different granularities. However, the result was quite satisfying as it allows us to create a lot of fancy frames!

Show me the cool demos!

Enough theory, let’s see some cool examples and how to simply use the generators to create complex-looking shapes and animations.

We start with a classic layout featuring numerous wavy dividers!

We have four shapes in that demo, and all of them are a simple copy/paste from the wavy divider generator. The header uses the bottom configuration, the footer uses the top configuration and the other elements use the top + bottom configuration.

Let’s get fancy and add some animation.

Each element will have the following code:

@media screen and (prefers-reduced-motion: no-preference) {
  .element {
    --s1: shape( ... );
    --s2: shape( ... );
    animation: dance linear 1.6s infinite alternate;
  }

  @keyframes dance {
    0% {clip-path: var(--s1)}
    to {clip-path: var(--s2)}
  }
}

From the generator, you fix the granularity and size, then you generate two different shapes for each one of the variables (--s1 and --s2). The number of curves will be the same, which means the browser can have an interpolation between both shapes, hence we get a nice animation!

And what about introducing scroll-driven animation to have the animation based on the scroll? All you have to do is add animation-timeline: scroll() and it’s done.

Here is the same effect with a sticky header.

For this one, you play with the size. You fix the granularity and the shape ID then you consider a size equal to 0 for the initial shape (a rectangle) and a size different from 0 for the wavy one. Then you let the browser animate between both.

Do you see all the possibilities we have? You can either use the shapes as static decorations or create fancy animations between two (or more) by using the same granularity and adjusting the other settings (size and shape ID).

What cool demo can you create using those tricks? Share it in the comment section.

I will leave you with more examples you can use as inspiration.

A bouncing hover effect with blob shapes:

A squishy button with a hover and click effect:

A wobbling frame animation:

liquid reveal effect:

And a set of fancy CSS loaders you can find at my site.

Conclusion

Do you see all the potential of the new shape() function? We now have the opportunity to create complex-looking shapes without resorting to SVG or images. In addition to that, we can easily have nice transition/animation.

Don’t forget to bookmark my CSS Generators website, from where you can get the code of the shapes we studied and more. I also have the CSS Shape website which I will soon update to utilize the new shape() for most of the shapes and optimize a lot of old code!

What about you? Can you think about a complex shape we can create using shape()? Perhaps you can give me the idea for my next generator!


Making Complex CSS Shapes Using shape() originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.



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

Wednesday, April 1, 2026

Showers today!



With a high of F and a low of 34F. Currently, it's 44F and Mostly Cloudy outside.

Current wind speeds: 7 from the North

Pollen: 0

Sunrise: April 1, 2026 at 06:35PM

Sunset: April 2, 2026 at 07:15AM

UV index: 0

Humidity: 95%

via https://ift.tt/o5RCT9d

April 2, 2026 at 10:02AM

Looking at New CSS Multi-Column Layout Wrapping Features

Multi-column layouts have not been used to their full potential, mostly because once content exceeded a limit, multi-column would force a ho...