Flexbox justify-content:center vs overflow:auto [duplicate] - css

In attempting to make a useful modal using flexbox, I found what seems to be a browser issue and am wondering if there is a known fix or workaround -- or ideas on how to resolve it.
The thing I'm trying to solve has two aspects. First, getting the modal window vertically centered, which works as expected. The second is to get the modal window to scroll -- externally, so the whole modal window scrolls, not the contents within it (this is so you can have dropdowns and other UI elements that can extend outside of the bounds of the modal -- like a custom date picker, etc.)
However, when combining the vertical centering with scroll bars, the top of the modal can become inaccessible as it begins to overflow. In the above example, you can resize to force the overflow, and in doing so it allows you to scroll to the bottom of the modal, but not to the top (first paragraph is cut off).
.modal-container {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-x: auto;
}
.modal-container .modal-window {
display: -ms-flexbox;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* Optional support to confirm scroll behavior makes sense in IE10
//-ms-flex-direction: column;
//-ms-flex-align: center;
//-ms-flex-pack: center; */
height: 100%;
}
.modal-container .modal-window .modal-content {
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
width: 100%;
max-width: 500px;
padding: 10px
}
<div class="modal-container">
<div class="modal-window">
<div class="modal-content">
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
This affects (current) Firefox, Safari, Chrome, and Opera. It does interestingly behave correctly in IE10 if you comment in the IE10 vendor prefixed CSS -- I did not bother testing in IE11 yet, but assume the behavior matches that of IE10.
Here's the link to the example code (highly simplified)
https://jsfiddle.net/dh9k18k0/2/

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 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.

I managed to pull this off with just 3 containers. The trick is to separate the flexbox container from the container that controls the scrolling. Lastly, put everything into a root container to center it all. Here are the essential styles to create the effect:
CSS:
.root {
display: flex;
justify-content: center;
align-items: center;
}
.scroll-container {
margin: auto;
max-height: 100%;
overflow: auto;
}
.flex-container {
display: flex;
flex-direction: column;
justify-content: center;
}
HTML:
<div class="root">
<div class="scroll-container">
<div class="flex-container">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
I've created a demo here: https://jsfiddle.net/r5jxtgba/14/

Well, as Murphy's Law would have it, the reading I did after posting this question resulted in a few results -- not completely resolved, but somewhat useful nonetheless.
I played around with min-height a bit before posting, but was not aware of the intrinsic sizing constraints that are fairly new to the spec.
http://caniuse.com/#feat=intrinsic-width
Adding a min-height: min-content to the flexbox area does resolve the issue in Chrome, and with vendor prefixes also fixes Opera and Safari, though Firefox remains unresolved.
min-height: -moz-min-content; // not implemented
min-height: -webkit-min-content // works for opera and safari
min-height: min-content // works for chrome
Still looking for ideas on Firefox, and other potential solutions.

I think I found a solution. It works with lots of text and a little text. You don't need to specify the widths of anything, and it should work in IE8.
.wrap1 {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-y: auto;
}
.wrap2 {
display: table;
width: 100%;
height: 100%;
text-align: center;
}
.wrap3 {
vertical-align: middle;
display: table-cell;
}
.wrap4 {
margin: 10px;
}
.dialog {
text-align: left;
background-color: white;
padding: 5px;
border-radius: 3px;
margin: auto;
display: inline-block;
box-shadow: 2px 2px 4px rgba(0, 0, 0, .5);
}
<div class="wrap1">
<div class="wrap2">
<div class="wrap3">
<div class="wrap4">
<div class="dialog">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
</div>
</div>

You should probably use the margin: auto technique, but if you would like to not use flexbox for whatever reason, you can use the pseudo element with vertical align hack to accomplish this.
Example
If codepen does not work
<div class="wrapper">
<div class="modal"></div>
</div>
<style>
.wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000;
overflow-y: auto;
text-align: center;
}
/* Required for centering */
.wrapper:before {
content: '';
height: 100%;
width: 0;
vertical-align: middle;
display: inline-block;
}
.modal {
/* Required for centering */
display: inline-block;
vertical-align: middle;
text-align: left;
width: 320px;
height: 320px;
background-color: #fff;
border-radius: 25px;
}
</style>
It works by creating an inline element, which as the full height of the parent and is displayed as inline-block, just as your target element ( .modal ), then vertical-align: middle is used on both, and the browser does its magic - it aligns the .modal and the pseudo element as though they were regular text. You can also use top/bottom vertical align on the modal div. Combined with text-align, the modal can be placed in any position.
You can use text-align: center on the parent to center the dialog horizontally. Should be supported in any browser and the overflow also works.
At the time of writing ( 9/15/2021 ), going to Google in incognito mode shows a cookie policy modal, which uses this technique for centering.

Try this!
<div class="flex-container">
<div class="item">First item</div>
<div class="item">Second item</div>
<div class="item">Third item</div>
</div>
.flex-container {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
overflow-x: auto;
.item:first-child {
margin-left: auto;
}
.item:last-child {
margin-right: auto;
}
}

My case uses horizontal flex and overflow, and is indeed a boomer. I'm trying to make scrollable content on horizontal flex, like example below:
div {
display: flex;
justify-content: center;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
The solution was by using margin:auto on the first and last element instead:
div {
display: flex;
justify-content: flex-start;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
pre:first-child { margin-left: auto; }
pre:last-child { margin-right: auto; }
<p>When overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
<p>When not overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
Hope it helps

According to MDN, the safe value can now be provided to properties like align-items and justify-content. It's described as follows:
If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were start.
So, it might be used as follows.
.rule
{
display: flex;
flex-direction: row;
justify-content: center;
align-items: safe center;
}
However, it's unclear how much browser support it has, I could not find any examples of its use, and I have been having some issues with it myself. Mentioning it here to draw more attention to it.

I also managed to do it using extra container
HTML
<div class="modal-container">
<div class="modal">
<div class="content-container">
<div class="content">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
</div>
CSS
.modal-container {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: black;
}
.modal {
display: flex;
justify-content: center;
align-items: center;
background-color: #aaa;
height: 80%;
width: 90%;
}
.content-container {
background-color: blue;
max-height: 100%;
overflow: auto;
padding:0;
}
.content {
display: flex;
background-color: red;
padding: 5px;
width: 900px;
height: 300px;
}
in jsfiddle > https://jsfiddle.net/Nash171/cpf4weq5/
change .content width/height values and see

2 Container Flex Method with Table fallback tested IE8-9, flex works in IE10,11.
Edit: Edited to ensure vertical centering when minimal content, added legacy support.
The issue stems from height being inherited from the viewport size which causes children to overflow, as Michael answered. https://stackoverflow.com/a/33455342/3500688
something more simple and use flex to maintain the layout within the popup container(content):
#popup {
position: fixed;
top: 0;
left: 0;
right: 0;
min-height: 100vh;
background-color: rgba(0,0,0,.25);
margin: auto;
overflow: auto;
height: 100%;
bottom: 0;
display: flex;
align-items: flex-start;
box-sizing:border-box;
padding:2em 20px;
}
.container {
background-color: #fff;
margin: auto;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
/* width: 100%; */
max-width: 500px;
padding: 10px;
/* display: flex; */
/* flex-wrap: wrap; */
}
<!--[if lt IE 10]>
<style>
#popup {
display: table;
width:100%;
}
.iewrapper {
display: table-cell;
vertical-align: middle;
}
</style>
<![endif]-->
<div id="popup">
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
<div class="container">
<p class="p3">Test</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
</div>

Just use display: grid instead.

Instead of justify-content: center, add two div with flex: 1 as the first and the last child of your flex container.
html,
body {
background-color: blue;
height: 100%;
overflow: hidden;
}
.container {
background-color: red;
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden auto;
}
.flex-1 {
flex: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Static Template</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="container">
<div class="flex-1"></div>
<h1>
This is a static template, there is no bundler or bundling involved!
</h1>
<p>
This is a static template, there is no bundler or bundling involved!
This is a static template, there is no bundler or bundling involved!
</p>
<div class="flex-1"></div>
</div>
</body>
</html>

Related

I have a form in CSS, but it is cutting at the top of the form [duplicate]

In attempting to make a useful modal using flexbox, I found what seems to be a browser issue and am wondering if there is a known fix or workaround -- or ideas on how to resolve it.
The thing I'm trying to solve has two aspects. First, getting the modal window vertically centered, which works as expected. The second is to get the modal window to scroll -- externally, so the whole modal window scrolls, not the contents within it (this is so you can have dropdowns and other UI elements that can extend outside of the bounds of the modal -- like a custom date picker, etc.)
However, when combining the vertical centering with scroll bars, the top of the modal can become inaccessible as it begins to overflow. In the above example, you can resize to force the overflow, and in doing so it allows you to scroll to the bottom of the modal, but not to the top (first paragraph is cut off).
.modal-container {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-x: auto;
}
.modal-container .modal-window {
display: -ms-flexbox;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* Optional support to confirm scroll behavior makes sense in IE10
//-ms-flex-direction: column;
//-ms-flex-align: center;
//-ms-flex-pack: center; */
height: 100%;
}
.modal-container .modal-window .modal-content {
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
width: 100%;
max-width: 500px;
padding: 10px
}
<div class="modal-container">
<div class="modal-window">
<div class="modal-content">
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
This affects (current) Firefox, Safari, Chrome, and Opera. It does interestingly behave correctly in IE10 if you comment in the IE10 vendor prefixed CSS -- I did not bother testing in IE11 yet, but assume the behavior matches that of IE10.
Here's the link to the example code (highly simplified)
https://jsfiddle.net/dh9k18k0/2/
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 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.
I managed to pull this off with just 3 containers. The trick is to separate the flexbox container from the container that controls the scrolling. Lastly, put everything into a root container to center it all. Here are the essential styles to create the effect:
CSS:
.root {
display: flex;
justify-content: center;
align-items: center;
}
.scroll-container {
margin: auto;
max-height: 100%;
overflow: auto;
}
.flex-container {
display: flex;
flex-direction: column;
justify-content: center;
}
HTML:
<div class="root">
<div class="scroll-container">
<div class="flex-container">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
I've created a demo here: https://jsfiddle.net/r5jxtgba/14/
Well, as Murphy's Law would have it, the reading I did after posting this question resulted in a few results -- not completely resolved, but somewhat useful nonetheless.
I played around with min-height a bit before posting, but was not aware of the intrinsic sizing constraints that are fairly new to the spec.
http://caniuse.com/#feat=intrinsic-width
Adding a min-height: min-content to the flexbox area does resolve the issue in Chrome, and with vendor prefixes also fixes Opera and Safari, though Firefox remains unresolved.
min-height: -moz-min-content; // not implemented
min-height: -webkit-min-content // works for opera and safari
min-height: min-content // works for chrome
Still looking for ideas on Firefox, and other potential solutions.
I think I found a solution. It works with lots of text and a little text. You don't need to specify the widths of anything, and it should work in IE8.
.wrap1 {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-y: auto;
}
.wrap2 {
display: table;
width: 100%;
height: 100%;
text-align: center;
}
.wrap3 {
vertical-align: middle;
display: table-cell;
}
.wrap4 {
margin: 10px;
}
.dialog {
text-align: left;
background-color: white;
padding: 5px;
border-radius: 3px;
margin: auto;
display: inline-block;
box-shadow: 2px 2px 4px rgba(0, 0, 0, .5);
}
<div class="wrap1">
<div class="wrap2">
<div class="wrap3">
<div class="wrap4">
<div class="dialog">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
</div>
</div>
You should probably use the margin: auto technique, but if you would like to not use flexbox for whatever reason, you can use the pseudo element with vertical align hack to accomplish this.
Example
If codepen does not work
<div class="wrapper">
<div class="modal"></div>
</div>
<style>
.wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000;
overflow-y: auto;
text-align: center;
}
/* Required for centering */
.wrapper:before {
content: '';
height: 100%;
width: 0;
vertical-align: middle;
display: inline-block;
}
.modal {
/* Required for centering */
display: inline-block;
vertical-align: middle;
text-align: left;
width: 320px;
height: 320px;
background-color: #fff;
border-radius: 25px;
}
</style>
It works by creating an inline element, which as the full height of the parent and is displayed as inline-block, just as your target element ( .modal ), then vertical-align: middle is used on both, and the browser does its magic - it aligns the .modal and the pseudo element as though they were regular text. You can also use top/bottom vertical align on the modal div. Combined with text-align, the modal can be placed in any position.
You can use text-align: center on the parent to center the dialog horizontally. Should be supported in any browser and the overflow also works.
At the time of writing ( 9/15/2021 ), going to Google in incognito mode shows a cookie policy modal, which uses this technique for centering.
Try this!
<div class="flex-container">
<div class="item">First item</div>
<div class="item">Second item</div>
<div class="item">Third item</div>
</div>
.flex-container {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
overflow-x: auto;
.item:first-child {
margin-left: auto;
}
.item:last-child {
margin-right: auto;
}
}
My case uses horizontal flex and overflow, and is indeed a boomer. I'm trying to make scrollable content on horizontal flex, like example below:
div {
display: flex;
justify-content: center;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
The solution was by using margin:auto on the first and last element instead:
div {
display: flex;
justify-content: flex-start;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
pre:first-child { margin-left: auto; }
pre:last-child { margin-right: auto; }
<p>When overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
<p>When not overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
Hope it helps
According to MDN, the safe value can now be provided to properties like align-items and justify-content. It's described as follows:
If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were start.
So, it might be used as follows.
.rule
{
display: flex;
flex-direction: row;
justify-content: center;
align-items: safe center;
}
However, it's unclear how much browser support it has, I could not find any examples of its use, and I have been having some issues with it myself. Mentioning it here to draw more attention to it.
I also managed to do it using extra container
HTML
<div class="modal-container">
<div class="modal">
<div class="content-container">
<div class="content">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
</div>
CSS
.modal-container {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: black;
}
.modal {
display: flex;
justify-content: center;
align-items: center;
background-color: #aaa;
height: 80%;
width: 90%;
}
.content-container {
background-color: blue;
max-height: 100%;
overflow: auto;
padding:0;
}
.content {
display: flex;
background-color: red;
padding: 5px;
width: 900px;
height: 300px;
}
in jsfiddle > https://jsfiddle.net/Nash171/cpf4weq5/
change .content width/height values and see
2 Container Flex Method with Table fallback tested IE8-9, flex works in IE10,11.
Edit: Edited to ensure vertical centering when minimal content, added legacy support.
The issue stems from height being inherited from the viewport size which causes children to overflow, as Michael answered. https://stackoverflow.com/a/33455342/3500688
something more simple and use flex to maintain the layout within the popup container(content):
#popup {
position: fixed;
top: 0;
left: 0;
right: 0;
min-height: 100vh;
background-color: rgba(0,0,0,.25);
margin: auto;
overflow: auto;
height: 100%;
bottom: 0;
display: flex;
align-items: flex-start;
box-sizing:border-box;
padding:2em 20px;
}
.container {
background-color: #fff;
margin: auto;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
/* width: 100%; */
max-width: 500px;
padding: 10px;
/* display: flex; */
/* flex-wrap: wrap; */
}
<!--[if lt IE 10]>
<style>
#popup {
display: table;
width:100%;
}
.iewrapper {
display: table-cell;
vertical-align: middle;
}
</style>
<![endif]-->
<div id="popup">
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
<div class="container">
<p class="p3">Test</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
</div>
Just use display: grid instead.
Instead of justify-content: center, add two div with flex: 1 as the first and the last child of your flex container.
html,
body {
background-color: blue;
height: 100%;
overflow: hidden;
}
.container {
background-color: red;
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden auto;
}
.flex-1 {
flex: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Static Template</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="container">
<div class="flex-1"></div>
<h1>
This is a static template, there is no bundler or bundling involved!
</h1>
<p>
This is a static template, there is no bundler or bundling involved!
This is a static template, there is no bundler or bundling involved!
</p>
<div class="flex-1"></div>
</div>
</body>
</html>

Flexbox justify-content:center vs overflow:auto in absolutely positioned container [duplicate]

In attempting to make a useful modal using flexbox, I found what seems to be a browser issue and am wondering if there is a known fix or workaround -- or ideas on how to resolve it.
The thing I'm trying to solve has two aspects. First, getting the modal window vertically centered, which works as expected. The second is to get the modal window to scroll -- externally, so the whole modal window scrolls, not the contents within it (this is so you can have dropdowns and other UI elements that can extend outside of the bounds of the modal -- like a custom date picker, etc.)
However, when combining the vertical centering with scroll bars, the top of the modal can become inaccessible as it begins to overflow. In the above example, you can resize to force the overflow, and in doing so it allows you to scroll to the bottom of the modal, but not to the top (first paragraph is cut off).
.modal-container {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-x: auto;
}
.modal-container .modal-window {
display: -ms-flexbox;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* Optional support to confirm scroll behavior makes sense in IE10
//-ms-flex-direction: column;
//-ms-flex-align: center;
//-ms-flex-pack: center; */
height: 100%;
}
.modal-container .modal-window .modal-content {
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
width: 100%;
max-width: 500px;
padding: 10px
}
<div class="modal-container">
<div class="modal-window">
<div class="modal-content">
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
This affects (current) Firefox, Safari, Chrome, and Opera. It does interestingly behave correctly in IE10 if you comment in the IE10 vendor prefixed CSS -- I did not bother testing in IE11 yet, but assume the behavior matches that of IE10.
Here's the link to the example code (highly simplified)
https://jsfiddle.net/dh9k18k0/2/
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 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.
I managed to pull this off with just 3 containers. The trick is to separate the flexbox container from the container that controls the scrolling. Lastly, put everything into a root container to center it all. Here are the essential styles to create the effect:
CSS:
.root {
display: flex;
justify-content: center;
align-items: center;
}
.scroll-container {
margin: auto;
max-height: 100%;
overflow: auto;
}
.flex-container {
display: flex;
flex-direction: column;
justify-content: center;
}
HTML:
<div class="root">
<div class="scroll-container">
<div class="flex-container">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
I've created a demo here: https://jsfiddle.net/r5jxtgba/14/
Well, as Murphy's Law would have it, the reading I did after posting this question resulted in a few results -- not completely resolved, but somewhat useful nonetheless.
I played around with min-height a bit before posting, but was not aware of the intrinsic sizing constraints that are fairly new to the spec.
http://caniuse.com/#feat=intrinsic-width
Adding a min-height: min-content to the flexbox area does resolve the issue in Chrome, and with vendor prefixes also fixes Opera and Safari, though Firefox remains unresolved.
min-height: -moz-min-content; // not implemented
min-height: -webkit-min-content // works for opera and safari
min-height: min-content // works for chrome
Still looking for ideas on Firefox, and other potential solutions.
I think I found a solution. It works with lots of text and a little text. You don't need to specify the widths of anything, and it should work in IE8.
.wrap1 {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-y: auto;
}
.wrap2 {
display: table;
width: 100%;
height: 100%;
text-align: center;
}
.wrap3 {
vertical-align: middle;
display: table-cell;
}
.wrap4 {
margin: 10px;
}
.dialog {
text-align: left;
background-color: white;
padding: 5px;
border-radius: 3px;
margin: auto;
display: inline-block;
box-shadow: 2px 2px 4px rgba(0, 0, 0, .5);
}
<div class="wrap1">
<div class="wrap2">
<div class="wrap3">
<div class="wrap4">
<div class="dialog">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
</div>
</div>
You should probably use the margin: auto technique, but if you would like to not use flexbox for whatever reason, you can use the pseudo element with vertical align hack to accomplish this.
Example
If codepen does not work
<div class="wrapper">
<div class="modal"></div>
</div>
<style>
.wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000;
overflow-y: auto;
text-align: center;
}
/* Required for centering */
.wrapper:before {
content: '';
height: 100%;
width: 0;
vertical-align: middle;
display: inline-block;
}
.modal {
/* Required for centering */
display: inline-block;
vertical-align: middle;
text-align: left;
width: 320px;
height: 320px;
background-color: #fff;
border-radius: 25px;
}
</style>
It works by creating an inline element, which as the full height of the parent and is displayed as inline-block, just as your target element ( .modal ), then vertical-align: middle is used on both, and the browser does its magic - it aligns the .modal and the pseudo element as though they were regular text. You can also use top/bottom vertical align on the modal div. Combined with text-align, the modal can be placed in any position.
You can use text-align: center on the parent to center the dialog horizontally. Should be supported in any browser and the overflow also works.
At the time of writing ( 9/15/2021 ), going to Google in incognito mode shows a cookie policy modal, which uses this technique for centering.
Try this!
<div class="flex-container">
<div class="item">First item</div>
<div class="item">Second item</div>
<div class="item">Third item</div>
</div>
.flex-container {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
overflow-x: auto;
.item:first-child {
margin-left: auto;
}
.item:last-child {
margin-right: auto;
}
}
My case uses horizontal flex and overflow, and is indeed a boomer. I'm trying to make scrollable content on horizontal flex, like example below:
div {
display: flex;
justify-content: center;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
The solution was by using margin:auto on the first and last element instead:
div {
display: flex;
justify-content: flex-start;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
pre:first-child { margin-left: auto; }
pre:last-child { margin-right: auto; }
<p>When overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
<p>When not overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
Hope it helps
According to MDN, the safe value can now be provided to properties like align-items and justify-content. It's described as follows:
If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were start.
So, it might be used as follows.
.rule
{
display: flex;
flex-direction: row;
justify-content: center;
align-items: safe center;
}
However, it's unclear how much browser support it has, I could not find any examples of its use, and I have been having some issues with it myself. Mentioning it here to draw more attention to it.
I also managed to do it using extra container
HTML
<div class="modal-container">
<div class="modal">
<div class="content-container">
<div class="content">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
</div>
CSS
.modal-container {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: black;
}
.modal {
display: flex;
justify-content: center;
align-items: center;
background-color: #aaa;
height: 80%;
width: 90%;
}
.content-container {
background-color: blue;
max-height: 100%;
overflow: auto;
padding:0;
}
.content {
display: flex;
background-color: red;
padding: 5px;
width: 900px;
height: 300px;
}
in jsfiddle > https://jsfiddle.net/Nash171/cpf4weq5/
change .content width/height values and see
2 Container Flex Method with Table fallback tested IE8-9, flex works in IE10,11.
Edit: Edited to ensure vertical centering when minimal content, added legacy support.
The issue stems from height being inherited from the viewport size which causes children to overflow, as Michael answered. https://stackoverflow.com/a/33455342/3500688
something more simple and use flex to maintain the layout within the popup container(content):
#popup {
position: fixed;
top: 0;
left: 0;
right: 0;
min-height: 100vh;
background-color: rgba(0,0,0,.25);
margin: auto;
overflow: auto;
height: 100%;
bottom: 0;
display: flex;
align-items: flex-start;
box-sizing:border-box;
padding:2em 20px;
}
.container {
background-color: #fff;
margin: auto;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
/* width: 100%; */
max-width: 500px;
padding: 10px;
/* display: flex; */
/* flex-wrap: wrap; */
}
<!--[if lt IE 10]>
<style>
#popup {
display: table;
width:100%;
}
.iewrapper {
display: table-cell;
vertical-align: middle;
}
</style>
<![endif]-->
<div id="popup">
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
<div class="container">
<p class="p3">Test</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
</div>
Just use display: grid instead.
Instead of justify-content: center, add two div with flex: 1 as the first and the last child of your flex container.
html,
body {
background-color: blue;
height: 100%;
overflow: hidden;
}
.container {
background-color: red;
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden auto;
}
.flex-1 {
flex: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Static Template</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="container">
<div class="flex-1"></div>
<h1>
This is a static template, there is no bundler or bundling involved!
</h1>
<p>
This is a static template, there is no bundler or bundling involved!
This is a static template, there is no bundler or bundling involved!
</p>
<div class="flex-1"></div>
</div>
</body>
</html>

How to make first element(s) available on center-aligned flex items [duplicate]

In attempting to make a useful modal using flexbox, I found what seems to be a browser issue and am wondering if there is a known fix or workaround -- or ideas on how to resolve it.
The thing I'm trying to solve has two aspects. First, getting the modal window vertically centered, which works as expected. The second is to get the modal window to scroll -- externally, so the whole modal window scrolls, not the contents within it (this is so you can have dropdowns and other UI elements that can extend outside of the bounds of the modal -- like a custom date picker, etc.)
However, when combining the vertical centering with scroll bars, the top of the modal can become inaccessible as it begins to overflow. In the above example, you can resize to force the overflow, and in doing so it allows you to scroll to the bottom of the modal, but not to the top (first paragraph is cut off).
.modal-container {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-x: auto;
}
.modal-container .modal-window {
display: -ms-flexbox;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* Optional support to confirm scroll behavior makes sense in IE10
//-ms-flex-direction: column;
//-ms-flex-align: center;
//-ms-flex-pack: center; */
height: 100%;
}
.modal-container .modal-window .modal-content {
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
width: 100%;
max-width: 500px;
padding: 10px
}
<div class="modal-container">
<div class="modal-window">
<div class="modal-content">
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
This affects (current) Firefox, Safari, Chrome, and Opera. It does interestingly behave correctly in IE10 if you comment in the IE10 vendor prefixed CSS -- I did not bother testing in IE11 yet, but assume the behavior matches that of IE10.
Here's the link to the example code (highly simplified)
https://jsfiddle.net/dh9k18k0/2/
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 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.
I managed to pull this off with just 3 containers. The trick is to separate the flexbox container from the container that controls the scrolling. Lastly, put everything into a root container to center it all. Here are the essential styles to create the effect:
CSS:
.root {
display: flex;
justify-content: center;
align-items: center;
}
.scroll-container {
margin: auto;
max-height: 100%;
overflow: auto;
}
.flex-container {
display: flex;
flex-direction: column;
justify-content: center;
}
HTML:
<div class="root">
<div class="scroll-container">
<div class="flex-container">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
I've created a demo here: https://jsfiddle.net/r5jxtgba/14/
Well, as Murphy's Law would have it, the reading I did after posting this question resulted in a few results -- not completely resolved, but somewhat useful nonetheless.
I played around with min-height a bit before posting, but was not aware of the intrinsic sizing constraints that are fairly new to the spec.
http://caniuse.com/#feat=intrinsic-width
Adding a min-height: min-content to the flexbox area does resolve the issue in Chrome, and with vendor prefixes also fixes Opera and Safari, though Firefox remains unresolved.
min-height: -moz-min-content; // not implemented
min-height: -webkit-min-content // works for opera and safari
min-height: min-content // works for chrome
Still looking for ideas on Firefox, and other potential solutions.
I think I found a solution. It works with lots of text and a little text. You don't need to specify the widths of anything, and it should work in IE8.
.wrap1 {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-y: auto;
}
.wrap2 {
display: table;
width: 100%;
height: 100%;
text-align: center;
}
.wrap3 {
vertical-align: middle;
display: table-cell;
}
.wrap4 {
margin: 10px;
}
.dialog {
text-align: left;
background-color: white;
padding: 5px;
border-radius: 3px;
margin: auto;
display: inline-block;
box-shadow: 2px 2px 4px rgba(0, 0, 0, .5);
}
<div class="wrap1">
<div class="wrap2">
<div class="wrap3">
<div class="wrap4">
<div class="dialog">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
</div>
</div>
You should probably use the margin: auto technique, but if you would like to not use flexbox for whatever reason, you can use the pseudo element with vertical align hack to accomplish this.
Example
If codepen does not work
<div class="wrapper">
<div class="modal"></div>
</div>
<style>
.wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000;
overflow-y: auto;
text-align: center;
}
/* Required for centering */
.wrapper:before {
content: '';
height: 100%;
width: 0;
vertical-align: middle;
display: inline-block;
}
.modal {
/* Required for centering */
display: inline-block;
vertical-align: middle;
text-align: left;
width: 320px;
height: 320px;
background-color: #fff;
border-radius: 25px;
}
</style>
It works by creating an inline element, which as the full height of the parent and is displayed as inline-block, just as your target element ( .modal ), then vertical-align: middle is used on both, and the browser does its magic - it aligns the .modal and the pseudo element as though they were regular text. You can also use top/bottom vertical align on the modal div. Combined with text-align, the modal can be placed in any position.
You can use text-align: center on the parent to center the dialog horizontally. Should be supported in any browser and the overflow also works.
At the time of writing ( 9/15/2021 ), going to Google in incognito mode shows a cookie policy modal, which uses this technique for centering.
Try this!
<div class="flex-container">
<div class="item">First item</div>
<div class="item">Second item</div>
<div class="item">Third item</div>
</div>
.flex-container {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
overflow-x: auto;
.item:first-child {
margin-left: auto;
}
.item:last-child {
margin-right: auto;
}
}
My case uses horizontal flex and overflow, and is indeed a boomer. I'm trying to make scrollable content on horizontal flex, like example below:
div {
display: flex;
justify-content: center;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
The solution was by using margin:auto on the first and last element instead:
div {
display: flex;
justify-content: flex-start;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
pre:first-child { margin-left: auto; }
pre:last-child { margin-right: auto; }
<p>When overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
<p>When not overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
Hope it helps
According to MDN, the safe value can now be provided to properties like align-items and justify-content. It's described as follows:
If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were start.
So, it might be used as follows.
.rule
{
display: flex;
flex-direction: row;
justify-content: center;
align-items: safe center;
}
However, it's unclear how much browser support it has, I could not find any examples of its use, and I have been having some issues with it myself. Mentioning it here to draw more attention to it.
I also managed to do it using extra container
HTML
<div class="modal-container">
<div class="modal">
<div class="content-container">
<div class="content">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
</div>
CSS
.modal-container {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: black;
}
.modal {
display: flex;
justify-content: center;
align-items: center;
background-color: #aaa;
height: 80%;
width: 90%;
}
.content-container {
background-color: blue;
max-height: 100%;
overflow: auto;
padding:0;
}
.content {
display: flex;
background-color: red;
padding: 5px;
width: 900px;
height: 300px;
}
in jsfiddle > https://jsfiddle.net/Nash171/cpf4weq5/
change .content width/height values and see
2 Container Flex Method with Table fallback tested IE8-9, flex works in IE10,11.
Edit: Edited to ensure vertical centering when minimal content, added legacy support.
The issue stems from height being inherited from the viewport size which causes children to overflow, as Michael answered. https://stackoverflow.com/a/33455342/3500688
something more simple and use flex to maintain the layout within the popup container(content):
#popup {
position: fixed;
top: 0;
left: 0;
right: 0;
min-height: 100vh;
background-color: rgba(0,0,0,.25);
margin: auto;
overflow: auto;
height: 100%;
bottom: 0;
display: flex;
align-items: flex-start;
box-sizing:border-box;
padding:2em 20px;
}
.container {
background-color: #fff;
margin: auto;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
/* width: 100%; */
max-width: 500px;
padding: 10px;
/* display: flex; */
/* flex-wrap: wrap; */
}
<!--[if lt IE 10]>
<style>
#popup {
display: table;
width:100%;
}
.iewrapper {
display: table-cell;
vertical-align: middle;
}
</style>
<![endif]-->
<div id="popup">
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
<div class="container">
<p class="p3">Test</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
</div>
Just use display: grid instead.
Instead of justify-content: center, add two div with flex: 1 as the first and the last child of your flex container.
html,
body {
background-color: blue;
height: 100%;
overflow: hidden;
}
.container {
background-color: red;
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden auto;
}
.flex-1 {
flex: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Static Template</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="container">
<div class="flex-1"></div>
<h1>
This is a static template, there is no bundler or bundling involved!
</h1>
<p>
This is a static template, there is no bundler or bundling involved!
This is a static template, there is no bundler or bundling involved!
</p>
<div class="flex-1"></div>
</div>
</body>
</html>

Overflow not visible for centered flex item [duplicate]

In attempting to make a useful modal using flexbox, I found what seems to be a browser issue and am wondering if there is a known fix or workaround -- or ideas on how to resolve it.
The thing I'm trying to solve has two aspects. First, getting the modal window vertically centered, which works as expected. The second is to get the modal window to scroll -- externally, so the whole modal window scrolls, not the contents within it (this is so you can have dropdowns and other UI elements that can extend outside of the bounds of the modal -- like a custom date picker, etc.)
However, when combining the vertical centering with scroll bars, the top of the modal can become inaccessible as it begins to overflow. In the above example, you can resize to force the overflow, and in doing so it allows you to scroll to the bottom of the modal, but not to the top (first paragraph is cut off).
.modal-container {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-x: auto;
}
.modal-container .modal-window {
display: -ms-flexbox;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* Optional support to confirm scroll behavior makes sense in IE10
//-ms-flex-direction: column;
//-ms-flex-align: center;
//-ms-flex-pack: center; */
height: 100%;
}
.modal-container .modal-window .modal-content {
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
width: 100%;
max-width: 500px;
padding: 10px
}
<div class="modal-container">
<div class="modal-window">
<div class="modal-content">
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
This affects (current) Firefox, Safari, Chrome, and Opera. It does interestingly behave correctly in IE10 if you comment in the IE10 vendor prefixed CSS -- I did not bother testing in IE11 yet, but assume the behavior matches that of IE10.
Here's the link to the example code (highly simplified)
https://jsfiddle.net/dh9k18k0/2/
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 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.
I managed to pull this off with just 3 containers. The trick is to separate the flexbox container from the container that controls the scrolling. Lastly, put everything into a root container to center it all. Here are the essential styles to create the effect:
CSS:
.root {
display: flex;
justify-content: center;
align-items: center;
}
.scroll-container {
margin: auto;
max-height: 100%;
overflow: auto;
}
.flex-container {
display: flex;
flex-direction: column;
justify-content: center;
}
HTML:
<div class="root">
<div class="scroll-container">
<div class="flex-container">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
I've created a demo here: https://jsfiddle.net/r5jxtgba/14/
Well, as Murphy's Law would have it, the reading I did after posting this question resulted in a few results -- not completely resolved, but somewhat useful nonetheless.
I played around with min-height a bit before posting, but was not aware of the intrinsic sizing constraints that are fairly new to the spec.
http://caniuse.com/#feat=intrinsic-width
Adding a min-height: min-content to the flexbox area does resolve the issue in Chrome, and with vendor prefixes also fixes Opera and Safari, though Firefox remains unresolved.
min-height: -moz-min-content; // not implemented
min-height: -webkit-min-content // works for opera and safari
min-height: min-content // works for chrome
Still looking for ideas on Firefox, and other potential solutions.
I think I found a solution. It works with lots of text and a little text. You don't need to specify the widths of anything, and it should work in IE8.
.wrap1 {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-y: auto;
}
.wrap2 {
display: table;
width: 100%;
height: 100%;
text-align: center;
}
.wrap3 {
vertical-align: middle;
display: table-cell;
}
.wrap4 {
margin: 10px;
}
.dialog {
text-align: left;
background-color: white;
padding: 5px;
border-radius: 3px;
margin: auto;
display: inline-block;
box-shadow: 2px 2px 4px rgba(0, 0, 0, .5);
}
<div class="wrap1">
<div class="wrap2">
<div class="wrap3">
<div class="wrap4">
<div class="dialog">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
</div>
</div>
You should probably use the margin: auto technique, but if you would like to not use flexbox for whatever reason, you can use the pseudo element with vertical align hack to accomplish this.
Example
If codepen does not work
<div class="wrapper">
<div class="modal"></div>
</div>
<style>
.wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000;
overflow-y: auto;
text-align: center;
}
/* Required for centering */
.wrapper:before {
content: '';
height: 100%;
width: 0;
vertical-align: middle;
display: inline-block;
}
.modal {
/* Required for centering */
display: inline-block;
vertical-align: middle;
text-align: left;
width: 320px;
height: 320px;
background-color: #fff;
border-radius: 25px;
}
</style>
It works by creating an inline element, which as the full height of the parent and is displayed as inline-block, just as your target element ( .modal ), then vertical-align: middle is used on both, and the browser does its magic - it aligns the .modal and the pseudo element as though they were regular text. You can also use top/bottom vertical align on the modal div. Combined with text-align, the modal can be placed in any position.
You can use text-align: center on the parent to center the dialog horizontally. Should be supported in any browser and the overflow also works.
At the time of writing ( 9/15/2021 ), going to Google in incognito mode shows a cookie policy modal, which uses this technique for centering.
Try this!
<div class="flex-container">
<div class="item">First item</div>
<div class="item">Second item</div>
<div class="item">Third item</div>
</div>
.flex-container {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
overflow-x: auto;
.item:first-child {
margin-left: auto;
}
.item:last-child {
margin-right: auto;
}
}
My case uses horizontal flex and overflow, and is indeed a boomer. I'm trying to make scrollable content on horizontal flex, like example below:
div {
display: flex;
justify-content: center;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
The solution was by using margin:auto on the first and last element instead:
div {
display: flex;
justify-content: flex-start;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
pre:first-child { margin-left: auto; }
pre:last-child { margin-right: auto; }
<p>When overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
<p>When not overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
Hope it helps
According to MDN, the safe value can now be provided to properties like align-items and justify-content. It's described as follows:
If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were start.
So, it might be used as follows.
.rule
{
display: flex;
flex-direction: row;
justify-content: center;
align-items: safe center;
}
However, it's unclear how much browser support it has, I could not find any examples of its use, and I have been having some issues with it myself. Mentioning it here to draw more attention to it.
I also managed to do it using extra container
HTML
<div class="modal-container">
<div class="modal">
<div class="content-container">
<div class="content">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
</div>
CSS
.modal-container {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: black;
}
.modal {
display: flex;
justify-content: center;
align-items: center;
background-color: #aaa;
height: 80%;
width: 90%;
}
.content-container {
background-color: blue;
max-height: 100%;
overflow: auto;
padding:0;
}
.content {
display: flex;
background-color: red;
padding: 5px;
width: 900px;
height: 300px;
}
in jsfiddle > https://jsfiddle.net/Nash171/cpf4weq5/
change .content width/height values and see
2 Container Flex Method with Table fallback tested IE8-9, flex works in IE10,11.
Edit: Edited to ensure vertical centering when minimal content, added legacy support.
The issue stems from height being inherited from the viewport size which causes children to overflow, as Michael answered. https://stackoverflow.com/a/33455342/3500688
something more simple and use flex to maintain the layout within the popup container(content):
#popup {
position: fixed;
top: 0;
left: 0;
right: 0;
min-height: 100vh;
background-color: rgba(0,0,0,.25);
margin: auto;
overflow: auto;
height: 100%;
bottom: 0;
display: flex;
align-items: flex-start;
box-sizing:border-box;
padding:2em 20px;
}
.container {
background-color: #fff;
margin: auto;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
/* width: 100%; */
max-width: 500px;
padding: 10px;
/* display: flex; */
/* flex-wrap: wrap; */
}
<!--[if lt IE 10]>
<style>
#popup {
display: table;
width:100%;
}
.iewrapper {
display: table-cell;
vertical-align: middle;
}
</style>
<![endif]-->
<div id="popup">
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
<div class="container">
<p class="p3">Test</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
</div>
Just use display: grid instead.
Instead of justify-content: center, add two div with flex: 1 as the first and the last child of your flex container.
html,
body {
background-color: blue;
height: 100%;
overflow: hidden;
}
.container {
background-color: red;
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden auto;
}
.flex-1 {
flex: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Static Template</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="container">
<div class="flex-1"></div>
<h1>
This is a static template, there is no bundler or bundling involved!
</h1>
<p>
This is a static template, there is no bundler or bundling involved!
This is a static template, there is no bundler or bundling involved!
</p>
<div class="flex-1"></div>
</div>
</body>
</html>

Flexbox: justify-content: center doesn't leave enough vertical space [duplicate]

In attempting to make a useful modal using flexbox, I found what seems to be a browser issue and am wondering if there is a known fix or workaround -- or ideas on how to resolve it.
The thing I'm trying to solve has two aspects. First, getting the modal window vertically centered, which works as expected. The second is to get the modal window to scroll -- externally, so the whole modal window scrolls, not the contents within it (this is so you can have dropdowns and other UI elements that can extend outside of the bounds of the modal -- like a custom date picker, etc.)
However, when combining the vertical centering with scroll bars, the top of the modal can become inaccessible as it begins to overflow. In the above example, you can resize to force the overflow, and in doing so it allows you to scroll to the bottom of the modal, but not to the top (first paragraph is cut off).
.modal-container {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-x: auto;
}
.modal-container .modal-window {
display: -ms-flexbox;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* Optional support to confirm scroll behavior makes sense in IE10
//-ms-flex-direction: column;
//-ms-flex-align: center;
//-ms-flex-pack: center; */
height: 100%;
}
.modal-container .modal-window .modal-content {
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
width: 100%;
max-width: 500px;
padding: 10px
}
<div class="modal-container">
<div class="modal-window">
<div class="modal-content">
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
This affects (current) Firefox, Safari, Chrome, and Opera. It does interestingly behave correctly in IE10 if you comment in the IE10 vendor prefixed CSS -- I did not bother testing in IE11 yet, but assume the behavior matches that of IE10.
Here's the link to the example code (highly simplified)
https://jsfiddle.net/dh9k18k0/2/
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 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.
I managed to pull this off with just 3 containers. The trick is to separate the flexbox container from the container that controls the scrolling. Lastly, put everything into a root container to center it all. Here are the essential styles to create the effect:
CSS:
.root {
display: flex;
justify-content: center;
align-items: center;
}
.scroll-container {
margin: auto;
max-height: 100%;
overflow: auto;
}
.flex-container {
display: flex;
flex-direction: column;
justify-content: center;
}
HTML:
<div class="root">
<div class="scroll-container">
<div class="flex-container">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
I've created a demo here: https://jsfiddle.net/r5jxtgba/14/
Well, as Murphy's Law would have it, the reading I did after posting this question resulted in a few results -- not completely resolved, but somewhat useful nonetheless.
I played around with min-height a bit before posting, but was not aware of the intrinsic sizing constraints that are fairly new to the spec.
http://caniuse.com/#feat=intrinsic-width
Adding a min-height: min-content to the flexbox area does resolve the issue in Chrome, and with vendor prefixes also fixes Opera and Safari, though Firefox remains unresolved.
min-height: -moz-min-content; // not implemented
min-height: -webkit-min-content // works for opera and safari
min-height: min-content // works for chrome
Still looking for ideas on Firefox, and other potential solutions.
I think I found a solution. It works with lots of text and a little text. You don't need to specify the widths of anything, and it should work in IE8.
.wrap1 {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow-y: auto;
}
.wrap2 {
display: table;
width: 100%;
height: 100%;
text-align: center;
}
.wrap3 {
vertical-align: middle;
display: table-cell;
}
.wrap4 {
margin: 10px;
}
.dialog {
text-align: left;
background-color: white;
padding: 5px;
border-radius: 3px;
margin: auto;
display: inline-block;
box-shadow: 2px 2px 4px rgba(0, 0, 0, .5);
}
<div class="wrap1">
<div class="wrap2">
<div class="wrap3">
<div class="wrap4">
<div class="dialog">
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
</div>
</div>
</div>
You should probably use the margin: auto technique, but if you would like to not use flexbox for whatever reason, you can use the pseudo element with vertical align hack to accomplish this.
Example
If codepen does not work
<div class="wrapper">
<div class="modal"></div>
</div>
<style>
.wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000;
overflow-y: auto;
text-align: center;
}
/* Required for centering */
.wrapper:before {
content: '';
height: 100%;
width: 0;
vertical-align: middle;
display: inline-block;
}
.modal {
/* Required for centering */
display: inline-block;
vertical-align: middle;
text-align: left;
width: 320px;
height: 320px;
background-color: #fff;
border-radius: 25px;
}
</style>
It works by creating an inline element, which as the full height of the parent and is displayed as inline-block, just as your target element ( .modal ), then vertical-align: middle is used on both, and the browser does its magic - it aligns the .modal and the pseudo element as though they were regular text. You can also use top/bottom vertical align on the modal div. Combined with text-align, the modal can be placed in any position.
You can use text-align: center on the parent to center the dialog horizontally. Should be supported in any browser and the overflow also works.
At the time of writing ( 9/15/2021 ), going to Google in incognito mode shows a cookie policy modal, which uses this technique for centering.
Try this!
<div class="flex-container">
<div class="item">First item</div>
<div class="item">Second item</div>
<div class="item">Third item</div>
</div>
.flex-container {
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
overflow-x: auto;
.item:first-child {
margin-left: auto;
}
.item:last-child {
margin-right: auto;
}
}
My case uses horizontal flex and overflow, and is indeed a boomer. I'm trying to make scrollable content on horizontal flex, like example below:
div {
display: flex;
justify-content: center;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
The solution was by using margin:auto on the first and last element instead:
div {
display: flex;
justify-content: flex-start;
overflow-x: auto;
}
pre {
padding: 30px;
background: gray;
margin: 20px;
}
pre:first-child { margin-left: auto; }
pre:last-child { margin-right: auto; }
<p>When overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
<p>When not overflow:</p>
<div>
<pre>Item</pre>
<pre>Item</pre>
<pre>Item</pre>
</div>
Hope it helps
According to MDN, the safe value can now be provided to properties like align-items and justify-content. It's described as follows:
If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were start.
So, it might be used as follows.
.rule
{
display: flex;
flex-direction: row;
justify-content: center;
align-items: safe center;
}
However, it's unclear how much browser support it has, I could not find any examples of its use, and I have been having some issues with it myself. Mentioning it here to draw more attention to it.
I also managed to do it using extra container
HTML
<div class="modal-container">
<div class="modal">
<div class="content-container">
<div class="content">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
</div>
</div>
</div>
CSS
.modal-container {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: black;
}
.modal {
display: flex;
justify-content: center;
align-items: center;
background-color: #aaa;
height: 80%;
width: 90%;
}
.content-container {
background-color: blue;
max-height: 100%;
overflow: auto;
padding:0;
}
.content {
display: flex;
background-color: red;
padding: 5px;
width: 900px;
height: 300px;
}
in jsfiddle > https://jsfiddle.net/Nash171/cpf4weq5/
change .content width/height values and see
2 Container Flex Method with Table fallback tested IE8-9, flex works in IE10,11.
Edit: Edited to ensure vertical centering when minimal content, added legacy support.
The issue stems from height being inherited from the viewport size which causes children to overflow, as Michael answered. https://stackoverflow.com/a/33455342/3500688
something more simple and use flex to maintain the layout within the popup container(content):
#popup {
position: fixed;
top: 0;
left: 0;
right: 0;
min-height: 100vh;
background-color: rgba(0,0,0,.25);
margin: auto;
overflow: auto;
height: 100%;
bottom: 0;
display: flex;
align-items: flex-start;
box-sizing:border-box;
padding:2em 20px;
}
.container {
background-color: #fff;
margin: auto;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
/* width: 100%; */
max-width: 500px;
padding: 10px;
/* display: flex; */
/* flex-wrap: wrap; */
}
<!--[if lt IE 10]>
<style>
#popup {
display: table;
width:100%;
}
.iewrapper {
display: table-cell;
vertical-align: middle;
}
</style>
<![endif]-->
<div id="popup">
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
<div class="container">
<p class="p3">Test</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p class="p3">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
<!--[if lt IE 10]>
<div class="iewrapper">
<![endif]-->
</div>
Just use display: grid instead.
Instead of justify-content: center, add two div with flex: 1 as the first and the last child of your flex container.
html,
body {
background-color: blue;
height: 100%;
overflow: hidden;
}
.container {
background-color: red;
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden auto;
}
.flex-1 {
flex: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Static Template</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="container">
<div class="flex-1"></div>
<h1>
This is a static template, there is no bundler or bundling involved!
</h1>
<p>
This is a static template, there is no bundler or bundling involved!
This is a static template, there is no bundler or bundling involved!
</p>
<div class="flex-1"></div>
</div>
</body>
</html>

Resources