Display:flex stretching percentage width images - html

I am trying to code a responsive icon-based menu bar. I am using display:flex to do this but the issue I am having is that the images keep wanting to stretch or squish horizontally when the page is scaled up or down. If they would just move relative to each other and scale uniformally that would be the better solution.
What am I doing wrong?
<!DOCTYPE html>
<html>
<head>
<style>
#A {
display: flex;
justify-content: space-around;
}
.B {
width: 15%
}
</style>
</head>
<body>
<div id="A">
<img class="B" src="http://tinyurl.com/h9zm7bp">
<img class="B" src="http://tinyurl.com/h9zm7bp">
<img class="B" src="http://tinyurl.com/h9zm7bp">
<img class="B" src="http://tinyurl.com/h9zm7bp">
<img class="B" src="http://tinyurl.com/h9zm7bp">
</div>
</body>
</html>

To have display: flex distribute the space without squishing images, you can convert the images into, say, <div>s and set the images as backgrounds with background-size: contain.
<!--- ... --->
<style>
#A {
}
.B {
width: 15%;
background-image: url("http://tinyurl.com/h9zm7bp");
background-size: contain;
}
</style>
<!-- ... -->
<div id="A">
<div class="B"></div>
<div class="B"></div>
<div class="B"></div>
</div>
Also, for some reason, setting a %-based height works:
#A {
display: flex;
justify-content: space-around;
}
.B {
width: 15%;
height: 1%; /* literally any % works here for some reason */
}
Here's a CodePen to demonstrate:
http://codepen.io/milaniliev/pen/eZgZJz
I have no explanation for why that works. It seems the actual height % is ignored.

Try this:
#A {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
.B {
max-width:100%;
}

You can use px instead of % and use the following code
#A {
overflow: auto;
}
#B {
float: left;
width: (in px);
}

Related

Force one div to change size of other div inside the same parent, so the first one can be seen

I have a div with two contents: an image (on top) and text (on bottom).
Height of image plus height of the text is bigger than the height of the parent.
I want an image to shrink, so the whole text will be visible.
So - now it looks like this:
And I want it to look like this:
How to achieve this?
I tried it with display: flex and flex-shrink or flex-grow, but it's not working.
Solution with flex will be much appreciated :)
Here's a codepen with an example:
https://codepen.io/anon/pen/zQXyLb
And here's code used:
<html>
<head></head>
<body style="background: yellow;">
<div style="
width: 150px;
height: 150px;
background: #ddd;
overflow: hidden;
display: flex;
flex-direction: column;
">
<div>
<img src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/apple/198/skull_1f480.png">
</div>
<div>
<div>Here i have some text</div>
<div>which is multiline</div>
<div>and it should make</div>
<div>the skull smaller</div>
</div>
</div>
</body>
</html>
Instead of img tag try div with background-image.
flex: is short form of: flex-grow, flex-shrink, flex-basis.
0 0 auto means that element will take just as much space as needed.
1 1 auto means that element will take all available space — so image takes box size minus text size. And text is always visible.
.box {
display: flex;
flex-direction: column;
margin-bottom: 20px;
width: 150px;
height: 150px;
background: #ddd;
}
.image {
flex: 1 1 auto;
background: url(https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/apple/198/skull_1f480.png) 0 0 no-repeat;
background-size: contain;
}
.text {
flex: 0 0 auto;
}
<div class="box">
<div class="image"></div>
<div class="text">
<div>Here I have some text</div>
<div>which is multiline</div>
<div>and it should make</div>
<div>the skull smaller</div>
</div>
</div>
<div class="box">
<div class="image"></div>
<div class="text">
<div>Here I have small text</div>
</div>
</div>
You can also keep image in the HTMl if you inbricate flex boxes to allow img container to shrink and img understand max-height:100%;
body {
background-color: #a3d5d3;
}
[class],
[class]>div {
display: flex;
flex-direction: column;
overflow: hidden;
}
img {
max-height: 100%;
margin-right: auto;
}
[class]>div[id] {
flex-grow: 1;
flex-shrink: 0;
}
<div class style="
width: 150px;
height: 150px;
background: #ddd;
">
<div>
<img src="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/apple/198/skull_1f480.png">
</div>
<div id>
<div>Here i have some text</div>
<div>which is multiline</div>
<div>and it should make</div>
<div>the skull smaller</div>
</div>
</div>
Resize the image using css.
img{
max-width:50px;
}
The above code should make the image flexible and allow it to be smaller.
Also you can put variable height to the parent div, i.e.
<div style="
width: 150px;
max-height: 250px; //added this part
background: #ddd;
overflow: hidden;
display: flex;
flex-direction: column;
">
But this way the image will stay large but the parent's height will increase. Allowing the text to appear in the enlarged div.

How to make flexbox 'justify-content: space-between' have effect?

I want to create following layout, where a header (green) spans the full width of the screen and is made up of two elements:
a picture (pink), that is top-left aligned, and has the height of the next element
a text block (red), that is top-right aligned. It made of two stacked elements: a text div (yellow) and a button. The width button equals the text width.
The expected output is this:
My code is the following:
.header{
background-color: green;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.flex-element{
display: inline-block;
}
.picture_container{
background-color: pink
}
.picture{
height: 100%;
}
.text_container{
background-color: red
}
.text{
background-color: yellow;
}
<div class="header">
<div class="flex-element picture_container">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Tux_Enhanced.svg/154px-Tux_Enhanced.svg.png" alt="" class="picture">
</div>
<div class="flex-element text_container">
<div class="text">
AAAAAAAAAA <br>
BBB
</div>
<button type="button" name="button" style="width: 100%">foo</button>
</div>
</div>
and gives following output:
The problem is that there is no "space-between" the pink and the red block, and they are not top aligned. I know I could work around it using css grid, yet I'd like to know why it isn't working.
Question: How to make justify-content: space-between have any effect?
This might be a browser issue. Indeed, I am using Firefox Developer Edition 63.0b14 as a browser.
A hack was then to add display: -moz-box; in the .header css definition. It is strange, though, as "Prefixed property values (such as -moz-box) are no longer needed for flexbox to work in major browsers." (see Michael_B's comment). A less hacky solution would hence be still appreciated.
Full code:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>test</title>
<style media="screen">
.header{
background-color: green; 
display: -moz-box;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.flex-element{
display: inline-block;
}
.picture_container{
background-color: pink
}
.picture{
height: 100%;
}
.text_container{
background-color: red
}
.text{
background-color: yellow;
}
</style>
</head>
<body>
<div class="header">
<div class="flex-element picture_container">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Tux_Enhanced.svg/154px-Tux_Enhanced.svg.png" alt="" class="picture">
</div>
<div class="flex-element text_container">
<div class="text">
AAAAAAAAAA <br>
BBB
</div>
<button type="button" name="button" style="width: 100%">foo</button>
</div>
</div>
</body>
</html>
Please try below code
<style>
.header {
padding: 10px;
}
.picture {
width: auto;
}
.text_container {
margin: auto 0;
}
.picture_container {
display: block;
}
</style>

IE 11: Image doesn't scale down correctly within flexbox

I'm trying to use flexbox to place two images in a column. In this case, the width of the div container is smaller than the width of the image. In Chrome the image perfectly fits into the div container, but it doesn't in IE, and I don't know why.
div.outer {
width: 400px;
display: flex;
flex-direction: column;
justify-content: space-around;
}
div.inner {
width: 100%;
border: 1px solid red;
}
img {
width: 100%;
height: auto;
}
<div class="outer">
<div class="inner">
<img src="http://placehold.it/480x360">
</div>
<div class="inner">
<img src="http://placehold.it/480x360">
</div>
</div>
https://jsfiddle.net/Yifei/16cpckqk/
This is what I've got in IE 11:
IE11 seems to have some trouble with the initial value of the flex-shrink property. If you set it to zero (it is initially set to 1), it should work:
div.outer {
width: 400px;
display: flex;
flex-direction: column;
justify-content: space-around;
}
div.inner {
flex-shrink: 0;
width: 100%;
border: 1px solid red;
}
img {
width: 100%;
height: auto;
}
<div class="outer">
<div class="inner">
<img src="http://placehold.it/480x360">
</div>
<div class="inner">
<img src="http://placehold.it/480x360">
</div>
</div>
The accepted solution destroyed my sticky footers in ie. So I solved this disturbing issue with the following non satisfying "only for ie JS"... . The px value instead the "height:auto" did the trick for me.
if(fuBrowser =='ie'){
var img = $("#teaser img");
img.each(function() {
$( this ).css({height: $( this ).height()});
});
}

float:left even if parent div is too small

The issue I am facing here has to do with the fact that the total width of the child divs is larger than the width of the parent div. I need the child divs to float to the left of each other even if they overflow the parent div.
I have this HTML:
<div class="gallery_container">
<div id="viewport">
<div class="gallery_img_container">
<img src="images/1/1.png" class="gallery_img">
</div>
<div class="gallery_img_container">
<img src="images/1/2.png" class="gallery_img">
</div>
<div class="gallery_img_container">
<img src="images/1/3.png" class="gallery_img">
</div>
</div>
</div>
And this CSS:
.gallery_container {
width: 70%;
height: 100%;
float: left;
background-color: #171717;
}
#viewport {
height: 100%;
width: 100%;
}
.gallery_img_container {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.gallery_img {
height: 95%;
}
How can I get all divs with of class gallery_img_container to float to the left of each other? I've tried adding float:left .gallery_img_container but it doesn't do anything. They go underneath each other instead of side by side.
Another note is that .gallery_img_container must have the display:flex property
Thanks in advance for any help!
EDIT: .gallery_img_container must have the width:100% property
You have "width:100%;" applied to the ".gallery_img_container" class causing each container to break into next line, remove this and add "float: left;" then it will work.
Edited based on comments.
.gallery_container {
width: 70%;
height: 100%;
background-color: #171717;
}
#viewport {
height: 100%;
width: 100%;
display: flex;
}
.gallery_img_container {
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
justify-content: flex-start;
flex-wrap: wrap;
}
.gallery_img {
height: 95%;
}
<div class="gallery_container">
<div id="viewport">
<div class="gallery_img_container">
<img src="images/1/1.png" class="gallery_img">
</div>
<div class="gallery_img_container">
<img src="images/1/2.png" class="gallery_img">
</div>
<div class="gallery_img_container">
<img src="images/1/3.png" class="gallery_img">
</div>
</div>
</div>
Farasat,
I'm not entirely sure what you are trying to accomplish. Let me see if I can confirm what I think you are seeking. You want to achieve a result where you have a set of images which are, collectively, wider than #viewport, but you want them to keep "piling up" to the right. That is, you don't want them to wrap. If we consider [] the bounds of the viewport and # to be an image, you want (for example), something like this:
[#]##
Is this right?
If so, I think a key thing to note is that your gallery_img_container is of display flex, which means it is a block, not inline, style. This will cause the gallery_img_containers to stack, not flow to the right.
I think all you need to do is to say "white-space: nowrap;" in #viewport (to keep things from wrapping), and then to make gallery_img_container to be of type inline-flex, so that they do not stack.
I'm attaching an example to hopefully demonstrate what I mean (notes: I just grabbed a random image off the web to make this more concrete. Also note that since your gallery_img_container is 100%, each image is the size of the #viewport. I'm not sure if that's what you want).
.gallery_container {
width: 70%;
height: 100%;
background-color: #171717;
}
#viewport {
height: 100%;
width: 100%;
white-space: nowrap;
}
.gallery_img_container {
width: 100%;
height: 100%;
display: inline-flex;
justify-content: center;
align-items: center;
}
.gallery_img {
height: 95%;
}
<div class="gallery_container">
<div id="viewport">
<div class="gallery_img_container">
<img src="https://wildfiregames.com/forum/uploads/monthly_2016_07/elephant.png.d12017f872cf14f8b046706f497701ba.png" class="gallery_img">
</div>
<div class="gallery_img_container">
<img src="https://wildfiregames.com/forum/uploads/monthly_2016_07/elephant.png.d12017f872cf14f8b046706f497701ba.png" class="gallery_img">
</div>
<div class="gallery_img_container">
<img src="https://wildfiregames.com/forum/uploads/monthly_2016_07/elephant.png.d12017f872cf14f8b046706f497701ba.png" class="gallery_img">
</div>
</div>
</div>

Vertically justify content

Hopefully this isn't an unsolved task, but I'm trying to vertically justify an unknown (ish) number of divs inside of a container.
Each div should be equal distances from each other, and, additionally, the same distance from the edges. (Assuming the last part can be accomplished using ghost elements before and after)
The divs will each fill the width of the container, and the container is a set height, but the number of elements inside the container is unknown.
I'm assuming it can be done using Flexbox to some degree, but have been unsuccessful in my attempts thus far.
Yep, flexbox is the simplest way to do it.
On the container element:
.container {
display: flex;
flex-direction: column;
justify-content: space-between;
}
On the child elements:
.container div {
flex: 1;
width: 100%
}
For the spacing between the elements, just add padding to the container and bottom margins to the children.
The style would look like this:
.container {
/* Same as above, and */
padding: 20px;
}
.container div {
/* Same as above, and */
margin-bottom: 20px;
}
.container div:last-of-type{
margin-bottom: 0;
/* So that spacing is even at bottom and top of container */
}
(I was typing this when you posted your answer, so I put it up anyway)
Fiddle
I use justify-content:space-evenly.
HTML:
div.container {
display: flex;
}
div.one_item_container {
display: flex;
flex-direction: column;
justify-content: space-evenly;
}
<div class="container">
<div class="one_item_container">
<img height="30" src="hello.jpeg" style="background-color:lightblue;" />
</div>
<div class="one_item_container">
<img height="50" src="hello2.jpeg" style="background-color:lightblue;" />
</div>
<div class="one_item_container">
<img height="40" src="hello2.jpeg" style="background-color:lightblue;" />
</div>
</div>
As usual, no matter how long I search, I find the answer only immediately after I ask the question. :D
For those curious, or for my own future reference: Flexbox's justify DOES work, you just need a few more options:
HTML:
<div id="outer-container">
<div class="inner-element"></div>
<div class="inner-element"></div>
<div class="inner-element"></div>
<div class="inner-element"></div>
<div class="inner-element"></div>
<div class="inner-element"></div>
<div class="inner-element"></div>
</div>
CSS:
#outer-container {
height: 250px;
width: 200px;
background: red;
display: flex;
justify-content: space-around;
flex-direction: column;
}
.inner-element {
width: 200px;
height: 10px;
background: blue;
}
https://css-tricks.com/almanac/properties/j/justify-content/
https://jsfiddle.net/WW3bh/