I'm trying to use the padding bottom hack (illustrated below) to stop reflow upon image load for an Angular website. The problem is that I don't know the aspect ratio of the image, as it is user specified. Is it possible to stop image reflow when the dimensions of the image are unknown? I've found examples of getting the image dimensions using javascript, but that seems to happen after the page is already loaded. Can I get the height an width of the image in the component before load? I have access to the image source in the component.
index.html
----------
<div class="img-wrapper" style="padding-bottom: calc((400/600)*100%);">
<img src="example.jpg" />
</div>
styles.css
----------
.img-wrapper {
position: relative;
display: block;
height: 0;
overflow: hidden;
}
.img-wrapper img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
max-width: inherit;
}
You can create a Javascript Image object in code (memory) and read the aspect ratio that way.
let image = new Image();
let width: number;
let height: number;
image.onload = () => {
{ height, width } = image;
const ratio = width / height;
}
newImg.src = 'Your source here'; // this must be done AFTER setting onload and will load the image.
Remember, setting the src of the image will load it, which is asynchronous. onload is the callback for when the image is loaded.
You could also just load it into the page via an img tag, initially style it so it's invisible and won't mess with the page layout (position: absolute; opacity: 0 or something similar), then grab the element with the Renderer2 and read its offsetWidth and offsetHeight as it exists in the page, then alter styling accordingly and show the image.
EDIT: Here's my own stackblitz of the above done in an Angular-ly fashion. It transforms onload into an Observable, prefetches the image, does some calculations, and then uses the Renderer2 to append it to the DOM. I'm calculating how to preserve the aspect ratio if you want one dimension to be 200px maximum, but that's just an example.
I want to achieve the following:
Where there is a background image, and a text over it (text position is bootstrap offset-6 col-6)
And for it to be responsive.
The thing is, that unlike conventional background, I do care how the background image is truncated, I need the phone to be visible regardless of the width.
I tried:
background: url(background-photo.jpg) center center cover no-repeat fixed;
And the invisible img trick on How to get div height to auto-adjust to background size?
In all the cases the phone gets truncated
Assistance will be appreciated
Edit:
As requested - the original div structure is:
<div id="hungry">
<div class="col-xs-offset-6 col-xl-offset-6 col-xs-6 col-xl-6">
<p>Hungry doesn't always happen in the kitchen</p>
</div>
</div>
But I have no problem changing it to whatever works...
Solution with JavaScript
I know this is not a CSS-only solution a I use JavaScript, but it could help as a temporary solution while we look for a CSS thing.
The HTML would be the same as you posted:
<div id="hungry">
<div class="col-xs-offset-6 col-xl-offset-6 col-xs-6 col-xl-6">
<p>Hungry doesn't always happen in the kitchen</p>
</div>
</div>
The CSS for the div with id "hungry" would look like this:
#hungry {
background:url('http://i.stack.imgur.com/7xasp.jpg') no-repeat center center ;
background-size:cover;
width:100%;
}
And finally, with JavaScript (I used jQuery to make it easier), you resize the height of #hungry depending on the screen width:
// you know the size for your image
imageWidth = 1919;
imageHeight = 761;
imageProportion = imageHeight/imageWidth;
function resizeJumbo() {
$("#hungry").css({ height: $(window).width() * imageProportion });
}
$(window).on("resize", function() {
resizeJumbo();
});
$(document).ready(function() {
resizeJumbo();
});
You can see a demo working on this fiddle: http://jsfiddle.net/hyfz0Lga/.
Solution with CSS only
Just update the CSS for the hungry div a little:
#hungry {
background:url('http://i.stack.imgur.com/7xasp.jpg') no-repeat center center ;
background-size:cover;
width:100%;
padding-top:20%;
padding-bottom:20%;
}
You can see it working here: http://jsfiddle.net/hyfz0Lga/1/.
Why padding-top:20% and padding-bottom:20%?
Those values have to do with the size of the picture, and the proportion between them. In your case: width = 1919 and height = 761, so the proportion between width and height is (761 / 1919) * 100 = 39.65%. Just add half that value on top, and half that value at the bottom, then the text will remain always in the middle, and the picture will always be proportional.
I know it's a bit "hacky" and plays with knowing some data, but it seems to be working fairly well.
you could try tweaking the jumbotron class in Bootstrap 3 just like i did for my website.
.jumbotron {
background: url('background-photo.jpg') no-repeat center center;
}
you could change the dimension of the jumbotron depending on the dimensions you want.
<div row jumbotron>
<div class="col-md-6 col-md-offset-6">text</div>
</div>
How to re-scale image relative to its own size in HTML and CSS?
I want an image to be scale up to 170% of its own size, or scale it down to 50% of its own size rather than the size if it's parent element.
I've tried this:
<div><img src="0001.svg" height="50%"></div>
it re-scales relative to its parent element's height.
This works:
<script>
function Start() {
OPIC = document.getElementById('PIC')
var x=OPIC.width, y=x=OPIC.height, pct=.7 // = 70%
OPIC.height=pct*y; OPIC.width=pct*x;
}
</script>
<body onload="Start()">
<img id='PIC' src=...>
However with IE and Edge I seem to be losing the picture
Specify some width for parent div.Then give either width or height for the image to maintain aspect ratio of the image.
Here is the LINK
HTML:
<div class="image_resize">
<img src="http://www.sxc.hu/img/certified_images/crt_melaniemar.jpg" />
</div>
CSS:
.image_resize {
width:260px;
}
.image_resize img {
width:60%;
}
This code below works, but I would like it to maintain the absolute center of the image, not stretch it based on the top left corner. See images:
html
<div class="full-img-container">
<img src="/images/crowd.jpg" class="full-img">
</div>
css
.full-img-container {
max-height: 300px;
overflow: hidden;
}
.full-img {
width: 100%;
margin: 0 auto;
vertical-align:middle;
}
When the browser is small:
When the browser is stretched - it stays in 300px but isn't vertically centered (there should be more people in the image)
UPDATE
This is what I was trying to do: http://demo.solemone.de/overflow-image-with-vertical-centering-for-responsive-web-design/
UPDATE:
I think I know what you want now. Interesting problem. So vertical centering, with the possibility of cropping off even amounts of the top and bottom of the image due to the priority of keeping the center of the image in the center of your window.
I found an example that might help you at another website :
http://demo.solemone.de/overflow-image-with-vertical-centering-for-responsive-web-design/
Try his example and let me know if it works for you or at least gets you closer to your ideal solution! I will try to help further as needed after I hear back from you.
Set height: auto; to the <img> tag.
I think I misunderstood the question. The answer is: make the image block: display: block;.
You should try to set
background-size: contain;
You could use jQuery for this:
$(window).resize(function(){
var imgheight = $('.full-img').height();
var containerheight = $('full-img-container').height();
heightDifference = imgheight - containerheight;
if(heightDifference > 0)
{
$('.full-img').css('margin-top', '-' + heightDifference/2 + 'px')
}
});
I have a background image on the body of my web page. I have used background-size:cover so that the image stretches across the body whilst maintaining the aspect ratio of the image. I would like this to be the same for IE7 + IE8.
I have looked around and seen the following code:
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(
src='AutumnWinter_4.jpg',
sizingMethod='scale');
-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(
src='AutumnWinter_4.jpg',
sizingMethod='scale')";
But this doesn't preserve the aspect ratio, which is really bad for the website we are aiming at.
Is there any way to do this? Without hitting up jQuery?
What's the reason of not using jQuery? You could load it in conditional comments for IE<8 only, so that for every other modern browser jQuery is not loaded.
Also consider that IE7 has a very low market share (2,52%, April 2012) so it can be acceptable to load ~ 25kb extra for that specific browser if this feature is so important for your site/application.
So, I've found this plugin for jQuery: https://github.com/louisremi/jquery.backgroundSize.js
A jQuery cssHook adding support for "cover" and "contain" to IE6-7-8, in 1.5K
See Github project page for more info.
backgroundSize.js will not actually stretch the bg image in IE7, it seems to just center it at the original size. See their demo and click on 'Check what IE6-7-8 users would normally see.'
#danRhul
I have read that backstretch will work in IE7+
Good luck!
You could just fake a background image with an actual image. It's a bit more HTML editing and certainly not ideal, but since when has handling IE ever been ideal?
<body>
<img id="mainBG" src="mainBG.jpg" />
<div id="content">
[ ... ]
Then style it accordingly
body{
position:relative;
}
#mainBG{
width:100%
position:absolute;
top:0px;
left:0px;
}
Should be cross-browser if I'm not mistaken.
I've used the following (http://css-tricks.com/perfect-full-page-background-image/) and it works well in ie7.
HTML:
<body>
<img class="bg" src="filename">
</body>
CSS:
.bg {
/* Set rules to fill background */
min-height: 100%;
min-width: 1024px;
/* Set up proportionate scaling */
width: 100%;
height: auto;
/* Set up positioning */
position: fixed;
top: 0;
left: 0;
}
#media screen and (max-width: 1024px) { /* Specific to this particular image */
img.bg {
left: 50%;
margin-left: -512px; /* 50% */
}
}
I know this is now an old question, but I thought I'd share a solution I came up with for anyone else who finds this question on google, like I did.
I was trying to get an image to cover a site's background and came across this question, however none of the solutions worked for me. I came up with this instead:
HTML: move the background image to an <img />, make it the first thing in your <body>.
<html>
<body>
<img class="background" src="kitty.jpg" />
<div class="content">
...
CSS: make the background appear under the content, set it's min-width/height to 100%.
html {
height: 100%
}
body .background {
position: absolute;
z-index: -1;
min-height: 100%;
min-width: 100%;
}
It's the min-height and min-width here that does the magic. Do not give the image a width and height in the HTML or CSS, or the aspect ratio will change.
The above will work for IE7 and IE8. If you would like to support IE6, you could set a centered image fallback like this:
CSS: If IE6, don't display the image, use a background image instead.
body {
_background: url("kitty.jpg") 50% top no-repeat;
}
body .background {
_display: none;
}
(N.B. If you don't like the underscore hack to target IE6, you could use conditionals instead – that's what the HTML5 Boilerplate does.)
After much trial and error, the best solution was guessing it!
The following worked for me.
body {
background-size:100%;
}
You have two options to achieve this with just CSS:
Use Object-fit: cover. The only problem with this is that it will not work in all browsers
If you want cross browser support, you can follow primitive CSS approach:
Position the image inside the container with absolute and then place it right at the centre using the combination:
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
Note:
Since transform ONLY works from IE9, you can make use of filters. Here is an answer for this.
Once it is in the centre, you can do,
// For vertical blocks (i.e., where height is greater than width)
height: 100%;
width: auto;
// For Horizontal blocks (i.e., where width is greater than height)
height: auto;
width: 100%;
This makes the image get the effect of Object-fit:cover.
Here is a demonstration of the above logic.
https://jsfiddle.net/furqan_694/s3xLe1gp/
Unfortunately, most solutions to this kind of problem either depend on css3 or ignore the native functionality of "cover" that preserves the original aspect ratio of the image. https://github.com/louisremi/background-size-polyfill is supposed to preserve ratio, but I could never get it to work completely when stretching the browser in certain ways (operator error, I'm sure :-) ). To solve this problem, I wrote a jquery script that I've tested on safari, chrome, ff and ie8+. You'll notice that you will have to use an img positioned absolutely instead of css background-image. Just add the bgImg as an id in the tag in html.
CSS:
.container { height: auto; overflow:hidden; position:relative;}
.container #bgImg { position:absolute; z-index:-1;}
You're image selector will have to be positioned absolutely to get it to sit behind the content. That means that you're parent container has to have position: relative and then overflow: hidden so that whatever overflows from the image (since you're maintaining ratio, some pieces of it inevitable will) is hidden. Be aware also that certain display tags in the parent container will break the hiding of the overflow.
JQUERY:
$(window).load(function () {
// only do this once and pass as function parameters, because chrome
// and safari have trouble not only with document.ready but window.resize
var img = new Image();
img.src = $("#bgImg").attr('src');
var $width_orig = img.width;
var $height_orig = img.height;
resizeBGImage($width_orig, $height_orig);
$(window).resize(function () {
resizeBGImage($width_orig, $height_orig);
});
});
function resizeBGImage($width_img_orig, $height_img_orig) {
// get dimensions of container
var $width_container = $('.container').outerWidth();
var $height_container = $('.container').outerHeight();
// calculate original aspect ratio and ratio of the container
var $imageratio = $width_img_orig / $height_img_orig;
var $containerratio = $width_container / $height_container;
var $wdiff = $width_container - $width_img_orig;
var $hdiff = $height_container - $height_img_orig;
// original size, so just set to original
if (($wdiff == 0) && ($hdiff == 0)) {
$("#bgImg").css('width', $width_img_orig);
$("#bgImg").css('height', $height_img_orig);
}
// if container is smaller along both dimensions than the original image,
// set image to container size
else if (($wdiff < 0) && ($hdiff < 0)) {
$("#bgImg").css('width', $width_img_orig);
$("#bgImg").css('height', $height_img_orig+1); // adding one because chrome can't do math
}
// if container is wider than long relatiave to original image aspect ratio
// set width to container width and calculate height
else if ($containerratio > $imageratio) {
$("#bgImg").css('width', $width_container);
// calculate height using orig aspect ratio and assign to image height
$("#bgImg").css('height', (($width_container * $height_img_orig) / $width_img_orig) + 1); // adding one because chrome can't do math
}
// else container is taller than long relatiave to original image aspect ratio
// set height to container height and calculate width
else {
// set the image height to container height
$("#bgImg").css('height', $height_container + 1); // adding one because chrome can't do math
// calculate width using orig aspect ratio and assign to image width
$("#bgImg").css('width', (($height_container * $width_img_orig) / $height_img_orig));
}
$("#bgImg").css('left', (($width_container - $("#bgImg").width()) / 2).toString() + 'px');
};
Note the use of $(window).load() instead of $(document).ready(). Chrome and safari seem to have issues with the latter since in those browsers, the background image may not be fully loaded when the DOM is. Using $(window).load() ensures all window elements are in place before the script runs.
Sounds like you need a 'shim' or 'polyfill' like Modernizer:
http://modernizr.com/docs/#html5inie