I tried many ways to achieve this but without success.
Basically, I want to have a div element (like a card) with an image and a text under the image and the goal is to make it responsive so that when the user scales down the browser or they use their phone, this whole div does not get messed up but keeps its proportions. The goal is to have multiple card-like divs setup in a 3x3 matrix. The requirement is that no matter what image is there, it just fills the container - the image should not keep its aspect ratio if its too big, it should always be a squere.
link to current state*
(*it says I am too low level to have images in my posts)
As you can see, the current problem is that the image itself does not fill in the container but, keeps the aspect ration which means the whole container div is different height and it gets pushed to another line instead of making it 3x3. That is as far as I got.
Code is here:
.box {
max-width: 120px;
max-height: 120px;
}
.card-image {
width: 100%;
height: 100%;
max-width: 90px;
max-height: 90px;
border: 1px solid black;
}
<div class="box">
<img ng-src="{{item.img}}" ng-if="item.img" class="app-image" />
<div style="font-size:80%;">{{item.name}}</div>
</div>
I am using angular to fill in the images but that should have no impact on the solution. As far as I know, setting width and height by adding "vw"s to these css parameters is not the best way because then it keeps these values fixed and it is not really responsive
So, at the end of the day, there are two ways you can help me out:
1) with the current code I have, add some css that will make the images stretch its height so that it is the same as width
2) suggest more optimal solution
Thank you
I think the easiest way, with nice browser compatibility would be something like this:
.item {
width: 30%;
height: 0;
padding-top: 30%;
display: inline-block;
background-size: cover;
background-position: center;
}
.container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
resize: both;
overflow: auto;
}
<div class="container">
<div class="item" style="background-image: url(https://dummyimage.com/600x400/000/fff)"></div>
<div class="item" style="background-image: url(https://dummyimage.com/400x400/000/fff)"></div>
<div class="item" style="background-image: url(https://dummyimage.com/300x400/000/fff)"></div>
</div>
The image will always fill the whole container, and container will keep ratio. You will need to work a little bit on multi row layout, but still I find it the easiest way.
.card-image {
width: 100%;
height: 100%;
max-width: 90px;
max-height: 90px;
border: 1px solid black;
object-fit:fill; /* try fill,cover,contain for different results*/
}
For more info Object fit CSS tricks
Related
I am building a chat message and I want to fit an image inside the text bubble. The bubble has a fixed width and should scale its height depending on the image aspect ratio.
I am unable to scale the div to maintain the img aspect ratio. All of the answers found use an <img> tag, while I am using a div and none of that fixed my issue.
This is the desired outcome:
What I have achieved instead is either a very small img (size of an empty speech bubble if I do not impose any vertical or horizontal dimension) or a long img if I impose the width and keep the height dynamic.
.speech-right-wrapper {
max-width: 90%;
display: flex;
flex-direction: column;
}
speech-right-message-container {
display: flex;
justify-content: flex-end;
align-items: flex-start;
}
.speech-right-bubble {
position: relative;
background: rgb(154, 226, 255);
box-shadow: 0px 1px 2px gray;
border-radius: 15px 0 15px 15px;
display: flex;
}
.bubble-background {
width: 200px;
height: auto;
overflow: hidden;
}
.bubble-background-img {
position: absolute;
border-radius: 15px 0 15px 15px;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
background: no-repeat;
background-size: cover;
background-position: center;
}
<div class="speech-right-wrapper">
<div class="speech-right-message-container">
...
<div class="speech-right-bubble">
<div class="bubble-background">
<div class="bubble-background-img" v-bind:style="{ 'background-image': 'url(' + require('../assets/img/profiles/' + storyPath + bubble.bubble_background) + ')' }" v-bind:alt="bubble.bubble_background"></div>
</div>
...
</div>
...
</div>
</div>
UPDATE
For clarity, I need the <div class="bubble-background-img"> to be fix in width (say 200px) and height: auto to maintain the image aspect ratio; and I need the <div class="speech-right-bubble"> to scale to fit the image inside.
Also, unfortunately I need to use a <div> tag because v-bind:src seems not to work for local images. If I do:
<img class="bubble-background-img" v-bind:src="'../assets/img/profiles/' + storyPath + bubble.bubble_background"/>
I get this:
You should probably find a workaround for your v-bind:src issue since the correct way to display a content image is via the HTML img element.
That said, there is a solution, but it relies on using the CSS content property for element replacement, which is a fairly recent technology that's apparently still not supported in Microsoft Edge. The following CSS code is the gist of it and worked for me in testing in Firefox 68:
div { content: ('image.jpeg'); max-width: 200px; }
(In theory, a variation of this technique should also work with the more backward-compatible CSS ::before and ::after pseudo-elements, but the image inexplicably doesn't scale in my testing. I didn't spend much time experimenting though.)
I'm not a hundred percent certain what you are going for, but you could try setting the background-size as a percentage?
background-size: 100%;
background-position: center center;
Using a percentage in background size lets you scale one or more axis according to the parent container. (e.g. background-size: 100% 100%; would scale width and height, and give an effect equivalent to the contain value).
Would that work?
(Personally, I would load the image using an element as that's what they are there for, and you could use object-fit as appropriate, but obviously depends on how you've architected the view...)
I'm developping an ionic application, and i want to display some images in some cards, the problem is that my images have not the some size, and i want them to look the some.
The idea is to use à css class that will solve the problem ( at least in the width )
.full-width-image {
width: 100%
}
this class will solve the problem of size and all the images will have the some width. how ever i dont know how to make a fixed height for them all. if i add to my css class a fixed height like:
.full-width-image {
width: 100%;
height: 60px;
}
some pictures will look ugly:
how it looks like
what i want is to hide the extra part of the image.
If you have a set width and height you can use object-fit: cover; for the image to fill the entire space without losing its aspect ratio.
I would recommend you to use a flex wrapper around an image.
.wrapper {
display: flex;
justify-content: center;
align-items: center;
box-shadow: 0 0 2px gray;
width: 100px;
height: 100px;
overflow: hidden;
margin: 1em;
}
.wrapper img {
border: 1px solid black;
max-width: 100%;
max-height: 100%;
}
.example {
display: flex;
}
<div class="example">
<div class="wrapper">
<img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png?v=c78bd457575a">
</div>
<div class="wrapper">
<img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a">
</div>
<div class="wrapper">
<img src="https://upload.wikimedia.org/wikipedia/commons/e/eb/Ash_Tree_-_geograph.org.uk_-_590710.jpg">
</div>
<div>
Using this technique you get a kind of smart image - it scales itself to fit your wrapper, its fixed size, but without distortion. Look, there are black borders around the images, so you can see that both an image with width > height and an image with a tree, where height > width, fit well the wrapper, restricting the width and the height correspondingly.
Also you can you inline-flex instead of flex in the wrapper class.
I cannot figure this out. I would like 3 images to sit side by side inside a 930px wide div.
so, when you enter into responsive design mode, or drag the screen browser width wise to make it smaller all the 3 images stay side by side inside the div without wrapping to the next line.
But automatically start to re-size to fit the re-sized div.
The 3 images only start to resize correctly inside the div only when the 3rd image has wrapped under the second image. So it looks like this below.
[]
[]
[]
Once all the images are vertically aligned the images then start to shrink down correctly. But this image wrapping under the next image is no good for me, as when viewing the website on a mobile phone, or when re-sizing the screen the images are still super large.
Must be a way to stop these images from wrapping underneath each other, and just stay inline but automatically re-size themselves
as the div/page width shrinks down?
I've tried white-space: nowrap; display: inline; inline-block; even display: table-cell; nothing seems
to do what I need it to do. However, if I use only one image instead of 2, or 3 then it works perfectly fine.
You're probably thinking why not just put all 3 images inside 1 image in photoshop? Well each img is an href link, so that's not possible.
Even floating the images all to the left still doesn't help.
Here's my CSS/HTML
img {
max-width: 100%;
height: auto;
}
then
<div style="width: 930px; max-width: 100%; border: 1px solid blue;">
<img src="camera.png"> <img src="lights.png"> <img src="action.png">
</div>
Can someone tell me where I may be going wrong please? How can I stop images wrapping underneath other images when the parent container shrinks down.
I've had to resort to using multiple #media queries of different pre-fixed image sizes per break-point. But there's got to be a much much easier way. Something so simple that I'm missing.
I figure I might share a flexbox solution as well. I've included the code below so it should be relatively self explanatory. Feel free to leave a comment below if you think I should clarify anything.
.container{
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: flex-start;
}
img {
flex: 1;
max-width: 100%;
height: auto;
max-height: 310px;
}
<div class="container" style="width: 930px; max-width: 100%; border: 1px solid blue;">
<img src="https://cdn.vox-cdn.com/uploads/chorus_image/image/44336734/fujifilmx100t-1.0.0.jpg">
<img src="https://d3k7s9wfq6lao0.cloudfront.net/latest/37504/main/7.jpg">
<img src="https://upload.wikimedia.org/wikipedia/commons/3/33/Clapperboard%2C_O2_film%2C_September_2008.jpg">
</div>
you can use inline-block for this. you will need to alter the width with media queries as your screen gets smaller
img {
display:inline-block;
width: 33%;
height: auto;
}
you should also wrap the images in a div.container and give this div a width:100%
Image width set to 100% occupy all the horizontal space of the container, since you want to fit three images inline to each other, divide the 100% by 3 so that when the container is resized the three images will occupy one third of the available space. The margin-left: -2px is to make sure that the image border don't touch the edge, otherwise it will wrap to new line. Try this sample:
CSS:
img {
display: inline-block;
width: 33%;
height: auto;
margin-left: -2px;
box-sizing: border-box;
}
HTML element:
<div style="width: 930px; max-width: 100%; border: 1px solid blue;">
<img src="camera.png">
<img src="lights.png">
<img src="action.png">
</div>
My answers' more or less a follow up to Tom's which I'm writing on here so I don't overflow the comments section.
The problem with max-width: 100% is that the relative sizing doesn't start to kick in until each image outgrows its parent, in this case, the div. Since all images have a default absolute size based on their image src they force themselves onto a new line before resizing and so only then will max-width start doing what you want it to. As per Tom's response, the percentage sizing of 33% forces the images to have a relative size which causes them to shrink immediately.
Naturally 'img' tags are given the display of inline which means you could opt to just use the following code:
img {
width: 33.3%;
}
Now here's the biggest gotcha I had when dealing with inline images.
A display of inline and inline-block is respective of the whitespace
that exists within your HTML markup.
Therefore the small presence of whitespace below whilst not evident is enough to cause images to still move over to a new line.
img {
width: 33.3%;
}
<div style="width: 930px; max-width: 100%; border: 1px solid blue;">
<img src="https://picsum.photos/250/250/?random1">
<img src="https://picsum.photos/250/250/?random2">
<img src="https://picsum.photos/250/250/?random3">
</div>
But once this whitespace is removed the images all fit perfectly across the screen whilst resizing.
img {
width: 33.3%;
}
<div style="width: 930px; max-width: 100%; border: 1px solid blue;"><img src="https://picsum.photos/250/250/?random1"><img src="https://picsum.photos/250/250/?random2"><img src="https://picsum.photos/250/250/?random3"></div>
Now compressing the HTML markup above makes it rather unwieldy and so as an alternative, you could opt to use the floating method. By setting a float of left for each image you'll force each 'img' tag to sit flush, regardless of the extra spacing between them. Just be sure to give the parent div a float of left as well or an overflow of auto to stop it from collapsing.
img {
width: 33.3%;
float: left;
}
After many days testing various ways out here's the perfect way to do this without flex. Make sure each image is wrapped in its own div that's important.
<style>
* {
box-sizing: border-box;
}
img {
width: 100%;
max-width: 100%;
height: auto;
}
.column {
float: left;
width: 33.33%;
padding: 5px;
}
/* Clearfix (clear floats) */
.row::after {
content: "";
clear: both;
display: table;
}
</style>
Now, here's where I've changed it up a little bit for more flexibility. Since each image is now in its own div we can then make the image width: 100%; or max-width: 100%; then add the width: 33.33%; part that used to be under img {} to each of the new 3 div columns instead.
<div class="row">
<div class="column"> /* 33.33% width */
<img src="flash-tooltip.png">
</div>
<div class="column"> /* 33.33% width */
<img src="html-tooltip.png">
</div>
<div class="column"> /* 33.33% width */
<img src="portables-tooltip.png">
</div>
</div>
Lot's of people provided great advice.
The easiest way is using flex. But, something people don't tell you when using flexbox. You should still wrap each of the images inside their own div container. Otherwise, you will get some weird things happening when you encase them in hyperlink anchors, that is if all three images are just placed inside the first flex container div. And without their own div container images won't keep any kind aspect ratio when they shrink/enlarge. They just squash and skew together.
And finally very important! Always make sure any images inside a flex container is set up the same way. Either width: 100%; or max-width: 100%; otherwise, the images will not shrink up/down at all in Google Chrome.
I've included this same method as above, only this time in a flexbox version.
I have the following recurring problem that I've not been able to find an effective solution for. Others must have come across the same issue but despite searching I cannot seem to find the exact issue, although it must be very commonplace. Hopefully this question will be useful for many developers.
I am aiming to fill and center an image that is within a container div. The images may be portrait, landscape or square and have different aspect ratio's/sizes that are all variable. The container div has a fixed height but a percentage based width, so is also variable.
I am finding that with the below code the images are scaled extremely large, and any adjustment to the code results in stretching of the aspect ratio, which is not desirable. Of course cropping is inevitable but I'd like to find the best way to minimise this and display all images in the best light possible. I've added a red background to the container div as I do not want any of this to show in any instance.
I'm open to any resolutions that might be out there.
Fiddle
Live Example of problem (scale browser to see)
HTML
<div class="container">
<img src="http://lorempixel.com/1000/500/">
</div>
<div class="container">
<img src="http://lorempixel.com/500/1000/">
</div>
<div class="container">
<img src="http://lorempixel.com/500/500/">
</div>
CSS
.container {
width: 40%;
height: 350px;
display: inline-block;
float: left;
background: red;
overflow: hidden;
margin: 10px;
}
.container img {
display: block;
width: auto;
min-width: 100%;
height: auto;
min-height: 100%;
}
I've asked this question before (sort of), and the answer wasn't able to help me do what I'm trying to do. After working on this website more, and countless hours trying to figure out the solution to this (I'm not even entirely sure it can be done), I'm back trying to figure this out. It's the centerpiece for the home page, so it's kind of important it works the way I want, visually.
The problem:
I have two "modules" (displayed as table cells) in a container (displayed as a table). I have created this jsfiddle as a way to show how the model will interact with a landscape image and portrait image. I'll go ahead and list the requirements.
The content container should have a minimum width of 30% - 30px (10px padding and a border of 20px on the right) of the container.
If the photo isn't big enough to take up 70% of the container, the content container width should grow and photo container width shrink.
The height of the content container (which will essentially be a news/blog post) should never be taller or shorter than the image. If the contents overflow, they should be scrollable.
To prevent this block from being absolutely super tall, it shouldn't have a height over 1000px (I'm think maybe setting the image max-height would be the way to say this.
I feel like I've been all over the internet trying to figure out how to do this, and I have had no luck.
Below is mark-up and styling:
<div id="container">
<div class = "content">
<h5>
blah
</h5>
</div>
<div class = "image">
<img src="http://www.blah.com/blah.jpg" />
</div>
</div>
#container {
display: inline-table;
width: 100%;
border-bottom: 20px solid #cc0000;
}
#container .content {
display: table-cell;
vertical-align: top;
min-width: calc(30% -40px);
border-right: 20px solid #383838;
padding: 10px;
background: #eee;
max-height: 100%;
overflow:scroll;
}
#container .image {
display: table-cell;
width: 70%;
padding: 0px;
background: #ccc;
max-height: 100%;
}
img {
max-width: 100%;
}