Change Justify-Content Value When Flex Items Overflow Container

Change justify-content value when flex items overflow container

justify-content is not the right approach to center because of the problem you describe.

Instead, I recommend auto margins. You can use them to center:

Prior to alignment via justify-content and align-self,
any positive free space is distributed to auto margins in that
dimension.

And they behave as you want with overflow:

Overflowing boxes ignore their auto margins and overflow in the end
direction.

For example, you can set margin-left: auto to the first flex item and margin-right: auto to the last one, or insert ::before and ::after pseudo-elements.

.test {  display: flex;  flex-flow: row nowrap;  width: 200px;  border: 2px solid red;  margin: 10px;}.wide.test {  width: 500px;}.test::before, .test::after {  content: '';  /* Insert pseudo-element */  margin: auto; /* Make it push flex items to the center */}.item {  flex: 0 0 50px;  margin-right: 10px;  background: blue;  height: 50px;  border: 2px solid black;}
<div class="test">  <div class="item"></div><div class="item"></div><div class="item"></div>  <div class="item"></div><div class="item"></div><div class="item"></div></div><div class="wide test">  <div class="item"></div><div class="item"></div><div class="item"></div>  <div class="item"></div><div class="item"></div><div class="item"></div></div>

flexbox justify-content causes overflow: auto not work correctly

One of the solutions to this problem is to use the reverse order of the elements in the flex-container, i.e. in your case, using flex-direction: column-reverse instead of flex-direction: column.

Example #1 below:

.container {
width: 20rem;
height: 20rem;
background-color: red;
display: flex;
justify-content: center;
flex-direction: column-reverse;
align-items: center;
overflow-y: auto;
}

.child {
width: 10rem;
min-height: 0;
height: 40rem;
background-color: blue;
flex-shrink: 0;
max-height: 150%;
}

.top {
width: 1rem;
height: 1rem;
background-color: green;
}
<div class="container">
<div class="child">
<div class="top">test</div>
</div>
</div>

Is there a way to have different justify-content values for different rows inside a flexbox-container?

The answer is no.

In grid, there is the justify-self property in which this would be true. However, in flex there is no support for this style as of May 2022.

flex does support align-self for aligning flex item's on the y-axis (align-items), but not for the x-axis (justify-content).

The good news.

You can still replicate these styles in your stylesheet but they will have to be done manually. You can target the first and second flex-item and use width: calc(100%/2) for the first two flex items that you want to each take 50%. Then you can add flex-wrap: wrap on to your flex-container so the image flex-items wrap onto a new row. Then you can replicate justify-content: space-between; by adding margin: auto; to those respective flex-items.

See below:

.flex-container {
display: flex;
flex-wrap: wrap;
}

.flex-item:first-child,
.flex-item:nth-child(2) {
width: calc(100%/2);
outline: dotted 1px black;
}

.flex-item:nth-child(3),
.flex-item:nth-child(4),
.flex-item:nth-child(5) {
outline: solid 1px;
background: orange;
padding: 10px;
}
<div class="wrapper flex-container">
<div class="flex-item">
<h2>Text</h2>
<p>Text</p>
</div>
<div class="flex-item">
<h2>Text</h2>
<p>Text</p>
</div>
<figure class="flex-item" style="margin-right: auto;"><img src="https://dummyimage.com/100/000/fff" alt="junckers"></figure>
<figure class="flex-item" style="margin: auto;"><img src="https://dummyimage.com/100/000/fff" alt="byg-garanti"></figure>
<figure class="flex-item" style="margin-left: auto;"><img src="https://dummyimage.com/100/000/fff" alt="gulvbranchen"></figure>
</div>

Can I change the justify-content value depending on the number of elements in the flex container?

Depending on what you need to support, it might make more sense to use CSS grid layouts (as TylerH pointed out, CSS Grids do not have universal browser support). Check the documentation for further info: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout

.flex-container {  display: grid;  grid-template-columns: repeat(4, 1fr);  grid-gap: 10px;  grid-auto-rows: minmax(100px, auto);}
<div class="flex-container">        <div class="thumb-grid">            <div class="img-block">                <a href=""><img src="https://www.expedient.com/wp-content/uploads/2017/06/exp-mq-resouce-thumbnail-1-150x150.jpg" alt="example image"></a>              </div>            <p>Image 1</p>          </div>        <div class="thumb-grid">            <div class="img-block">                <a href=""><img src="https://www.expedient.com/wp-content/uploads/2017/06/exp-mq-resouce-thumbnail-1-150x150.jpg" alt="example image"></a>              </div>            <p>Image 2</p>          </div>       <div class="thumb-grid">            <div class="img-block">                <a href=""><img src="https://www.expedient.com/wp-content/uploads/2017/06/exp-mq-resouce-thumbnail-1-150x150.jpg" alt="example image"></a>              </div>            <p>Image 3</p>          </div>        <div class="thumb-grid">      <div class="img-block">               <a href=""><img src="https://www.expedient.com/wp-content/uploads/2017/06/exp-mq-resouce-thumbnail-1-150x150.jpg" alt="example image"></a>              </div>            <p>Image 4</p>          </div>        <div class="thumb-grid">            <div class="img-block">                <a href=""><img src="https://www.expedient.com/wp-content/uploads/2017/06/exp-mq-resouce-thumbnail-1-150x150.jpg" alt="example image"></a>              </div>            <p>Image 5</p>          </div>        <div class="thumb-grid">            <div class="img-block">                <a href=""><img src="https://www.expedient.com/wp-content/uploads/2017/06/exp-mq-resouce-thumbnail-1-150x150.jpg" alt="example image"></a>              </div>            <p>Image 6</p>          </div>       <div class="thumb-grid">            <div class="img-block">        <a href=""><img src="https://www.expedient.com/wp-content/uploads/2017/06/exp-mq-resouce-thumbnail-1-150x150.jpg" alt="example image"></a>              </div>            <p>Image 7</p>          </div>      </div>

Can't scroll to top of flex item that is overflowing container

The Problem

Flexbox makes centering very easy.

By simply applying align-items: center and justify-content: center to the flex container, your flex item(s) will be vertically and horizontally centered.

However, there is a problem with this method when the flex item is bigger than the flex container.

As noted in the question, when the flex item overflows the container the top becomes inaccessible.

Sample Image

For horizontal overflow, the left section becomes inaccessible (or right section, in RTL languages).

Here's an example with an LTR container having justify-content: center and three flex items:

Sample Image

See the bottom of this answer for an explanation of this behavior.


Solution #1

To fix this problem use flexbox auto margins, instead of justify-content.

With auto margins, an overflowing flex item can be vertically and horizontally centered without losing access to any part of it.

So instead of this code on the flex container:

#flex-container {
align-items: center;
justify-content: center;
}

Use this code on the flex item:

.flex-item {
margin: auto;
}

Sample Image

Revised Demo


Solution #2 (not yet implemented in most browsers)

Add the safe value to your keyword alignment rule, like this:

justify-content: safe center

or

align-self: safe center

From the CSS Box Alignment Module specification:

4.4. Overflow Alignment: the safe and unsafe keywords and
scroll safety
limits

When the [flex item] is larger than the [flex container], it will
overflow. Some alignment modes, if honored in this situation, may
cause data loss: for example, if the contents of a sidebar are
centered, when they overflow they may send part of their boxes past
the viewport’s start edge, which can’t be scrolled to.

To control this situation, an overflow alignment mode can be
explicitly specified. Unsafe alignment honors the specified
alignment mode in overflow situations, even if it causes data loss,
while safe alignment changes the alignment mode in overflow
situations in an attempt to avoid data loss.

The default behavior is to contain the alignment subject within the
scrollable area, though at the time of writing this safety feature is
not yet implemented.

safe

If the size of the [flex item] overflows the [flex container], the
[flex item] is instead aligned as if the alignment mode were
[flex-start].

unsafe

Regardless of the relative sizes of the [flex item] and [flex
container], the given alignment value is honored.

Note: The Box Alignment Module is for use across multiple box layout models, not just flex. So in the spec excerpt above, the terms in brackets actually say "alignment subject", "alignment container" and "start". I used flex-specific terms to keep the focus on this particular problem.


Explanation for scroll limitation from MDN:

Flex item
considerations

Flexbox's alignment properties do "true" centering, unlike other
centering methods in CSS. This means that the flex items will stay
centered, even if they overflow the flex container.

This can sometimes be problematic, however, if they overflow past the
top edge of the page, or the left edge [...], as
you can't scroll to that area, even if there is content there!

In a future release, the alignment properties will be extended to have
a "safe" option as well.

For now, if this is a concern, you can instead use margins to achieve
centering, as they'll respond in a "safe" way and stop centering if
they overflow.

Instead of using the align- properties, just put auto margins on
the flex items you wish to center.

Instead of the justify- properties, put auto margins on the outside
edges of the first and last flex items in the flex container.

The auto margins will "flex" and assume the leftover space,
centering the flex items when there is leftover space, and switching
to normal alignment when not.

However, if you're trying to replace justify-content with
margin-based centering in a multi-line flexbox, you're probably out of
luck, as you need to put the margins on the first and last flex item
on each line. Unless you can predict ahead of time which items will
end up on which line, you can't reliably use margin-based centering in
the main axis to replace the justify-content property.

problem with justify-content:center; in flexbox

In your CSS for the main identifier, you have flex-direction: column; so you need align-items: center;, not justify-content: center;. Also, I love this resource on Flexbox.

align-items is used for the "cross axis" (if you're adding elements in the column flex direction, the cross axis is the horizontal, and you want your stuff centered horizontally; justify-contents follows the direction axis so it would be trying to center things vertically).

Here's the updated chunk of code in question:

/* ... other styles were above ... */
main {
text-align: center;
background: white;
padding: 2em auto;
margin-top: 2rem;
margin-bottom: 2rem;
display: flex;
flex-direction: column;
justify-content: center; /* don't need this */
align-items: center;
}
/* ... there's more stuff below ... */

How to transition item size change inside a display: flex; justify-content: space-between; div

In order to transition between widths, you must toggle the width value and use the CSS transition property. You cannot transition the width using hidden, as this is either true or false, there are no intermediate values to transition between.

Changes I made to your code:

  • Add overflow: hidden on the container
  • Toggle between widths (instead of the 'hidden' property). This enables transition to work.
  • Add transition: width 2s to both children.

document.getElementById("toggle").addEventListener("click",function(e){

const width = document.getElementById("second").style.width;

if (width === "" || width === "50px") {
document.getElementById("second").style.width = "0px";
} else {
document.getElementById("second").style.width = "50px";
}

},false);
.container {
display: flex;
justify-content: space-between;

background: #aaf;
width: 200px;
height: 40px;
align-items: center;
overflow: hidden;
}

.container > *:first-child {
background: #afa;
width: 100%;
transition: width 2s;
}

.container > *:last-child {
background: #faa;
width: 50px;
transition: width 2s;
}
<div class="container">
<div><span>1st</span></div>
<div id="second">2nd</div>
</div>
<button id="toggle">toggle</button>


Related Topics



Leave a reply



Submit