I'm having some difficulty understanding the different image size configurations in Flexbox. It seems like I get a different result every time I try to apply them.
Instead of saying "it all depends on the situation", can someone explain the following with some coherent logic stringing through these different scenarios? I would like to know why the results are different each time. I'm not too concerned about the ratio of the images, but more so about the locations of the images depending on the viewport size. Let's say I use object-fit: cover for all scenarios. Here's an example that puts two images side by side.
index.html
<section>
<figure>
<img src="profile image1.jpg" alt="">
</figure>
<figure>
<img src="profile image2.jpg" alt="">
</figure>
</section>
style.css
section {
display: flex;
}
Scenario 1
style.css
/* figure wrapper's dimension is set, but not those of the images */
figure {
flex: 50%;
width: 100%;
height: auto;
}
Scenario 2
style.css
/* figure wrapper's dimension and the images' dimension are both set with a percentage unit */
figure {
flex: 50%;
width: 100%;
height: auto;
}
img {
width: 100%;
height: 100%;
}
Scenario 3
style.css
/* figure wrapper's dimension and the images' dimension are both set with the pixel unit */
figure {
flex: 50%;
width: 400px;
height: 400px;
}
img {
width: 400px;
height: 400px;
}
Scenario 4
style.css
/* figure's dimension is set with max-width and max-height */
figure {
flex: 50%;
max-width: 400px;
max-height: 400px;
}
img {
width: 100%;
height: 100%;
}
Senario 5
style.css
/* figure's dimension and image's dimension are set with max-width and max-height */
figure {
flex: 50%;
max-width: 400px;
max-height: 400px;
}
img {
max-width: 100%;
max-height: 100%;
}
I guess I'm ultimately trying to figure out what the benefit of putting the image in a container with different configurations of pixel/percentage dimension unit.
Not setting image width (scenario #1), the image will use its
original width and height, meaning if, for example, you are using an image having 1024*768 dimension, it fills 1024 px of your page width and 768px of your page height. This behavior will ignore whatever
the configuration you have used for its wrapper i.e. figure.
Having set the img width 100%, meaning you've forced the element to adhere to the width of its container (in this case figure). So, in this case, the flex configurations come into effect.
In scenario#2 you have set the width of flex item (i.e. figure) to 100% of its container (i.e. section). But it sets the initial width of the figure! meaning unless you haven't set the flex-shrink to 0, the figure will be shrunk to fulfill the specifications of Flexbox.
Flexbox specification says while flex-wrap is nowrap which is the default behavior, the width of the container will be assigned equally to the items. As you have two items here (two figures), the width of each will be shrunk to 50% of its container (i.e. section).
The result is obvious now. The image will be shrunk to 100% of its container which in turn have 50% of its container and you will see two images beside each other.
When you set width: 400px for figure element which in place is a flex item, It's somehow ignored by the browser and is replaced by the browser calculated width. flex-shrink, flex-grow are two of them. When you say flex: 50%, you have not changed flex-grow and flex-shrink default values (i.e. 1) allowing the browser to shrink the items to position them in one line (as flex-wrap: nowrap says to do that!)
As a result, in scenario#3 which the flex-basis is 50%, the specified width will be ignored and the base width of the element will be 50% of its container. But of course, they will be shrunk so that the final width will be something that allows figure items to be beside each other and img tags adhere the width of their container and cover them (will be resized to fill them)
In scenario#4 and #5, you have set the max-width of figure item. Doing such will cut the calculated width of browser meaning it will overwrite everything the browser calculated using the above rules. It does not matter whether you have specified the width using px or percent If the browser calculated width is greater than the specified max-width, the final width will be changed to max-width.
Scenario 1
The images use their natural size. If they are smaller than the flexboxes, they are aligned to the left or their respective flexbox like text, forming two columns. If they are bigger, they overflow. I would therefore advise against this.
flex: 50% is a shorthand for flex-basis: 50%; flex-grow: 1; flex-shrink: 1. The figures have both a flex-basis and a width, which is useless. Only the flex-basis will be considered. Therefore, the algorithm will first create the figures at 50% of the width of their parent, then either grow them or shrink them evenly to fit said parent. As I said before, the images will overflow regardless if they are too big.
Scenario 2
Just like in Scenario 1, the width: 100% on the figure is useless.
Giving the images both a height and width will make them stretch to fill their parent. I do not know the exact algorithm which determines their size in this case because I never do that. I'd recommend only setting width in this case, so the height of the image is automatically chosen to respect the aspect ratio.
Scenario 3
The width and height of 400px on the figure is ignored because flex: 50% set the flex-basis which has priority.
The image is stretched to be exactly 400px by 400px, which might cause it to overflow horizontally.
Scenario 4
The figures are told they cannot grow beyond 400px, so if 50% of their parent is bigger than that, they will be of 400px wide. Being given no set height, and since their children have a relative height of 100%, their height is set to their max-height of 400px. If someone knows a better explanation of this behavior, please share in the comments.
The images are stretched to fill the flexbox entirely, losing their original aspect ratio.
Scenario 5
The figures behave just like in scenario 4.
The images keep their original size EXCEPT if they are wider than their parent figures, in which case they are shrunk down. Since both max-width and max-height are set, the images may lose their original aspect ratio in the process.
Another recommendation
You don't need to make the figures grow at all. This can be desirable if you want to style them and add legends to your images. Example:
section {
display: flex;
}
figure {
background-color: #dca;
padding: 20px;
}
img {
max-width: 100%;
}
<!-- PS: the width and height attributes on img tags emulate actual image size -->
<section>
<figure>
<img width="200" height="100" alt="">
<legend>Fig. 1</legend>
</figure>
<figure>
<img width="400" height="100" alt="">
<legend>Fig. 2</legend>
</figure>
</section>
The default flex-styles for any element are:
flex-grow: 0; /* do not grow */
flex-shrink: 1; /* shrink automatically to fit parent */
flex-basis: auto; /* but otherwise determine size based on content */
Then again, you might want elements to fit into columns neatly, in which case a flex: 50% on a wrapper around the figure elements might be better. In any case, it always helps to add background colors to elements when testing things out!
Related
somehow my image is not scaling down or up at all. I have seen many things on the internet but I could not solve it. W3schools told me to make it like this, with the formular-banner image.
.formular-banner
{
max-width: 100%;
height: auto;
}
<div class="formular-banner">
<img src="koala.jpeg">
</div>
First of all, you are defining settings for the parent element of the image, not for the image itself. So you can't expect that to have an effect on the image...
For the image itself, you also shouldn't use those settings, but instead of max-width: 100% (to make it the full width of the container), you should use width: 100%, plus a max-width that has the original width of the image in pixels, in order not to make it any bigger (i.e. distorted) than the original image in case it's smaller (i.e. less wide) than the container.
So your CSS rule would be
.formular-banner > img {
width: 100%;
max-width: 1240px; /* use the actual width of your image here */
height: auto;
}
If the image is smaller than the container (which, as a div = block element) will have 100% width by default) and you want it to be centered, you can add this rule (for the container) which will horizontally center the image (as an inline element) inside the container:
.formular-banner {
text-align: center;
}
I have an image element, it can contain any aspect ratio of the image (eg horizontal and vertical). I want to fill the page with it until either its height or width is 100% of the page.
I tried checking the image height and width and setting min-width/height to 100%. This worked very well for vertical images, but with horizontal images, sometimes the 100% height gets reached before the width does, (especially on 4:3 aspect ratio images).
Basically, I just want it to fill either the height or width of the screen, depending on what happens first.
Try with object-fit on image, so it fits it's container and chose the value that suits your needs best.
https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit
The object-fit property will do this if you set it to contain (if you set it to fill it will become distorted if the aspect ratio of the container and the img are not the same).
Here's a simple example, change the viewport dimensions to see the affect on the image:
.container {
width: 50vw;
height: 50vh;
background: gray;
}
.container img {
width: 100%;
height: 100%;
object-fit: contain;
}
<div class="container">
<img src="https://picsum.photos/id/1015/768/1024"/>
</div>
The basic code is simple:
CSS
.pop {
position: fixed ;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
background-color: yellow ; }
HTML
<body>
<div class="pop">some variable text.</div>
</body>
BEHAVIOURS
div.pop expands to fit its contents into a rectangle that, in a
viewport 915px wide, has a maximum width of 457.5px wide, and a
maximum height of 100%.
If the viewport is reduced, "margins" appear on either side of
div.pop, each taking up about a quarter of the viewport width.
Continuing to reduce the viewport width, the width of div.pop then
shrinks. After it has shrunk to the width of its largest word the
proportion of the "margins" starts to shrink, until they disappear,
and the div.pop contents "overflow" the viewport.
GOAL and PROBLEM
I want to have a fixed position, centered DIV that does not exceed
e.g. 95% of the viewport or 30em, whichever is smallest, and that
ideally shrinks to fit content smaller than this, with a minimum width
of 10em. I need to control the behaviours (above) to do this but have
been unable to find an explanation of them.
APPROACHES
I can't find a combination of min-width, max-width, and width
that achieves the goal. min-width achieves the minimum width
requirement, but nothing seems to override the "margins", and maximum
width behaviours of div.pop.
Using display:table-row; and display:table-cell; seems to have no
effect, suggesting the maximum width and "margins" of div.pop are
not the result of anonymous cells.
From stripping out all code except that given here, it looks like the
"problem" comes from an intrinsic set of behaviours. I have been
unable to find a definition of these or way they can be
controlled.
Including/omitting the Meyers reset css has no effect, so browser
presets don't seem to be involved.
FF Inspector displays the width of div.pop onscreen in the popup
associated with it; this width is also shown in the Box Model pane but
no computed width for it is given nor any rules relating to
that.
QUESTION
How are the dimensions of div.pop being calculated and the
behaviours being generated, and how can this be controlled to achieve
a goal like that described?
Try using max-width and setting a media query:
.pop {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: yellow ;
width: 30em;
min-width: 10em;
}
#media (max-width: 30em) {
.pop {
max-width: 95%;
}
}
If you need something more advanced, try using calc (reference).
I am trying to insert full width hero image. Problem is based on the original height of the image, it's getting too short on mobile device.
Large Screen:
Mobile Screen:
Basically, I wanted little bit bigger height than the calculated height on mobile screen. So, I thought it would be good if I apply a min-height to the image.
So, I have added this:
img {
min-height: 300px;
}
Surely, it's not the way.
How to fix this?
Code Demo
You need to wrap the img block in the parent block. Then in the parent block to set the minimum height, and in the img block to specify width of 100%. This will preserve the aspect ratio of the image, and its height will be either greater or as the parent, but not less than that set in the parent block. Of course, the parent block must inherit the entire screen width from its parent block or explicitly have a width of 100%. For example:
.block__image {
/*width: 100%;*/
min-height: 300px;
}
.block__image img {
width: 100%;
}
<div class="block__image">
<img src="https://i.stack.imgur.com/U1tXC.jpg" alt="image error">
</div>
I have a dynamic-height container (its height is specified in relative measurements), inside of it, two elements - a header, and an img, e.g.:
<div class="item">
<header><h1>Title</h1></header>
<img ... />
</div>
I want the image to show in its entirety. Its css is set with height:100% .
Because of the height that the header takes, the image is clipped a little bit below (it is has an hidden overflown edge), where I want its height to auto adjust (become smaller) to fit inside the container.
There is a solution, where I use calc(100%-[height of header]) for the height of the image, but since calc is not supported in all browsers I was wondering if there is a different more supported solution for this.
Here is a jsfiddle:
http://jsfiddle.net/7xLo7mr6/
(Apply the class fix to the container to apply the calc fix)
Perhaps CSS flex could be your solution for this one:
http://jsfiddle.net/7xLo7mr6/9/
Using flex-direction: column; and applying a max-width to the container (allowing the image to fill in the rest of the height after the header text while not stretching the width) could potentially solve your issue, but might cause you more troubles depending on what you're ultimately after.
Another option: http://jsfiddle.net/7xLo7mr6/11/
apply height: 7%; to the header and height: 93%; to the image
Make the clipping happen at the top of the image instead of the bottom:
http://jsfiddle.net/7xLo7mr6/13/
Apply position: absolute; to the header, give it a background: white; and width: 100%;, then apply a position: relative; to the container so that the header applies a width 100% to the container and not the body.
If you just want the image to shrink when its container shrinks, you can give it a max-width of 100%, and that will stop your image from growing so large it exceeds its container.
.item img {
height: 100%;
max-width: 100%;
}
It might be important to note that declaring height: 100% does not make elements 100% of the height of their containers, it makes them 100% of their own intrinsic height. The heights of elements are determined by their content, not the other way around. Read a full explanation here: https://stackoverflow.com/a/5658062/4504641.
http://jsfiddle.net/ingridly/337wrgj8/1/