This question already has answers here:
CSS: center and scale up or down image while preserving aspect ratio
(4 answers)
Closed 7 years ago.
I am building a responsive website. On the homepage I have a number of articles whose thumbnails should be displayed at 230px * 115px at full size desktop output. The article publishers will be uploading images of all sizes with no particular set aspect ratio.
I currently just have code to resize an image based on it's parent container. the width will be 100% of it's parent container and the height is automatic and will vary depending on which aspect ratio of the original image.
.img {
width:100%;
height:auto!important;
}
Is not really cutting the mustard.
My research suggest using a background img with background-size:cover. Is this a good way to go is it possible to center the cover horzontally and vertically? And work responsively?
Abit more direction would be great there are alot of articles our there but I can't find the exact answer to my needs.
update: #LGSon That's Great thankyou. It's the best solution I have tried so far.... I like the way the image is controlled within the div. Perfect. I guess the difference is now how to control the aspect ratio of the div. if i set the width to 50% the height it still fixed.
Your <img> rule is good, but you have to pack each <img> into another container that gets a percentage-based width and height: auto;
You can do this:
CSS
div {
display: block;
overflow: hidden;
}
.img {
width: 200%;
height: auto!important;
margin: -50%;
}
HTML
<div>
<img class="img" src="http://a5.mzstatic.com/us/r30/Purple5/v4/5a/2e/e9/5a2ee9b3-8f0e-4f8b-4043-dd3e3ea29766/icon128-2x.png">
</div>
DEMO HERE
You should set the image rule to, along with your other rules.
.img {
width:100%;
max-width:100%;
}
Will you know the dimensions of the image or are they unexpected?
The rule above is meant if you control the image and its accordance to your ratio in the design.
height is auto by default and adding !important to it does not make much of a difference.
Using a background image is a neat feature but cover will not do the job as expected. It covers the container with the images stretches or shrunk as needed to fill it entirely. Background images are also not recommended for performs reasons as they are loaded regardless of being displayed on the page or not as part of the css file, unless you load CSS files on demand with that request which is not necessary.
Hoep this helps, I will be glad to clarify.
I also disagree with the comment made about setting the parent container's height to auto as it does nothing. This is the default behaviour...
Related
I have an img element that looks like:
<img src="header-900x600.jpg" class="header-image" alt="" width="900" height="600" style="background-color: rgb(4, 96, 247);">
With the css:
.header-image {
display: block;
max-width: 100%;
max-height: 400px;
width: auto;
height: auto;
}
Now this is meant to force the image to resize to be max-height: 400px, or max-width: 100% whilst keeping its aspect ratio. Although when loading the image collapses into:
And after the image loaded, it pushes the text down:
I thought that since the image has the width and height inline, the browser would know it's aspect ratio already, and the image wouldn't be jumping around? Is there something I am missing?
All I want is the image element, before the image source has loaded, to be in the same aspect ratio as the image will be. Making the layout not jump around!
All major browsers are now capable of doing exactly this in their current versions.
When you specify width and height attributes in HTML on the img tag and in CSS you set a width (percentage or fixed, also max-width is valid) and height to auto (or vice versa) the browser calculates the correct size and aspect ratio out of it, until the image is loaded. When the image is loaded, it uses the dimensions of the loaded image, so these should not differ from the attributes you set, otherwise you will get a layout shift again.
Note, however, that an invalid image or an image that cannot be loaded might be treated differently than a not yet loaded image. It is not guaranteed that width and height attributes of the img are considered. (This is especially important if you want to test the behavior, you cannot simply remove the value of the src attribute, this won't get you the same result as a not yet loaded image.)
Also note that there are still issues with responsive images (picture element and srcset attribute of img element) as described in the follwing link.
A great article with more detailed info and browser support can be found here: https://www.smashingmagazine.com/2020/03/setting-height-width-images-important-again/
Note: Simply providing width and height to your images can result in a way better result in the new Lighthouse CLS (Cumulative Layout Shift) measurement, see https://web.dev/cls/
The browser doesn't know anything about the image until it is loaded. You can't set parameters of an element that doesn't exist. Instead, simply add the image into a container with full width, like so:
<div class="container">
<img src="header-900x600.jpg" class="header-image">
</div>
.container {
display: block;
width: 100%;
}
.header-image {
display: block;
max-width: 100%;
max-height: 400px;
}
Also what Tarik says in his answer is correct, if you are declaring auto height and width then max-height and max-width are doing nothing.
You set the width and height to auto. This means that the size will be set to the currently loaded image rather than anything to do with the max-height or max-width.
Note that this is probably a duplicate of CSS: Keep Aspect Ratio of an Element for Given Height
To be clear, when you set width and height to auto, you are overriding the other settings that you set and telling the browser to detect the size of the image. While the image is downloading, it cannot, so it behaves as you describe.
You could programmatically use javascript to set these properties after you detect that the image is done loading.
I want a background image to appear at the top part and fully cover the width of a page. As you can see, the image is quite wide and short - https://i.imgur.com/aJb6eBr.jpg. This should be the header image of a page, with the contents of the page appearing below it.
If the browser's width is bigger than the image's original width, the image's width and height should be enlarged proportionally (together with its container - thus pushing downwards the page's contents that appear under the image).
If the browser's width is smaller than the image's original width, the image should retain its original size without shrinking, and be cropped from both sides until a 15% crop is reached from each side (You can see that the image has quite wide green areas on both sides which are safe for cropping).
The tricky part is that once 15% of the crop has been reached from each side, I want the image to start shrinking proportionally to the browser's width, thus the middle 70% of the image will always be seen, and the image will never be cropped more than 15% from each side.
The height of the image (and it's container) should rescale automatically in proportion with the image's width. If the image's height (together with its container) shrinks to be smaller than it's original size, the page's contents are pushed up so the distance between the page's contents and the image is always kept the same.
I'm looking for a clean solution (preferably with CSS only) similar to this:
https://demodern.de/projekte/mediengruppe-rtl
Any ideas guys?
In terms of using CSS it is pretty simple to make everything work as you need. In order to do this you might use the image as it is via and the same image on a parent element's background. But you will have to adjust your CSS to work with this image ONLY. In case if you will try to use another image - you will have to adjust paddings or mediaqueries. Solution that works a kind of ONE time for a specific image, but still, it doesn't use JS at all, which is great. And regarding referencing the image twice - it is not a problem for a browser. It will make only one http request for a single unique media asset so no performance problems from this perspective.
Here is a way how you might do what you want:
.wrapper {
background: url(/images/_m1NuVvd.jpeg) 50% 50% no-repeat;
background-size: cover;
overflow: hidden;
position: relative;
padding-top: 38%;
}
.wrapper img {
transform: translateX(-50%);
left: 50%;
position: relative;
min-width: 100%;
display:none;
}
#media screen and (min-width: 1338px) {
.wrapper {
padding-top: 0;
}
.wrapper img {
display: inline-block;
vertical-align: top;
}
}
<div class="wrapper">
<img src="/images/_m1NuVvd.jpeg" />
</div>
Make sure to use a proper path to your image instead of /images/_m1NuVvd.jpeg.
BTW, in future it will be better to probide links to the images in a way, so those might be reused in jsfiddle. Dropbox doesn't allow to use the image via that link.
Best wishes
OK here's a challenging one! I really want to see if this can be accomplished with CSS only if possible.
I have a unique layout that requires images to be sized and positioned based on their parent container. If the image exceeds it's parent in height or width I need it to reduce size to fit. At the moment I'm using max-width and max-height together and it's working fine. The image resizes to fit and of course keeps it's aspect ratio.
Now here's the tricky part. I need to add a special shadow to this image that cannot be accomplished with CSS box shadows. The shadow uses PNG image. The shadow needs to be sized and positioned in relation to the image - meaning it falls at the bottom of the image and it equals the width of the image.
Normally I would achieve the shadow with ::after and size and position it relative to it's parent element, which works perfectly Except it's parent is the image and images do not allow ::before or ::after.
So as far as I can tell, the only way to achieve this is to wrap the image in another container so I can use that container as the parent elements and positioning reference for the shadow layer. But I cannot find a way to make that container div behave in the same way as the image in terms of the max-width and max-height sizing while still maintaining it's aspect ratio.
The best methods for maintaining aspect ratios use padding top, which works brilliantly when the width is the only important factor. But the padding-top technique doesn't allow for the container to have a max-height.
So I'm looking for a CSS technique that will allow a block element to maintain its aspect ratio, and have max-width and max-height at the same time. Similar to how an image would behave in this situation.
I've scoured the internets for a solution and haven't seen anyone describe this exact situation. Would be extremely grateful to anyone who can assist.
Added 1 Sept 2017:
I should mention that it's more than just the shadow I need to position relative to the image. There are some other elements as well that need to be positioned in this way, and those other elements are not simple background images. So while Lightbender's solution is great for the shadow, it doesn't solve the bigger issue at hand. I need a container around the image that I can use as reference to position other child elements.
While before and after won't work (easily) but you can still use padding and a background image and it will work exactly the way your current setup works.
img.fancyshadow {
height: auto;
width: auto;
max-width: 100%;
max-height: 100%;
padding: 0 10px 10px 0; /* adjust as needed */
background: url('path/to/your/shadow');
box-sizing: border-box;
}
I don't have a Mac handy, so I've only tested this in Firefox, Chrome, and IE, can anyone confirm Safari as well?
So I would like to see a simple example of what you are attempting as a starting point but you mentioned that the images need to be sized/positioned based upon the size of their container.
Here is an starting example of something like that. Not sure if it can be modified to suit your issue. Let me know and I can tweak.
When needing to have responsive images, I never use IMG tags. Setting the background image in CSS provides much more control on responsive sites/apps.
Documentation on background-size:
cover Scale the background image to be as large as possible so that the background area is completely covered by the background image. Some parts of the background image may not be in view within the background positioning area
contain Scale the image to the largest size such that both its width
and its height can fit inside the content area
$(function() {
$('.banner').resizable();
});
.banner {
background-image: url('https://s-media-cache-ak0.pinimg.com/originals/15/ae/a6/15aea601612443d5bddd0df945af6ffd.jpg');
background-size: cover;
background-position: center;
height: 175px;
width: 100%;
}
p {
color: #666;
}
.ui-resizable-se {
box-shadow: -1px -3px 10px 3px white;
}
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
<h1>Resize the image using the black triangle at bottom right of image</h1>
<p>Note how the image fills the container and the position is always centered (you can control where the position is, doesn't have to be in the center)</p>
<div class="banner">
</div>
It is often said that it's best to specify image sizes in img's HTML attributes, width and height. That way the browser can reserve the space for images that haven't initially been loaded yet, so that once they do load, they don't change the page layout by making the content below them jump as they appear. (I'm sorry to say I don't know what this technique is named so I don't really know how to search for this question specifically, thus this question)
What I'm wondering is how this is solved in responsive layouts? I know on a big desktop browser my news articles' images may be 400x300 px, for example, but I can't put that into my document, as:
<img src="/thumbs/article_image_400_300.jpg" width="400" height="300"/>
Because on a smaller browser I would also like my images to be smaller. But I would still like to keep this behaviour of reserving space, if possible.
Can this be done?
Put the height and width attributes into your HTML, showing the actual size of the image file you are using.
Then add this to your CSS to allow images to scale responsively while maintaining their aspect ratio:
img {
max-width: 100%;
height: auto;
width: auto;
}
Now set your desired image width for each breakpoint in your media queries, as a percentage of the width of the parent element.
For example:
img.medium {
width: 60%;
}
img.small {
width: 30%;
}
The widths set in your CSS will override those set in the HTML.
Currently working on a landing screen where users choose a colour theme on the site. There are two coloured sides that 'grow' on hover giving the effect of colouring the website seen on a mockup infront. (Check out the Codepen below to get what i mean, it's kinda hard to explain fully)
Demo: http://codepen.io/BAWKdesign/pen/PPvRjz/
To 'color' the mockup two images are used placed over one other.
It needs to be responsive so I've given the back image width: 100%; height: auto; which is also used to dictate the size of the parent div.
The top image is set to width: auto; height: 100%; as using width 100% causes the image to stretch and not clip.
The problem is, the overlaid image appears larger in size as you can see in the link below giving a cut up image effect. Perhaps there are differences in how the size is calculated when you swap 100% and Auto around?
Hopefully this is just me having a brain fart and I've made a rookie mistake somewhere!
Images are by default inline elements meaning they naturally have some spacing around them. You are setting your other images to position: absolute which causes them to display similar to a block element - ie. no default spacing.
Simple solution is to add display: block to your image element:
.img {
display: block;
}
Updated CodePen