I have a div within which I would like to put any arbitrarily-sized image, preferably using an img tag rather than the CSS background-image style. I've looked at many other similar questions and none have answered my question.
The way I would like the image to display is this:
If the image is portrait (height is greater than width), the image will have a width of 100% within the div and be vertically centered. The extra height will be outside of the div, but not visible (as in, the image would appear 'cropped'.)
If it is landscape, the properties in #1 would apply, but horizontally instead of vertically.
I do not want to stretch the image. I do want to fill the entire space within the div.
An example of this would be the image boxes that appear on imgur.com.
Try centering it with javascript. Just set the position: absolute, left:50%, top:50% and margin-left:-width/2, margin-top:-height/2
I'm surprised this question doesn't have an easy to find answer anywhere online, but I came up with a (mostly) pure CSS solution that might help someone. The idea is that there are two possible sizes for the image:
Width is 100% of the parent, height is determined by aspect ratio
Height is 100% of the parent, width is determined by aspect ratio
Of these two options, the one that is preferred is simply the bigger one, since the smaller one will leave gaps around the edges. Therefore, we can use a div in between container and image to "calculate" the larger size. Here's my code:
const image = document.getElementById("image");
const sizer = document.getElementById("sizer");
image.onload = () => {
const aspectRatio = image.width / image.height;
sizer.style = `aspect-ratio: ${aspectRatio}`;
};
#container {
position: relative;
overflow: hidden;
width: 400px;
height: 250px;
resize: both;
}
#sizer {
min-width: 100%;
height: 100%;
position:absolute;
left:50%;
top:0px;
transform: translate(-50%,0);
}
#image {
width: 100%;
height: auto;
position:absolute;
left:0;
top:50%;
transform: translate(0,-50%);
}
<div id="container">
<div id="sizer">
<img id="image" src="https://www.industrialempathy.com/img/remote/ZiClJf-1920w.jpg"/>
</div>
</div>
Try dragging around the corner of the image to check how it works.
The only JS required is to fix the aspect ratio of the sizer, and it's quite lightweight (only required when the image src is loaded). I believe this will also work across almost all browsers and versions, since the CSS is very basic.
Hope this helps someone!
Related
I have a avatar image for company logos. I want it to be round but due to sizing of the images it cuts off some of the image. I have thousands of these logos and I am looking for any Ideas on how to fix this.
The Ideal end result would be the logo centered in the circle with the least amount of overlap. I though about just adding extra background space and making the image smaller unfortunately the logos have different color backgrounds. Thanks for your time!
div {
border-radius: 50%;
width: 200px;
height: 200px;
outline: 2px dotted black;
overflow: hidden;
}
img {
height: 100%;
}
<div>
<img src="https://www.vectorlogo.zone/logos/stackoverflow/stackoverflow-tile.svg" alt="logo">
</div>
Use object-fit: cover.
Example:
img {
width: 200px;
height: 300px;
object-fit: cover;
}
The CSS object-fit property is used to specify how an <img> or <video> should be resized to fit its container.
This property tells the content to fill the container in a variety of ways; such as "preserve that aspect ratio" or "stretch up and take up as much space as possible".
The object-fit property can take one of the following values:
fill - This is default. The image is resized to fill the given dimension. If necessary, the image will be stretched or squished to fit
contain - The image keeps its aspect ratio, but is resized to fit within the given dimension
cover - The image keeps its aspect ratio and fills the given dimension. The image will be clipped to fit
none - The image is not resized
scale-down - the image is scaled down to the smallest version of none or contain
When viewing a website with Chrome for Android, the height of the view-area changes as soon as scrolling causes the URL-bar to hide. When using a fixed background image, this results in annyoing resizing of the image, initially when scrolling down, and also when the user scrolls up again, which enables to URL-bar again.
This topic has already been discussed here:
Background image jumps when address bar hides iOS/Android/Mobile Chrome
There was also a 'fix' announced, that recommends the use of vh instead of % to describe the height of the image:
https://developers.google.com/web/updates/2016/12/url-bar-resizing
Given now a site that contains a fixed background image:
<html>
<head>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="content">
<div style="padding-bottom:2000px; width:100%;">Test</div>
<div>Test again</div>
</div>
</body>
</html>
using the following CSS:
html, body {
margin: 0;
padding: 0;
}
div {
color:white;
font-size: 30px;
}
#content {
background: url(https://images.freeimages.com/images/large-previews/01a/technology-background-1632715.jpg) no-repeat right 15% center fixed;
background-size: cover;
}
will rescale the background image as described above, using Google Chrome for Android. Here is a Fiddle.
The methods determined to solve this (see linked JS-thread) make use of JavaScript to determine the window height after resizing of the window has taken place and then update the image height. However, it won't stop the background image from resizing without leaving a part of the page blank.
In order to keep the background image in place, two methods seem suitable:
preventing the URL-bar to hide
render the image with an initial offset to be able to compensate the image shift
Preventing the URL-bar to hide
In order to keep the URL-bar visible all the time, I created a fixed-div that contains a scrollable div-container:
<div id="content">
<div id="fixed">
<div id="scroller">
<div style="padding-bottom:2000px; width:100%;">Test</div>
<div>Test again</div>
</div>
</div>
</div>
CSS:
#fixed {
height:100vh;
width:100vw;
overflow:hidden;
}
#scroller {
overflow-y: auto;
height:100vh;
}
The idea is that since the user is not scrolling the website-body, the URL-bar won't disappear. This Even though this works on my emulator, it doesn't work on a real Galaxy S20. A user would be able to hide the URL-Bar after scrolling to the bottom of the page (the div).
Rendering the image with an initial offset to be able to compensate the image shift
The other idea was to draw the background image 'deeper' by default:
background-size: auto calc(100vh + 100px);
If there is "unused" space on top of the image, it should be possible to catch the resize- or touchmove-event, compare the new window height to the initial window height and then compensate the offset. Unfortunately, this will only affect the y-dimensions of the image and I would probably need to do the same for the x-axis or rescale the image again. However, when trying to determine the current image size in JavaScript (using jQuery, see this thread), I ran into another error; retrieving the image-size via $('#background').css('background-size') returned just auto and ignored the second part.
Most threads about this topic are older than five years. Can someone enlighten me and tell me there is a way to manage this by now?
Update:
I was able to eliminate the resizing using the following technique:
Assuming portrait-mode is active, I calculated the image width from the scaled image height and set the background-size to pixel values:
var initHeight = '';
var initWidth = '';
var imageHeight = 982;
var imageWidth = 1500;
var cssHeight;
var cssWidth;
$(window).on('resize', function () {
if (initHeight == 0) {
initHeight = $(window).height();
initWidth = $(window).width();
cssHeight = parseInt($('#content').css('background-size').split(" ")[1].slice(0,-2));
cssWidth = cssHeight / imageHeight * imageWidth;
$('#background').css('background-size', cssWidth + "px " + cssHeight + "px");
}
Now the background image won't scale, but it will move vertical when toggling the URL-bar.
To get rid of this, I make use of the second method described above and draw the background image with an initial offset:
background: url(../images/bg.jpg) no-repeat right 15% top -100px;
background-size: auto calc(100vh + 200px);
As soon as a resize-event occurs, I update the background image position:
let newHeight = $(window).height();
let newWidth = $(window).width();
let diff = newHeight - initHeight;
$('#background').css('background-position', "85% " + (startHeightOffset + diff) + "px")
This seems to work in my emulator. The background image stays in place now. However, when switching devices, I noticed that this approach works only for devices that have no toolbar in the bottom. Emulating a Galaxy S9, which has a URL-bar on the top as well as a toolbar on the bottom, the background image gets shifted too much, since the space acquired by both toolbars (top and bottom) will be added to the top of the image. In order to make this work, I would need to determine the height of the top URL-bar only and I genuinely don't know if this is possible.
Again, in order to solve this problem, one of the following problems must be solved:
reliably prevent hiding of the URL-bar
determining the height of the bottom toolbar
Update 2:
I was able to prevent hiding of the URL bar like so:
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: scroll;
}
body {
-webkit-overflow-scrolling:touch;
}
#content {
width: 100%;
height: 100%;
background: url(https://images.freeimages.com/images/large-previews/01a/technology-background-1632715.jpg) no-repeat right 15% center fixed;
background-size: cover;
}
#fixed {
height:100%;
width:100vw;
overflow:hidden;
}
#scroller {
overflow-y: auto;
height:100vh;
}
The background image stays in place, since the URL-bar will never collapse. However, this isn't the ideal solution and it would be great if there would be a way to make this work without the need of preventing the URL-bar to collapse.
I recently learned about the background-size property thanks to this topic
Set size on background image with CSS?
As you can guess, I am trying to make a background image take up the full screen and no more/no less. Here is my fiddle
https://jsfiddle.net/1x7ytdaa/
document.body.style.backgroundImage = "url('http://www.crystalinks.com/ColosseumNight2.jpg')";
document.body.style.backgroundSize = "contain";
Here is what the contain property does
Scale the image to the largest size such that both its width and its height can fit inside the content area
It shouldn't matter what size the image is. If it's smaller, it should be scaled to the full size of the screen. If it's larger, it should be scaled down.
In the fiddle, you can see that the image is repeated 5 times horizontally and 5 1/2 times vertically.
I've tried 100% 100% and while the width stretches the full screen, it still shows the same image 5 1/2 times vertically
I can not explain this behavior. Does anyone have any ideas?
Two things:
background-repeat
width and height of body
As you can in an edited fiddle, the problem is that the default value of background-repeat is repeat. Therefore, the image will be repeated rather than stretched. That doesn't solve everything, though, as the body and HTML elements should have a width defined that is 100%.
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
document.body.style.backgroundImage = "url('http://www.crystalinks.com/ColosseumNight2.jpg')";
document.body.style.backgroundSize = "contain";
document.body.style.backgroundRepeat = "no-repeat";
If you want to cover the whole screen, use cover instead of contain. Cover makes sure that the element is completely covered, whereas contain simply makes sure that the background image is maximally contained (which can cause white space).
This might help:
position: fixed;
background-position: center;
overflow-x: hidden;
width: 100%;
height: 100%;
background: url(img/xxx.jpg);
background-size: 100%;
background-attachment: fixed;
overflow-y: scroll;
I got a problem with scaling my svg pictures. Actually, I'm creating a design for a html cardgame.
Here is a picture of the window:
The scaling is correct, because there is enough space in both directions, so the svg fills the space.
But when I'm gonna resize the window and the width gets smaller and smaller, something like that happens:
So, the scaling of the picture svg itself is correct, but html/css thinks that the image is the whole part inside of the displayed border lines. I just took the image with a drag'n'drop to visualize the problem.
HTML: (just a part, here the last row)
<div id="playerRow">
<img id="playerCard2"/>
<img id="playerCard3"/>
<img id="playerCard4"/>
<img id="playerCard5"/>
</div>
CSS:
#playerRow{
display:flex;
flex-direction:row;
justify-content: center;
align-items: center;
background-color: forestgreen;
border-style: solid;
border-radius: 20px;
height: 45%;
}
#playerCard1, #playerCard2, #playerCard3, #playerCard4, #playerCard5 {
min-width:0px;
min-height:0px;
height:90%;
margin:1vh;
border-style: dashed;
border-color: #555555;
border-radius: 15px;
}
I'm quite sure that there is a mistake with the height. Because when I put the height from 90% down to 40% it looks better for the resized width-low window.
I tried to use max-height instead height, but that doesn't make any difference.
What could be the problem? I just want to scale the border lines to the size of the image. I tried also with javascript a kind of rescaling, but the problem is, that I can't get the height of the svg, it always takes the whole part. Furthermore, I also want to know if that problem is possible to solve only in CSS.
EDIT:
The last row with the ratio css trick:
I solved my problem.
First of all, I used the CSS-ratio trick, which is described here: Responsively change div size keeping aspect ratio
But the problem still appeared, because the width was responsible for the resolution. So when the width grows, the height grows too, that's correct, because it always takes care of the defined ratio. The only thing is, that the correct width has to be calculated.
So, everytime the window has been resized, the width has to be recalculated. I'm doing that with javascript:
function correctRatio(card, div){
width =$(div).width();
currentHeight = $(div).height();
wrongWidth = $(div).width();
newWidth = 9/14 * currentHeight;
if(wrongWidth+1 > newWidth){
newWidth = newWidth/(width/100);
}else{
newWidth = 100;
}
$(card).width(newWidth+"%");
console.log("Setted Width:" + newWidth);
}
The 9/14 resp. 14/9 is in my case the ratio 9:14
You should be able to have the card containers keep their aspect ratio using this trick.
Responsively change div size keeping aspect ratio
I'd like to have a simple html code that displays an image at 100% of the browser's resolution width, but have it not extend to greater than the image's original resolution width.
For instance, I have an image w/ resolution 800x600. I'd like the image to display with a width of 100% on a mobile web browser, but at a width of 800 on a computer's browser that has a resolution of greater than 800x600.
Is this possible?
Thanks!
You can do this with CSS very easily.
img {
width: 100%;
max-width: 800px;
}
With CSS you can achieve what you want:
img {
max-width: 100%;
}
#media (min-width: 800px) {
.img {
max-width: auto;
}
}
<img class='img' src='http://images5.fanpop.com/image/photos/25000000/Facing-the-wind-the-amazing-world-of-gumball-25060558-588-339.png' />
I'd recommend you this:
.img-responsive {
display: block;
max-width: 100%;
height: auto;
}
if you're using bootstrap you can just pass that class to the selector. i.e.
<img class="img-responsive>
wrap it into a div and add a max-width to 800px to that wrapper
Solution #1
If you're able to link images in your CSS, you're able to use the background-size:contain; property contain will resize the image smaller but not larger. It will not go above its native resolution.
CSS
div {
background-image:url("linkhere.com");
background-size:contain;
}
Solution #2
If you do not have the luxury of using CSS like this, then you could write some javascript:
Fist make sure your image is set to 100%
img {
width:100%;
}
then the script
var image = new Image();
image.src = $(this).attr("src");
image.onload = function() {
$(this).css({'max-width':this.width+'px');
};
Solution #3
If you know the dimensions of the image, you could set it as an in-line style - this may take some time if you have a lot of images
Fist make sure your image is set to 100%
img {
width:100%;
}
Then in the html, write something like this.
<img src="imagesource.com" style="max-width:800px"/>
I would write this in-line because you may have many images in which you'll have to catalog.