I have a div with one image and one paragraph in it.
<div id="container">
<img src="..." />
<p>
This is my text
</p>
</div>
I use flex-box and flex-direction: column to align them.
#container {
display: flex;
flex-direction: column;
height: 300px;
width: 400px;
}
img {
max-width: 80%;
flex-basis: 50%;
}
p {
flex-basis: 50%;
}
Since both img and p have flex-basis 50% I would expect each of them to take up 50% of the space. In Firefox it works, but in Chrome the image is bigger (in height) than the container itself.
I have made a jsfiddle to demonstrate this: https://jsfiddle.net/q2esvro9/1/
How can I get the behaviour from Firefox in Chrome?
(Another interesting fact: In Internet Explorer 11 the image and text take up the same space, but the image is stretched in width. Which means 3 different behaviours for a very short and simple CSS code)
#container {
display: flex;
align-items: center;
align-content: center;
text-align: center;
flex-direction: column;
border: solid 2px red;
height: 300px;
width: 400px;
}
img {
max-width: 80%;
flex-basis: 50%;
}
p {
flex-basis: 50%;
border: solid 2px green;
}
<div id="container">
<img src="https://image.freepik.com/free-icon/apple-logo_318-40184.jpg" />
<p>
This is my text
</p>
</div>
There are flexbox rendering variations between the major browsers.
When dealing with images, the number of variations grows.
What I've found to work consistently across browsers is to not use img elements in a flex formatting context (i.e., don't make them flex items).
Instead, wrap an img in a div element, making the div the flex item and keeping the image in a block formatting context.
#container {
display: flex;
align-items: center;
align-content: center;
text-align: center;
flex-direction: column;
border: solid 2px red;
height: 300px;
width: 400px;
}
#container > div {
flex: 0 0 50%; /* 1 */
min-height: 0; /* 2 */
}
img {
height: 100%;
}
p {
flex-basis: 50%;
border: solid 2px green;
}
<div id="container">
<div>
<img src="https://image.freepik.com/free-icon/apple-logo_318-40184.jpg" />
</div>
<p>
This is my text
</p>
</div>
Notes:
The meaning and benefits of flex: 1
Why don't flex items shrink past content size?
Related
I'm trying to create a vertical line inside a flexbox container div, and am finding that unless I give either the line or the container a specific height (like 100px instead of a percentage), the line won't show. Examination with devtools shows that the line has 0 height, even though the container has a non-zero height. I'm guessing that maybe the rendering engine somehow doesn't know about the container's height at the time it's rendering the line? I'd like to find a way to make this work with percentages in order to make the container and line responsive.
jsfiddle: [https://jsfiddle.net/jjorsett/d0852yhx/25/][1] Set .line's height units to px and it will show up.
css and html:
<div class="container">
<img class="image" src="http://via.placeholder.com/100x250"/>
<div class="line">
</div>
</div>
.container {
background: yellow;
display: flex;
height: auto;
justify-content: space-around;
align-items: center;
}
.line {
border-left: .25em solid #f60;
height: 50%;
}
.image {
object-fit: contain;
width: 25%;
}
[1]: https://jsfiddle.net/jjorsett/d0852yhx/25/
Just remove align-items: center; from your container and height: 50% from your child and see the magic.
.container {
background: yellow;
display: flex;
height: auto;
justify-content: space-around;
}
.line {
border-left: .25em solid #f60;
}
.image {
object-fit: contain;
width: 25%;
}
<div class="container">
<img class="image" src="http://via.placeholder.com/100x250"/>
<div class="line">
</div>
</div>
When you align your item in the center it will automatically shrink your child container according to the children of your child div.
For the benefit of anyone else coming across this, I got the behavior I wanted by using javascript as follows (fiddle here: https://jsfiddle.net/jjorsett/d0852yhx/62/)
<div class="container">
<img class="image" src="http://via.placeholder.com/100x250"/>
<div id="line">
</div>
</div>
.container {
background: yellow;
display: flex;
height: auto;
justify-content: space-around;
align-items: center;
}
#line {
border-left: .25em solid #f60;
height: 50%;
}
.image {
object-fit: contain;
width: 25%;
}
window.onresize = adjustLineSize;
window.onload = adjustLineSize;
function adjustLineSize() {
var line = document.getElementById("line");
var desiredLineHeight = line.parentElement.clientHeight/2;
line.style.height= desiredLineHeight + "px";
}
I have a div using flexbox to center its items. Inside this div I have 3 elements, one of them is an image.
<div id="flex-container">
<div id="container1"></div>
<img src="#" alt="">
<div id="container2"></div>
</div>
#container1 and #container2 have their own height, and the img should use the remaining height inside #flex-container.
This snippet works on Firefox, but doesn't work in Chrome. (jsfiddle)
#flex-container{
height: 300px;
width: 500px;
display: flex;
display: -webkit-flex;
flex-flow: column nowrap;
-webkit-flex-flow: column nowrap;
justify-content: center;
-webkit-justify-content: center;
align-items: center;
-webkit-align-items: center;
border: 5px solid black;
}
#container1, #container2{
height: 100px;
width: 300px;
background: orange;
flex: 1 0 auto;
-webkit-flex: 1 0 auto;
}
<div id="flex-container">
<div id="container1">300x100 px</div>
<img src="http://i.imgur.com/RRUe0Mo.png" alt="">
<div id="container2">300x100 px</div>
</div>
Chrome needs -webkit- prefixes for flexbox, but the issue doesn't seem to be this.
What can be happening? Is a browser bug or I'm forgetting something?
There are two problems you need to overcome:
Firefox solves them both on its own, but Chrome needs assistance.
Problem #1
The first problem is that flex items, by default, cannot be smaller than their content. An initial setting on flex items is min-height: auto.
Therefore, a flex item with a replaced element, like an image, will default to the inherent size of the image. The item cannot be made smaller, unless you override the initial setting (use min-height: 0).
#flex-container {
height: 300px;
width: 500px;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
border: 5px solid black;
}
#container1, #container2 {
height: 100px;
width: 300px;
background: orange;
flex: 1 0 auto;
}
img { min-height: 0; } /* NEW */
<div id="flex-container">
<div id="container1">300x100 px</div>
<img src="http://i.imgur.com/RRUe0Mo.png" alt="">
<div id="container2">300x100 px</div>
</div>
A complete explanation of this issue can be found here:
Why doesn't flex item shrink past content size?
Problem #2
Then you hit the second problem: keeping the aspect ratio. This is a common problem in flex containers. One option is to define a height for the image:
#flex-container {
height: 300px;
width: 500px;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
border: 5px solid black;
}
#container1, #container2 {
height: 100px;
width: 300px;
background: orange;
flex: 1 0 auto;
}
img { min-height: 0; height: 100px; } /* NEW */
<div id="flex-container">
<div id="container1">300x100 px</div>
<img src="http://i.imgur.com/RRUe0Mo.png" alt="">
<div id="container2">300x100 px</div>
</div>
This question concerns a browser with full css3 support including flexbox.
I have a flex container with some items in it. They are all justified to flex-start but I want the last .end item to be justified to flex-end. Is there a good way to do this without modifying the HTML and without resorting to absolute positioning?
.container {
display: flex;
flex-direction: column;
outline: 1px solid green;
min-height: 400px;
width: 100px;
justify-content: flex-start;
}
p {
height: 50px;
background-color: blue;
margin: 5px;
}
<div class="container">
<p></p>
<p></p>
<p></p>
<p class="end"></p>
</div>
Flexible Box Layout Module - 8.1. Aligning with auto margins
Auto margins on flex items have an effect very similar to auto margins in block flow:
During calculations of flex bases and flexible lengths, auto margins are treated as 0.
Prior to alignment via justify-content and align-self, any positive free space is distributed to auto margins in that dimension.
Therefore you could use margin-top: auto to distribute the space between the other elements and the last element.
This will position the last element at the bottom.
p:last-of-type {
margin-top: auto;
}
.container {
display: flex;
flex-direction: column;
border: 1px solid #000;
min-height: 200px;
width: 100px;
}
p {
height: 30px;
background-color: blue;
margin: 5px;
}
p:last-of-type {
margin-top: auto;
}
<div class="container">
<p></p>
<p></p>
<p></p>
</div>
Likewise, you can also use margin-left: auto or margin-right: auto for the same alignment horizontally.
p:last-of-type {
margin-left: auto;
}
.container {
display: flex;
width: 100%;
border: 1px solid #000;
}
p {
height: 50px;
width: 50px;
background-color: blue;
margin: 5px;
}
p:last-of-type {
margin-left: auto;
}
<div class="container">
<p></p>
<p></p>
<p></p>
<p></p>
</div>
This flexbox principle also works horizontally
During calculations of flex bases and flexible lengths, auto margins
are treated as 0. Prior to alignment via justify-content and
align-self, any positive free space is distributed to auto margins in
that dimension.
Setting an automatic left margin for the Last Item will do the work.
.last-item {
margin-left: auto;
}
Code Example:
.container {
display: flex;
width: 400px;
outline: 1px solid black;
}
p {
height: 50px;
width: 50px;
margin: 5px;
background-color: blue;
}
.last-item {
margin-left: auto;
}
<div class="container">
<p></p>
<p></p>
<p></p>
<p class="last-item"></p>
</div>
Codepen Snippet
This can be very useful for Desktop Footers.
As Envato did here with the company logo.
Codepen Snippet
I have a web page using a column flexbox, with fixed size header and footer, and a content area which takes up the remaining space. This works fine.
The content area is a row flexbox, and I have 2 square divs side by side. I am making them square by using padding-bottom. This works fine, unless the window is >2x the content area height. Then my squares start bleeding into the footer, because padding is based on element width.
I would like the squares to never overlap the footer. I'm ok with there just being dead space to the right of the squares. I would like to stick with flexbox and avoid floats if possible. Only modern browsers need be supported.
Is this possible with only CSS? Or is this a job for JS.
Fiddle
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#box {
display: flex;
flex-flow: column;
height: 100%;
}
div {
border: 1px solid tomato;
box-sizing: border-box;
margin: 0;
padding: 2px;
}
#header {
flex: 0 0 5em;
}
#footer {
flex: 0 0 5em;
}
#content {
background: blue;
display: flex;
flex: 1 1 auto;
flex-flow: row wrap;
min-height: 30%;
}
#content > div {
background: tomato;
border-color: black;
flex: 1 0 auto;
max-height: 50%;
padding-bottom: 50%;
}
<div id="box">
<div id="header">
<p><b>header</b>
</p>
</div>
<div id="content">
<div id='am'></div>
<div id='pm'></div>
</div>
<div id="footer">
<p><b>footer</b>
</p>
</div>
</div>
TIA!
Simple soluton:
#box
{
display: flex;
flex-flow: column;
min-height: 100%; /* this*/
}
JSfiddle Demo
Note: This assumes you want the page to overflow...but I didn't see any reference to containing the page height to the viewport.
This question already has answers here:
When flexbox items wrap in column mode, container does not grow its width
(9 answers)
Closed 6 years ago.
When using flex box in default row direction, the container height grows to contain all the flex items, even if it is absolutely positioned.
#container {
position: absolute;
display: flex;
flex-wrap: wrap;
}
#container > div {
flex: 0 0 200px;
height: 200px;
}
See http://codepen.io/tamlyn/pen/dPjLoN/?editors=110
However if the flex direction is changed to column, the container collapses to the width of a single flex item, even if the items wrap onto the next column.
#container {
position: absolute;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
#container > div {
flex: 0 0 200px;
width: 200px;
}
See http://codepen.io/tamlyn/pen/rarbeN?editors=110
How can I make the container contain all flex items in column mode?
I've actually found a CSS-only solution to this but it isn't the most perfect thing in the world. Here it is: http://codepen.io/anon/pen/vEPBKK
The trick here is to create a visibility: collapsed container. In flex, visibility: collapsed objects take themselves out of the normal flex flow but retain their dimensions for the purpose of layout. This widens the flex container to the desired width but leaves the flex items unaffected. There are a few caveats, however:
This requires a bit of fiddling. As you can see, the magic <div> is a set width but it uses :nth-child to determine how many boxes are before it. If your actual design breaks at more or less than 3 rows, you'll have to adjust this and you'll most certainly have to adjust the width of the object.
Because of a rendering bug, this does not work in IE. Luckily, IE's incorrect implementation does exactly what you wanted in the first place without any changes so all you have to do is give IE it's own stylesheet with some conditional statements and shoot the div.magic some good old display: none.
HTML
<div id="container">
<div class="fb"></div>
<div class="fb"></div>
<div class="fb"></div>
<div class="fb"></div>
<div class="fb"></div>
<div class="fb"></div>
<div class="fb"></div>
<div class="magic"></div>
</div>
CSS
#container {
position: absolute;
display: flex;
flex-direction: column;
flex-wrap: wrap;
border: 1px solid #f00;
height: 650px;
padding: 1px;
}
#container div.fb {
border: 1px solid #555;
flex: 0 0 200px;
background-color: #ccc;
width: 200px;
margin: 1px;
height: 200px;
}
#container > div.magic {
height: 0;
margin: 0;
padding: 0;
visibility: collapsed;
}
#container > div.magic:nth-child(5),
#container > div.magic:nth-child(6),
#container > div.magic:nth-child(7) {
width: 408px;
}
#container > div.magic:nth-child(8),
#container > div.magic:nth-child(9),
#container > div.magic:nth-child(10) {
width: 612px;
}
#container > div.magic:nth-child(11),
#container > div.magic:nth-child(12),
#container > div.magic:nth-child(13) {
width: 816px;
}
I think this is the CSS you're looking for:
#container {
display: flex;
flex-flow: row wrap;
border: 1px solid #f00;
padding: 1px;
}
#container > * {
border: 1px solid #555;
background-color: #ccc;
height: 200px;
width: 200px;
margin: 1px;
}
The "Container" will always the the width of it's container, in this case the page, but now the boxes will adjust within it properly.
Let me know if I misunderstood your question.
Update
I've been playing with what you're asking for for several days now, and it really seems like it's not possible to do what you're asking... at least not in the direction that you're asking.
The container wants to be the maximum width possible. Unless you force the container to be the exact width, at which point it wont be the full width, but it wont flex with the flexing content either.
.flex-container {
padding: 0;
margin: 0;
list-style: none;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
justify-content: space-around;
border: 1px solid #f00;
}
.flex-item {
background-color: #ccc;
padding: 5px;
width: 200px;
height: 150px;
line-height: 150px;
color: white;
font-weight: bold;
font-size: 3em;
text-align: center;
border: 1px solid #555;
}
<div id="container" class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
<div class="flex-item">7</div>
</div>
The first try I do not understand what you mean
as reference material you can see this tutorial
https://css-tricks.com/snippets/css/a-guide-to-flexbox/