I have a problem with the flexbox. The image inside should fit into the outer box without overflow. The first and last works perfectly, but the second overflows at the top and the bottom.
How could I fix this?
.outer {
border: 1px solid red;
margin: 25px;
width: 160px;
height: 160px;
display: flex;
justify-content: center;
align-items: center;
}
.outer img {
max-width: 100%;
}
<div class="outer">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/16x9_by_Pengo.svg/220px-16x9_by_Pengo.svg.png" />
</div>
<div class="outer">
<img src="http://www.thepixiecollective.com/files/imagecache/product_full/product_images/blue.png" />
</div>
<div class="outer">
<img src="http://41.media.tumblr.com/fa335632f1b474dd55493757839d2a3a/tumblr_n0ukv5MLqG1qz5uc4o1_500.jpg" />
</div>
This is because the height of the second image is greater than the width. The width of the first and third images is either greater than or equal to the height so are constrained by max-width: 100%; which ensures they will never exceed the width of the parent container.
To fix make the following changes to css:
Add max-height: 100%; to .outer img - This will ensure the height of the image can never exceed the height of the container
.outer {
border: 1px solid red;
margin: 25px;
width: 160px;
height: 160px;
display: flex;
justify-content: center;
align-items: center;
}
.outer img {
max-height: 100%;
max-width: 100%;
}
<div class="outer">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/16x9_by_Pengo.svg/220px-16x9_by_Pengo.svg.png" />
</div>
<div class="outer">
<img src="http://www.thepixiecollective.com/files/imagecache/product_full/product_images/blue.png" />
</div>
<div class="outer">
<img src="http://41.media.tumblr.com/fa335632f1b474dd55493757839d2a3a/tumblr_n0ukv5MLqG1qz5uc4o1_500.jpg" />
</div>
You should insert your image in CSS, it's easier to have this behaviour.
.outer {
border: 1px solid red;
margin: 25px;
width: 160px;
height: 160px;
}
#pengo {
background-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/16x9_by_Pengo.svg/220px-16x9_by_Pengo.svg.png');
}
#blue {
background-image: url('http://www.thepixiecollective.com/files/imagecache/product_full/product_images/blue.png');
}
#tumblr {
background-image: url('http://41.media.tumblr.com/fa335632f1b474dd55493757839d2a3a/tumblr_n0ukv5MLqG1qz5uc4o1_500.jpg');
}
HTML
<div id="pengo" class="outer"></div>
<div id="blue" class="outer"></div>
<div id="tumblr" class="outer"></div>
Then play with background-position and background-size (see MDN) to do place the images, for example:
background-position: center;
background-size: cover; /* or contain*/
Related
I was trying to center an image right in between 2 different buttons, the left button & right button with the image in the middle. All my efforts have failed.
Below here is the code snippet of the image I centered:
html,
body {
height: 100%;
}
.parent {
height: 750px;
background: #CCCCCC;
display: flex;
align-items: center;
justify-content: center;
}
.child {
width: 100px;
height: 100px;
}
<div class="parent">
<div class="child">
<img src="https://i.postimg.cc/26K2ZdHb/juice.jpg" height="200px" width="200px" alt="picture" />
</div>
</div>
My goal
My goal was to have the image in the middle of 2 buttons like in this edited screenshot
You can force your images width and height to fit-content on the image element => child element.
html,
body {
height: 100%;
}
button {
background-color: skyblue;
width: 100px;
height: 50px;
border: 8px solid black;
}
.parent {
height: 750px;
background: #CCCCCC;
display: flex;
align-items: center;
justify-content: center;
}
.flex-child:not(:nth-of-type(1)) {
margin-left: 10px;
}
.child {
margin-left: 10px;
width: fit-content;
height: fit-content;
}
<div class="parent">
<button class="flex-child"></button>
<div class="child flex-child">
<img src="https://i.postimg.cc/26K2ZdHb/juice.jpg" height="200px" width="200px" alt="picture" />
</div>
<button class="flex-child"></button>
</div>
Remove widhs and heights from your elements unless strictly necessary, and then use flex with space-between or space-evenly or space-around on your parent to spread the three children out horizontally. You could remove the divs from around the two buttons, it will work without. I just like to keep divs around "columns" like this, Bootstrap-style:
.parent {
background: #CCCCCC;
display: flex;
align-items: center;
justify-content: space-evenly;
}
.child {
/* width: 100px;
height: 100px; */
}
button {
background: blue;
padding: 0.5rem 1.8rem;
border: 0;
color: #fff;
border-radius: 4px;
}
<div class="parent">
<div class="child">
<button>Button to the left</button>
</div>
<div class="child">
<img src="https://i.postimg.cc/26K2ZdHb/juice.jpg" height="200px" width="200px" alt="picture" />
</div>
<div class="child">
<button>Button to the right</button>
</div>
</div>
Your code has no big flaw at all.
You just messed up the image size.
Look that image is 200px wide and high, but child class only 100px.
Just fix that and everything goes well.
html,
body{
height: 100%;
}
.parent {
height: 750px;
background: #CCCCCC;
display: flex;
align-items: center;
justify-content: center;
}
.child {
width: 200px;
height: 200px;
padding-left: 1em;
padding-right: 1em;
}
.buttons {
background-color: skyblue;
width: 10em;
height: 5em;
border: 8px solid black;
}
<div class="parent">
<button type="button" class="buttons"></button>
<div class="child">
<img src="https://i.postimg.cc/26K2ZdHb/juice.jpg" height="200px" width="200px" alt="picture" />
</div>
<button type="button" class="buttons"></button>
</div>
I make row with items. Each item contains a title, image, and button. Images keep their aspect-ratio.
I dont understand why wrapper add empty space.
Sandbox:
https://codepen.io/krosert/pen/QWNNVxg
Now result:
Expected Result:
code:
<div class="panel">
<div class="item">
<span class="title">first item</span>
<img src="https://i.ibb.co/JQMJ3BW/2311f3c1-2802-417f-9b7e-2147f066e260.jpg">
<div class="btns">
<button>1</button>
<button>2</button>
<button>3</button>
</div>
</div>
<div class="item">
<span class="title">second item</span>
<img src="https://i.ibb.co/wMyyz1n/934tvi5uykv2.jpg">
<div class="btns">
<button>1</button>
<button>2</button>
<button>3</button>
</div>
</div>
</div>
.panel{
position: fixed;
background-color: #685;
top: 30px;
height: 200px;
display: flex;
width: 100%;
}
.item{
margin: 6px;
border: 2px solid black;
background-color: #553;
display: flex;
flex-direction: column;
align-items: flex-start;
box-shadow: 0 0 5px;
max-width: 300px;
}
img {
max-height: 100%;
max-width: 100%;
height: auto;
width: auto;
min-height: 0;
min-width: 0;
}
remove align-items: flex-start; and add object-fit: cover; object-position: top;
to img
remove this line:
.items {
align-items: flex-start;
}
What you are doing is telling the items element is to push the images to the start of their parent container column. Leaving the rest of the width as empty space.
To solve the issue with the image sizes overflowing their container, set a maximum height to the .items div:
.items{
max-height: 95%;
}
Then set your images to not have a larger height than would cause it to overflow:
img {
max-height: 140px;
object-fit: contain;
}
On my webpage there is an area and I'd like to add a image to it. I don't know the image's size and orientation (portrait or landscape). But I want it to fit the area as it is displayed in the picture:
So, if an image has a landscape orientation it must fill the whole width of the area. See picture 1. If the image's width is bigger that the area's width the image's width must be constrained and if its width is smaller - the image must be widened. However if the image's height is bigger than the area's one the image's height must be constrained. See picture 2.
The similar I want for the portrait image. See picture 2.
In short, what I want can be easily done with object-fit: contain;.
.wrapper {
width: 30%;
height: 400px;
overflow: hidden;
border: 1px solid black;
position: relative;
}
.img {
width: 100%;
height: 100%;
object-fit: contain;
}
.label {
position: absolute;
top: 0;
right: 0;
padding: 15px;
background-color: #cccccc;
}
<div class="wrapper">
<img class="img" src="https://images.unsplash.com/photo-1500622944204-b135684e99fd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80" alt="">
<span class="label">Label</span>
</div>
Here is the CodePen: see the code
But the problem is that I have a label to each picture and I want it to be on the top-right corner of the picture and not the area.
Is there any way to do this with CSS only?
Any help would appreciated! Thank you in advance!
instead of the object-fit: contain; replace it with background-size:cover in the img selector css file.
You can wrap the image with a div that has a display: inline-block rule, that will force the div to fit the image scale, then, in this div add another div for the label and position it with absolute.
.cont {
width: 300px;
height: 250px;
background-size: contain;
background-repeat: no-repeat;
margin: 20px;
border: 3px solid black;
display: flex;
align-items: center;
justify-content: center;
}
div .image-cont {
display: inline-block;
position: relative;
}
img {
max-width: 300px;
max-height: 250px;
width: auto;
height: auto;
}
.label {
background-color: yellow;
padding: 5px;
position: absolute;
top: 0;
right: 0;
}
<div class="cont">
<div class="image-cont">
<img src="https://image.shutterstock.com/image-photo/beautiful-abstract-grunge-decorative-navy-260nw-539880832.jpg" />
<div class="label">Label</div>
</div>
</div>
<div class="cont">
<div class="image-cont">
<img src="https://i.pinimg.com/originals/1b/30/80/1b30806bed30a7d071752948d00e75f8.jpg" />
<div class="label">Label</div>
</div>
</div>
You can do the following:
Wrap image and .label span with another span with class e.g. .inner-wrapper and add to its css
position: relative;
height: 100%;
Remove from .wrapper css position: relative; and add
display: flex;
justify-content: center;
Replace in .img css width: 100%;height: 100%; with max-width: 100%;max-height: 100%;
Look in the snippet in full page mode and resize the window.
.wrapper,
.wrapper200 {
width: 30%;
height: 400px;
overflow: hidden;
border: 1px solid black;
/*position: relative;*/
display: flex;
justify-content: center;
}
.wrapper200 {
height: 200px;
}
.inner-wrapper {
position: relative;
height: 100%;
}
.img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.label {
position: absolute;
top: 0;
right: 0;
padding: 15px;
background-color: #cccccc;
}
/* for visual illustration */
.container {
display: flex;
justify-content: space-evenly;
padding: 10px;
outline: dashed red 1px;
margin-bottom: 25px;
}
<h1>Heigth: 200px</h1>
<div class="container">
<div class="wrapper200">
<span class="inner-wrapper">
<img class="img" src="https://images.unsplash.com/photo-1500622944204-b135684e99fd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80" alt="">
<span class="label">Label</span>
</span>
</div>
<div class="wrapper200">
<span class="inner-wrapper">
<img class="img" src="https://images.unsplash.com/photo-1581622634376-ff17d073c4f7?ixlib=rb-1.2.1&auto=format&fit=crop&w=1832&q=80" alt="">
<span class="label">Label</span>
</span>
</div>
</div>
<h1>Heigth: 400px</h1>
<div class="container">
<div class="wrapper">
<span class="inner-wrapper">
<img class="img" src="https://images.unsplash.com/photo-1500622944204-b135684e99fd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80" alt="">
<span class="label">Label</span>
</span>
</div>
<div class="wrapper">
<span class="inner-wrapper">
<img class="img" src="https://images.unsplash.com/photo-1581622634376-ff17d073c4f7?ixlib=rb-1.2.1&auto=format&fit=crop&w=1832&q=80" alt="">
<span class="label">Label</span>
</span>
</div>
</div>
You should try to use background-image instead of a single image
.wrapper {
width: 30%;
height: 400px;
overflow: hidden;
border: 1px solid black;
position: relative;
}
.img {
width: 100%;
height: 100%;
object-fit: contain;
background-size: contain;
background-repeat: no-repeat;
position: absolute;
top: 10%;
}
.label {
position: absolute;
top: 0;
right: 0;
padding: 15px;
background-color: #cccccc;
}
<div class="wrapper">
<div class="img" style="background-image:url(https://images.unsplash.com/photo-1500622944204-b135684e99fd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&w=1000&q=80)" alt="">
<span class="label">Label</span>
</div>
</div>
Scenario :
I am having trouble getting an image to autofit a flexbox with a border around it. The image will be dynamically generated so sometimes the width or the height might be the longer side. Sometimes the image will be smaller or larger than the box it should be in, but it should automatically fit the size of the box and retain its proper proportions.
Tried Case :
The best I've come up with is to set both width and height of the image to 100%, and then use object-fit: contain.
However, object-fit: contain does not work well with borders. Instead of surrounding just the image the border is surrounding the entire parent div.
The Problem: If there is a tall skinny image it might enlarge or shrink to 30% width and 100% height. I would like the border to be also at the 30% and 100% region as well. However, the border is being placed at the 100% width and 100% height area which is not what I want.
What other method would work better for me here?
Here is a simplified look at my code:
<!DOCTYPE html>
<html>
<style>
html, body { width: 100%; height: 100% }
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
}
#second img {
border: solid black 5px;
object-fit: contain;
width: 100%;
height: 100%;
box-sizing: border-box;
}
</style>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<img src="https://via.placeholder.com/350x800/faa">
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
If you run the above code snippet you will see the thick border is surrounding the entire parent region (shown in yellow), rather than just appearing around the image itself (pink area).
What can I do so that the border is only around the image itself?
Clarification
I need something that meets the following criteria:
Smaller images are scaled up to meet the size of the parent div
Larger images are scaled down to meet the size of the parent div
Images should be proportional (i.e. images must retain their aspect ratio and not become distorted)
The image should be centered within the parent div
The image should have a border only around the image and not the larger area
Code must work for both portrait and landscape images
In most cases only two sides of the image will touch the parent boundary, leaving the rest of the parent div empty (i.e. the yellow background in my code sample)
I'm actually quite surprised given how far CSS has come that there seems to be no simple solution for this.
Do you want only with height 100%? If not height 100% is depend on image's prop, you can use object-fit: fill; and height:auto;
<!DOCTYPE html>
<html>
<style>
html, body { width: 100%; height: 100% }
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
}
#second img {
border: solid black 5px;
object-fit: contain;
width: 100%;
height: auto;
box-sizing: border-box;
}
</style>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<img src="https://picsum.photos/800/800">
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
Used object-fit: cover
so that the image will cover the entire parent.
Other solution will be inserting an image already having a border on it.Image can be edited online to attach a border to itself.
<!DOCTYPE html>
<html>
<style>
html, body { width: 100%; height: 100% }
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
}
#second img {
border: solid black 5px;
object-fit: cover;
width: 100%;
height: 100%;
box-sizing: border-box;
}
</style>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<img src="https://via.placeholder.com/350x800/faa">
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
Updated Solution:
So, to achieve this, we can put image inside a container that will be
take height and width according to image. Put this image container div inside the main div container.
So, in this case, we have put the following code into #second conatiner, and adjusted the corresponding css to achieve the desired result.
html, body { width: 100%; height: 100% }
img {
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
transform: translate(-50%, -50%);
position: relative;
left: 50%;
top: 50%;
}
#testing {
display: inline-block;
/* text-align: center; */
}
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
display: flex;
margin: 0 auto;
justify-content: center;
}
#second img {
border: solid black 5px;
object-fit: contain;
box-sizing: border-box;
}
<!DOCTYPE html>
<html>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<div id='testing'>
<img src="https://via.placeholder.com/1000x350/faa">
</div>
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<div id='testing'>
<img src="https://via.placeholder.com/350x1000/faa">
</div>
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
did you mean something like this?
changes are, move width: 100% and height: 100% to parent, add max-height: 100% on img, and add text-align: center on parent
update:
- add another div inside #second
- make #second display: flex; flex-direction: column; justify-content: center
- add max-width: 100% to img
- add max-height: 100%; max-width: 100%; height: fit-content; to the added div
html, body { width: 100%; height: 100% }
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
width: 100%;
height: 100%;
text-align:center;
display: flex;
flex-direction: column;
justify-content: center;
}
#second img {
border: solid black 5px;
box-sizing: border-box;
max-height: 100%;
max-width: 100%;
}
#vcenter{
max-height: 100%;
max-width: 100%;
height: fit-content;
}
<!DOCTYPE html>
<html>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<div id="vcenter">
<img src="https://via.placeholder.com/350x800/faa">
</div>
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
same code for landscape images
html, body { width: 100%; height: 100% }
#outer {
width: 100%;
height: 100%;
display: flex;
background-color: green;
flex-direction: column
}
#top, #bottom {
flex: 1;
display: flex;
border: solid black 1px;
}
#first, #third {
flex: 1;
background-color: blue;
}
#second {
flex: 3;
background-color: yellow;
width: 100%;
height: 100%;
text-align:center;
display: flex;
flex-direction: column;
justify-content: center;
}
#second img {
border: solid black 5px;
box-sizing: border-box;
max-height: 100%;
max-width: 100%;
}
#vcenter{
max-height: 100%;
max-width: 100%;
height: fit-content;
}
<!DOCTYPE html>
<html>
<body>
<div id="outer">
<div id="top">
<div id="first">First</div>
<div id="second">
<div id="vcenter">
<img src="https://via.placeholder.com/1350x200/faa">
</div>
</div>
<div id="third">Third</div>
</div>
<div id="bottom">
Bottom
</div>
</div>
</body>
</html>
I have a container that is 100vh (minus the fixed nav height).
<section class="container">
Inside this container I have some text:
<div class="text">
<p>title</p>
</div>
Which can be of any length as the content is dynamic.
Below this text I have an image:
<div class="image">
<img src="https://s-media-cache-ak0.pinimg.com/736x/d1/a6/64/d1a664bca214bf785a293cbc87950fc4.jpg">
</div>
The image needs to fill the rest of the 100vh (- nav height) container.
I use:
.container{
display:flex;
flex-flow: column nowrap;
....
Fiddle
The issue I am having is that I need the image to be the height of the rest of the space.
How can I do this? In my fiddle, if your screen is small it is being cut off and if your screen is large it does not fill the space. Height: 100% fails to work, making it too large.
Flex solutions only please, no table tricks - thanks!
Make the image container (.image) a flex container with height: 100%.
You can then fine-tune the image's aspect ratio and alignment with object-fit / object-position.
nav {
position:fixed;
background:grey;
width:100%;
height: 100px;
}
main {
padding-top: 100px;
}
.container {
display:flex;
flex-flow: column nowrap;
height: calc(100vh - 100px);
background: green;
border: 3px solid brown;
}
.text { background: yellow; }
/* ***** NEW ***** */
.image {
display: flex;
justify-content: center;
height: 100%;
}
img {
width: 100%;
object-fit: contain;
}
<nav>Nav</nav>
<main>
<section class="container">
<div class="text"><p>title</p></div>
<div class="image">
<img src="https://s-media-cache-ak0.pinimg.com/736x/d1/a6/64/d1a664bca214bf785a293cbc87950fc4.jpg">
</div>
</section>
<section class="container">
<div class="text"><p>hello</p></div>
<div class="image">
<img src="https://s-media-cache-ak0.pinimg.com/736x/d1/a6/64/d1a664bca214bf785a293cbc87950fc4.jpg">
</div>
</section>
</main>
Revised Fiddle
Note that the object-fit property is not supported by IE. For more details and a workaround see: https://stackoverflow.com/a/37127590/3597276
Maybe not exactly what you wanted, but if you move the image to a div and use it as a background, you can get the desired effect.
Fiddle
HTML:
Nav
title
<section class="container">
<div class="text">
<p>hello</p>
</div>
<div class="imageWrap">
<div class="image"></div>
</div>
</section>
</main>
CSS:
nav {
background: grey;
width: 100%;
height: 100px;
position: fixed;
}
main{
padding-top: 100px;
}
.container{
display: flex;
flex-flow: column nowrap;
height: calc(100vh - 100px);
background: green;
border: 3px solid brown;
}
.imageWrap {
flex: 1;
display: flex;
}
.image {
flex: 1;
background-size: contain;
background-repeat: no-repeat;
background-image: url(https://s-media-cache-ak0.pinimg.com/736x/d1/a6/64/d1a664bca214bf785a293cbc87950fc4.jpg)
}
.text{
background: yellow;
}