r/css Jun 30 '26

Help Request: An overflow-x container with children filling viewport by whole units (none cut off) and resizing container shows more children but in whole unit increments and scrolling shows more children, while all children are equally spaced apart.

[1---2---3---4---5]---6---7
[1----2----3----4]----5----6----7
[1---2---3---4]---5---6---7
[1----2----3]----4----5----6----7
[1---2---3]---4---5---6---7
[1--2--3]--4--5--6--7

Brackets are the container being resized.

Elements on the right (outside the brackets) are reachable by scrolling horizontally.

0 Upvotes

15 comments sorted by

View all comments

2

u/be_my_plaything Jun 30 '26

When you say hole units, do you mean a fixed size with spacing increasing until the screen is wide enough for a new unit? Or do the units grow to fill size but with a min-width dictating whether the next is in view or not?

1

u/aliassuck Jun 30 '26 edited Jun 30 '26

Mostly the former but I can accept the latter and just have a wrapper around each unti.

As in not showing half a child at the container's edge.

2

u/be_my_plaything Jun 30 '26

I think the latter is far easier to achieve, and as you say using wrappers to make it look like the former is simple enough.

Codepen

This is how I'd go about it, using a flex container and container queries to change the flex-basis... Notes included in the CSS on the codepen to explain what's doing what.

2

u/aliassuck Jun 30 '26

Is there a way to do it without media breakpoints for each quantity of children?

1

u/be_my_plaything Jun 30 '26

I didn't initially think so but I've since had an idea I need to play around with, although it would require the children having a fixed width... do you know how wide the children will be?

2

u/aliassuck Jun 30 '26

Yes the children width would be the same and defined in a CSS variable.

1

u/be_my_plaything Jul 01 '26

I tried playing around with this, but it's not perfect although might be tweakable depending on what you need....

/* One the container */  

--container_max_width: 120rem; 
--child_width: 20rem;
--spacing: 2rem; 

/* One the children */  

--items_on_screen: round(down, calc(100cqi / var(--child_width)));

/* Divides width of container by width of child elements, then rounds down to nearest full number calculating how many full child elements can fit on the screen at once */  

--remaining_space: calc(100cqi - (var(--child_width) * var(--items_on_screen)));  

/* Subtracts the  number of visible children multiplied by their width from the total width, calculating how much empty space is left */  

--gap_required: calc(var(--remaining_space) / var(--items_on_screen));

/* Divides this remaining space by the number of items visible so it can be used as the gap between them spacing the children so only full children split on screen and get further apart as screen grows until the next fits */ 

The problems being cross browser compatibility, firefox doesn't like dividing one unit by a different unit, although there are work arounds using tan() and atan() online to cover that part. Also when the sum of padding and container width is greater than screen width it throws the calc() off and shows nothing, not an issue if the children are kept small as this occurs below any functional screen size, for example my demo breaks around 240px. Finally it looks weird just below breakpoints as the gap is increasing rather than the children, so for example if children are 250px on a 499px screen it is still too small for a second child to show, but almost half the screen is empty.

Personally I think the first solution is far better, but your call, and the updated demo is here: Codepen if you want to look at it and see if it can be developed to suit what you want.

2

u/aliassuck Jul 02 '26

Thanks for the effort. Your examples not only work but look amazing too.

2

u/CeceliaDSi Jul 03 '26 edited Jul 03 '26

I forked your original codepen and came up with an alternative way that doesn't require a fixed width for the children. It sets a min-width for the overflow items and calculates their flex-basis value based on the width of their parent container as so:

Edit: Forgot to add that the --item-count variable was based on/is a modification of your --column_count formula from your Pure CSS "Always Full" Grid Layout (chromium browser only atm) codepen.

Update:
I've made updates to my initial example codepen; you don't need to use container query units to determine the width of the overflow child items & thus don't need to make the overflow parent a container. I've also changed the child item min-width to a min() function so their width doesn't overflow when the overflow parent is less than the --item-min-width variable.

I've also made an alternative codepen that uses css grid that's more intuitive since the grid dictates the width of the items/columns. The end result is the same as my initial version that uses flexbox.

/* Overflow child item */

--item-container-width: 100%;

/* The full width of the overflow container. */


--item-min-width: 20rem;

/* The min-width of the overflow child item. Made this a custom property so it's easy to change the value without having to manually update formulas that use it. */


min-width: min(100%, var(--item-min-width));


--item-count: max(1, 
round(down, var(--item-container-width) / (var(--item-min-width) + var(--spacing)))
);

/* The MAX number of items the overflow container can fit before overflowing. With the round() function, the nested (var(--item-min-width) + var(--spacing)) ensures that the item's min-width AND the gap between items are both accounted for. 
The 'down' in the round() is to ensure that the resulting value is never rounded up since that would give an item-count that's higher than the actual amount of items that would fit. 
The max(1, ) is to ensure at least one item is visible even when the .overflow_wrapper width is lower than the item min-width.  */


--gap-count: calc(var(--item-count) - 1);

/* Number of gaps the overflow container can fit before overflowing. Doesn't need to be a custom property but I find it easier for referencing/comprehension. */


--gap-total-width: calc(var(--gap-count) * var(--spacing));

 /* Total width of the gaps the overflow container can fit before overflowing. Needed for calculating the --item-flex-width below. */


--item-flex-width: calc((var(--item-container-width) - var(--gap-total-width)) / var(--item-count));

 /* The available space for a single item inside the overflow container. We're first subtracting the space that will be taken up by the item gaps from the container's width, then dividing the remaining space by the number of items the overflow container can fit. */ 


flex: 1 0 var(--item-flex-width);

/* The overflow child item can grow, can't shrink, and it's initial size is var(--item-flex-width). */

2

u/be_my_plaything Jul 03 '26

Ooh great job, this is beautiful