I have a parent with overflow-y and a fixed height. I wish to center align its child. The content of the child can vary in size, and sometimes it overflows the parent and triggers a scrollbar. In those cases, the top and bottom content of the child is cut out.
I wish the child to be center aligned, but only if it's smaller than the parent. Or it could always be center aligned, but then the content shouldn't be cut out.
Check out the problem here: https://jsfiddle.net/gumy023z/
.parent {
background-color: red;
height: 40px;
overflow-y: scroll;
/* Comment out the flex, and all the content will be available */
display: flex;
justify-content: center;
align-items: center;
}
<div class="parent">
<div class="child">
This is a test <br> This is a test <br> This is a test
</div>
</div>
The alignment will work in the flex axis of a flexbox. So you can switch to a column flexbox and give min-height: 0 (which overrides the default min-width: auto setting for a flex item) for the child element - see demo below:
.parent {
background-color: red;
height: 40px;
overflow-y: auto;
display: flex;
flex-direction: column; /* ADDED */
justify-content: center;
align-items: center;
}
.child {
min-height: 0; /* ADDED */
}
<div class="parent">
<div class="child">
1. This is a test <br> 2. This is a test <br> 3. This is a test
</div>
</div>
Related
This question already has an answer here:
Why is a flex item limited to parent size?
(1 answer)
Closed 4 months ago.
I have prepared the following simple sample
This code does not apply max-height to .b when flex-direction is row, and .b overflows.
However, when the flex-direction is column, the max-height is applied and the .b does not overhang due to the max-height. Why is this?
I tried changing align-items:stretch to a value such as flex-start, but I did not see any change.
https://jsfiddle.net/o2fsL9y8/
https://jsfiddle.net/o2fsL9y8/1/
<div class="a">
<div class="b">
</div>
</div>
.a {
max-height: 200px;
background: red;
display: flex;
flex-direction: row; /* or column */
}
.b {
overflow: auto;
background: blue;
flex: 1 1 auto;
height: 500px;
}
edit
When a large child element is created in .b as shown below, it scrolls without overflowing, regardless of whether flex-direction is specified for row or column.
The difference in behavior looks more and more unnatural, even though it should be doing almost the same thing as the code shown above. Why does it behave this way?
https://jsfiddle.net/o2fsL9y8/3/
<div class="a">
<div class="b">
<div style="height: 500px; background-color: yellow"></div>
</div>
</div>
.a {
max-height: 200px;
background: red;
display: flex;
flex-direction: row; /* or column */
}
.b {
overflow: auto;
background: blue;
flex: 1 1 auto;
}
overflow is applied to container not child. So that when the child overflows the container maintains its state and apply the overflow property that you have specified in the container.
<div class="a">
<div class="b">
</div>
</div>
.a {
max-height: 200px;
background: red;
display: flex;
flex-direction: row; /* or column */
overflow: auto;
}
.b {
background: blue;
flex: 1 1 auto;
}
This is hiding the overflow when column and not in row because in column layout the elements have to position with respect to how much height is available. But in row layout they only cares about how much width available and if something overflows you have to deal it within .a.
I am using display:flex in a parent element with justify-content:center and align-items:center and the parent element having multiple children. so when I want to scroll it to extreme top or extreme left, it doesn't work, its only scrolling from center to end. I want it to show center elements for the first time (which is showing) but should scroll from start to end. (Same scroll issue for flex-end).
Example Code:
.parent {
display: flex;
flex-direction: row;
justify-content: center;
width: 100px;
overflow-x: auto;
}
.child {
display: inline-block;
min-width: 50px;
border: 1px solid black;
min-height: 50px;
}
<div class="parent">
<div class="child">
</div>
<div class="child">
</div>
<div class="child">
</div>
<div class="child">
</div>
</div>
This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
CSS when inline-block elements line-break, parent wrapper does not fit new width
(2 answers)
Closed 3 years ago.
A simplified plunkr to show the problem:
https://plnkr.co/edit/mHTHLEumQ04tInFVAz3z?p=preview
If you resize the right viewport until the two containers no longer fit on the same row, right one moves to a new line.
However the parent inline-flex container width does not change, throwing the top "header" element off - the "button" in "header" should be right aligned with the last item in the container below.
The two (or more) items have fixed width but no space between them. Those are the only elements with fixed width or height.
How can I force the flex container width to fit/shrink when items wrap to a new row (without using js, pure HTML/CSS)?
.main-flex {
display: -webkit-inline-flex;
display: inline-flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.flex-container {
flex-grow: 1;
display: -webkit-inline-flex;
display: inline-flex;
-webkit-flex-direction: row;
flex-direction: row;
flex-wrap: wrap;
}
<div style="margin-top: 100px;" class="main-flex">
<div>
<span>header</span>
<span style="float:right">button</span>
</div>
<div class="flex-container">
<div style="height: 400px; width:250px; border: 1px solid black;"></div>
<div style="height: 400px; width:250px; border: 1px solid black;"></div>
</div>
</div>
In CSS, the parent container doesn't know when its children wrap. Hence, it continues scaling its size oblivious to what's going on inside.
Put another way, the browser renders the container on the initial cascade. It doesn't reflow the document when a child wraps.
That's why the container doesn't shrink-wrap the narrower layout. It just continues on as if nothing wrapped, as evidenced by the reserved space on the right.
More details here: Make container shrink-to-fit child elements as they wrap
But you don't need the container to shrink for your layout to work. It can be built with a few adjustments to your HTML and CSS.
.main-flex {
display: inline-flex;
flex-wrap: wrap;
}
.flex-container {
display: flex;
flex-direction: column;
}
.flex-container>div {
height: 400px;
width: 250px;
border: 1px solid black;
}
.flex-container:nth-child(2)>span {
align-self: flex-end;
}
<div class="main-flex">
<div class="flex-container">
<span>header</span>
<div></div>
</div>
<div class="flex-container">
<span>button</span>
<div></div>
</div>
</div>
revised demo
I've got a div with display: flex. Its content is centered horizontally and vertically.
When content is too long in the div, the content wraps. But the alignment is broken in this case. See the snippet.
If I add text-align: center it displays correctly. But why doesn't it center without text-align: center?
.box{
width: 100px;
height: 100px;
background-color: lightgreen;
margin: 10px;
}
.flex{
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: center;
}
.with-align{
text-align: center;
}
<div class="box flex">
some long text here
</div>
<div class="box flex with-align">
some long text here
</div>
The HTML structure of a flex container has three levels:
the container
the item
the content
Each level represents a separate, independent element.
The justify-content property, which is set on flex containers, controls flex items. It has no direct control over the children of the item (the text, in this case).
When you set justify-content: center on a row-direction container the item shrinks to the content width (i.e., shrink-to-fit) and is horizontally centered. The content, being inside the item, goes along for the ride.
Everything is centered nicely, when the content is narrower than the flex container.
On the other hand, when the content is wider than the flex container, the flex item can no longer be centered. In fact, the item cannot be aligned at all (start, end, center) because there is no free space – the item is consuming the full width of the container.
In such cases, the text can wrap. But justify-content: center doesn't apply to the text. It never did. The text was always subject to the default text-align: start (left in LTR / right in RTL).
Therefore, to center the text directly, add text-align: center to the flex item (or the flex container, it doesn't really matter due to inheritance).
article {
display: flex;
align-items: center;
justify-content: center;
}
.center {
text-align: center;
}
/* demo styles only */
article {
width: 100px;
height: 100px;
margin: 10px;
background-color: lightgreen;
}
<article>
<p>some long text here</p>
</article>
<article>
<p class="center">some long text here</p>
</article>
I am trying to stretch the size of an iframe to fill the remaining space within my web app. I know the maximum space is being allocated for the div (by adding a border), but the iframe height itself is not expanding to fill the entire vertical height.
The problem is the row content iframe is not filling the entire vertical space, even though the flexbox is allocating that space appropriately.
Any ideas?
.box {
display: flex;
flex-flow: column;
height: 100vh;
}
.box .row.header {
flex: 0 1 auto;
}
.box .row.content {
flex: 1 1 auto;
}
.box .row.footer {
flex: 0 1 40px;
}
.row.content iframe {
width: 100%;
border: 0;
}
<div class="box">
<div class="row header">
<h1>Event Details</h1>
<div id="container">
<h5>Test</h5>
</div>
<div data-role="navbar">
<ul>
<li>Players
</li>
<li>Games
</li>
<li>Chat
</li>
</ul>
</div>
</div>
<div class="row content">
<iframe src="players.html"></iframe>
</div>
<div class="row footer">
<p><b>footer</b> (fixed height)</p>
</div>
</div>
Here are two things to consider:
When you create a flex container only the child elements become flex items. Any descendants beyond the children are not flex items and flex properties don't apply to them.
Your iframe is not a flex item because it is a child of div class="row content" which is a flex item, but not a flex container. Therefore, no flex properties apply and there is no reason for the iframe to stretch.
To apply flex properties to the children of flex items, you need to make the flex item also a flex container. Try this:
.box .row.content {
flex: 1 1 auto;
display: flex; /* new */
}
With the adjustment above the iframe's parent becomes a (nested) flex container, the iframe becomes a flex item, and default flex settings (including align-items: stretch) go into effect. The iframe should now occupy the full height of the container.
You can fix it with just flexbox, Make sure the container (wrapper) of the iframe has a height set or its parent has, this can be a in pixels percent or VH. and flex-direction:column. The iframe itself needs a flex:1 1 auto; nothing else is needed so no height or width set on it.
Internet explorer can have some problem with the width of the iframe. But it should work vertically. For IE11 make sure you set a min-height:0 on the wrapper.
body{
padding:1em;
display:flex;
flex-direction:column;
align-items:center;
justify-content: center;
height:100vh;
}
.wrap {
display: flex;
flex-direction: column;
width: 80vw;
height: 80vh;
border: 2px solid blue;
min-height: 0;
}
.frame {
flex: 1 1 auto;
border: 0;
}
Simplified jsfidle demo
Complex jsfidle demo