Why does space-around allow flex items to overflow on the left side?
Since the container is limited in width and you want overflowing flex items to be accessed via horizontal scrolling, why use justify-content: space-around
?
Try justify-content: flex-start
:
Revised Codepen
To understand why overflowing flex items may be inaccessible via scroll, see this answer.
If you're interested in a Javascript workaround for the original code, see this post:
- When centering horizontally, li's get cut off
Prevent flex items from overflowing a container
Your flex items have
flex: 0 0 200px; /* <aside> */
flex: 1 0 auto; /* <article> */
That means:
The
<aside>
will start at200px
wide.Then it won't grow nor shrink.
The
<article>
will start at the width given by the content.Then, if there is available space, it will grow to cover it.
Otherwise it won't shrink.
To prevent horizontal overflow, you can:
- Use
flex-basis: 0
and then let them grow with a positiveflex-grow
. - Use a positive
flex-shrink
to let them shrink if there isn't enough space.
To prevent vertical overflow, you can
- Use
min-height
instead ofheight
to allow the flex items grow more if necessary - Use
overflow
different than visible on the flex items - Use
overflow
different than visible on the flex container
For example,
main, aside, article {
margin: 10px;
border: solid 1px #000;
border-bottom: 0;
min-height: 50px; /* min-height instead of height */
}
main {
display: flex;
}
aside {
flex: 0 1 200px; /* Positive flex-shrink */
}
article {
flex: 1 1 auto; /* Positive flex-shrink */
}
<main>
<aside>x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x </aside>
<article>don't let flex item overflow container.... y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y </article>
</main>
Better way to set distance between flexbox items
- Flexbox doesn't have collapsing margins.
- Flexbox doesn't have anything akin to
border-spacing
for tables (edit: CSS propertygap
fulfills this role in newer browsers, Can I use)
Therefore achieving what you are asking for is a bit more difficult.
In my experience, the "cleanest" way that doesn't use :first-child
/:last-child
and works without any modification on flex-wrap:wrap
is to set padding:5px
on the container and margin:5px
on the children. That will produce a 10px
gap between each child and between each child and their parent.
Demo
.upper {
margin: 30px;
display: flex;
flex-direction: row;
width: 300px;
height: 80px;
border: 1px red solid;
padding: 5px; /* this */
}
.upper > div {
flex: 1 1 auto;
border: 1px red solid;
text-align: center;
margin: 5px; /* and that, will result in a 10px gap */
}
.upper.mc /* multicol test */ {
flex-direction: column;
flex-wrap: wrap;
width: 200px;
height: 200px;
}
<div class="upper">
<div>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa<br/>aaa</div>
<div>aaa<br/>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa</div>
</div>
<div class="upper mc">
<div>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa<br/>aaa</div>
<div>aaa<br/>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa</div>
</div>
Flex items evenly spaced but first item aligned left
You can use justify-content: space-between
, but the last content will have also no space on the right.
A good documentation.
Elements overflows the flex from top of container
reset padding
, margin
, and box-sizing
at the top of the scope -
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
#sidebar {
box-sizing: border-box;
display: flex;
position: fixed;
justify-content: space-around;
flex-direction: column;
overflow-y: scroll;
left: 0;
bottom: 0;
background: blueviolet;
height: 92%;
width: 17%;
margin: 0 auto;
padding-left: 10px;
}
.side, .subs {
padding: 5px;
margin-left: 5px;
}
#things, #others, #subscriptions {
box-sizing: border-box;
display: flex;
flex-direction: column;
padding-bottom: 10px;
}
#things div, #others div, #subscriptions div {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
#things div i, #others div i, #subscriptions div i {
margin-right: 20px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="sidebar">
<div id="things">
<div><i class="fa-solid fa-house side"></i><p>Home</p></div>
<div><i class="fa-regular fa-compass side"></i><p>Explore</p></div>
<div><i class="fa-solid fa-s side"></i><p>Shorts</p></div>
<div><i class="fa-solid fa-photo-film side"></i><p>Subscriptions</p></div>
</div>
<div id="others">
<div><i class="fa-solid fa-file-video side"></i><p>Library</p></div>
<div><i class="fa-solid fa-clock-rotate-left side"></i><p>History</p></div>
<div><i class="fa-solid fa-circle-play side"></i><p>Your Videos</p></div>
<div><i class="fa-regular fa-clock side"></i><p>Watch later</p></div>
<div><i class="fa-solid fa-thumbs-up side"></i><p>Liked Videos</p></div>
<div><i class="fa-solid fa-angle-down side"></i><p>Show more</p></div>
</div>
<div id="subscriptions">
<h4 class="subs">SUBSCRIPTIONS</h4>
<div><i class="fa-solid fa-circle side"></i><p>TKA Team</p></div>
<div><i class="fa-solid fa-circle side"></i><p>Freecodecamp</p></div>
<div><i class="fa-solid fa-circle side"></i><p>Crypto Gurus</p></div>
</div>
</div>
</body>
</html>
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.
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:
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;
}
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
andunsafe
keywords and
scroll safety
limitsWhen 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,
whilesafe
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
considerationsFlexbox'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 putauto
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 thejustify-content
property.
How to make a flex-container's elements overflow to the left?
As unusual an experience as it is likely to cause, you can use a mixture of the flex-direction
and order
properties to have a scrollable container start on its right-most side.
Like was mentioned in the comments, you will need a container around your columns with flex-direction: row-reverse;
to start scrolling from the right. This will place your columns in the opposite order you expect, however.
If you try and use the direction: ltr;
style to fix this issue, the scrollbar will again start from the left. Instead, you must set the order
property of your columns in reverse. This will take some javascript or server-side templating if you want to avoid unnecessary nth-child
selectors.
Here's an example.
.column {
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex-direction: row;
}
#main {
flex-direction: row-reverse;
}
#left {
flex-direction: row-reverse;
overflow-x: scroll;
}
#banner { background-color: lightblue; }
#right { background-color: salmon; width: 400px; }
#left { background-color: teal; }
#footer { background-color: purple; }
<div class="column">
<div class="row" id="banner">Banner</div>
<div class="row" id="main">
<div id="right">Right Container</div>
<div class="row" id="left">
<div class="column" style="order:12">Column Container 1</div>
<div class="column" style="order:11">Column Container 2</div>
<div class="column" style="order:10">Column Container 3</div>
<div class="column" style="order:9">Column Container 4</div>
<div class="column" style="order:8">Column Container 5</div>
<div class="column" style="order:7">Column Container 6</div>
<div class="column" style="order:6">Column Container 7</div>
<div class="column" style="order:5">Column Container 8</div>
<div class="column" style="order:4">Column Container 9</div>
<div class="column" style="order:3">Column Container 10</div>
<div class="column" style="order:2">Column Container 11</div>
<div class="column" style="order:1">Column Container 12</div>
</div>
</div>
<div class="row" id="footer">Footer</div>
</div>
Flex item should align left, not center, when it wraps
Solution
Instead of justify-content: space-around
use justify-content: space-between
.
Explanation
Take a look at the flexbox spec:
8.2. Axis Alignment: the
justify-content
propertyThe
justify-content
property aligns flex items along the main axis
of the current line of the flex container.
There are five values that apply to justify-content
. Here are two of them:
space-around
Flex items are evenly distributed in the line, with half-size spaces
on either end.If the leftover free-space is negative or there is
only a single flex item on the line, this value is identical to
center
.
Emphasis mine. That's the problem you're having.
Now check out space-between
:
space-between
Flex items are evenly distributed in the line.
If the leftover free-space is negative or there is only a single flex item on the line, this value is identical to
flex-start
.
So, to left-align your flex item on wrap, use space-between
.
Then, if necessary, you can add some left and right padding to the container to simulate space-around
.
Of course, the next problem you'll face is when two items wrap, and each item aligns at opposite ends. But that's another question altogether :-)
Display: Flex loses right padding when overflowing?
You need to add another layer of wrapping, if you want to have both "overflow-x:auto" with scrollable padding at the end.
Something like this:
.scroll {
overflow-x: auto;
width: 300px;
border:1px #ccc solid;
}
.outer {
display: flex;
flex-direction: row;
box-sizing: border-box;
min-width: 100%;
height: 80px;
padding: 5px;
float: left; /* To size to content, & not be clamped to available width. (Vendor-prefixed intrinsic sizing keywords for "width" should work here, too.) */
}
.outer > div {
flex: 1 1 auto;
border: 1px #ccc solid;
text-align: center;
min-width: 50px;
margin: 5px;
}
<div class="scroll">
<div class="outer">
<div>text1</div>
<div>text2</div>
<div>text3</div>
<div>text4</div>
<div>text5</div>
<div>text6</div>
<div>text7</div>
<div>text8</div>
<div>text9</div>
<div>text10</div>
</div>
</div>
Related Topics
Why Selecting by Id Is Not Recommended in CSS
404 Errors on Bundled Jquery CSS, VS2012 Publishing to Azure
Why Does Space-Around Allow Flex Items to Overflow on the Left Side
Disable Bootstrap for One Element
CSS Hover Menu Appearing Behind PDF Iframe
How to Customize the Browse Button
Transform Scale: Problem with Scaling Down
Font Awesome 5 Font-Family Issue
Different CSS Transition-Delays for Hover and Mouseout
-Ms-Filter VS Filter What's the Difference
Bootstrap Cards with 100% Height and Margin Bottom
Can You Use CSS Transitions on Svg Attributes? Like Y2 on a Line
CSS Font Differences Between Browsers
CSS Property Box-Reflect Compatibility