CSS3 background-size - can I guarantee coverage?
I haven't implemented a css-only way to do this, but I did use the backstretch jQuery plugin once, and it worked across the board. http://srobbin.com/blog/easy-full-screen-background-images-with-jquery/
CSS3 background-size: cover doesn't make image cover vertically
Are you interested in only using a CSS background image? This can be done by loading an image and constraining it with the CSS.
Would either of these examples work?
HTML
<body id="page-body">
<img class="bg" src="images/bodyBackground1.jpg">
<div class="wrapper">
</div>
</body>
CSS
html {
background: url(images/bodyBackground1.jpg) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
body {
background:#fff;
margin: 0;
padding: 0;
overflow:hidden;
}
html, body {
height: 100%;
}
img.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% */
}
}
Or this one? This one loads images from a database into an array and loads them at random, but you might be able to glean some info from this:
PHP load function
<?php
$bg_images = array(
0 => 'comp1.png',
1 => 'comp2.png',
2 => 'comp3.png',
....
);
$image = $bg_images[ rand(0,(count($bg_images)-1)) ];
$showBG = "<img class=\"source-image\" src=\"images/bg/" . $image . "\"/>";
?>
HTML
...
<body>
<?php echo $showBG; ?>
<div id="wrapper">
...
CSS
html, body {
margin:0;
height:100%;
}
img.source-image {
width:100%;
position:absolute;
top:0;
left:0;
z-index:0;
min-width:1024px;
}
These options should fill up the browser window according to the height and width.
What's the math behind CSS's background-size:cover
Here's a logic behind cover calculations.
You have four base values :
imgWidth // your original img width
imgHeight
containerWidth // your container width (here 698px)
containerHeight
Two ratios derived from these values :
imgRatio = (imgHeight / imgWidth) // original img ratio
containerRatio = (containerHeight / containerWidth) // container ratio
You want to find two new values :
finalWidth // the scaled img width
finalHeight
So :
if (containerRatio > imgRatio)
{
finalHeight = containerHeight
finalWidth = (containerHeight / imgRatio)
}
else
{
finalWidth = containerWidth
finalHeight = (containerWidth / imgRatio)
}
... and you have the equivalent of a background-size : cover.
CSS3 background-size: contain;
On block elements (like div
), height does not work the same way as width. If you don't specify a height, the element will be as high as its content. That's one thing.
height: 100%
would be the way to go if you want your div to be as big as body
is, but the trick is that a percentaged height always comes from the parent's height. So you have to set height: 100%
on all the parents (including html
) for crosss-browser results.
html,body,#please_expand { height: 100%; }
jsFiddle Demo
CSS background-size: cover + background-attachment: fixed clipping background images
Unfortunately this is simply an artifact of how fixed positioning works in CSS and there is no way around it in pure CSS - you have to use Javascript.
The reason this happens is due to the combination of background-attachment: fixed
and background-size: cover
. When you specify background-attachment: fixed
it essentially causes the background-image
to behave as if it were a position: fixed
image, meaning that it's taken out of the page flow and positioning context and becomes relative to the viewport rather than the element it's the background image of.
So whenever you use these properties together, the cover
value is being calculated relative to the size of the viewport irrespective of the size of the element itself, which is why it works as expected when the element is the same size as the viewport but is cropped in unexpected ways when the element is smaller than the viewport.
To get around this you basically need to use background-attachment: scroll
and bind an event listener to the scroll
event in JS that manually updates the background-position
relative to how far the window has been scrolled in order to simulate fixed positioning but still calculate background-size: cover
relative to the container element rather than the viewport.
Is there an equivalent to background-size: cover and contain for image elements?
Solution #1 - The object-fit property (Lacks IE support)
Just set object-fit: cover;
on the img .
body {
margin: 0;
}
img {
display: block;
width: 100vw;
height: 100vh;
object-fit: cover; /* or object-fit: contain; */
}
<img src="https://loremflickr.com/1500/1000" alt="A random image from Flickr" />
Does background-size: cover stretch a background image?
It can stretch or constriction depending on image & background size.
It will crops the extra portion which does not matched to div size.
Suppose you have a div with 400*250
, and the background image is 400*350
. If you use background-size: cover
, then to cover all background it need to crop 100px height extra.
or, if you use 200*150 background image, then to cover all the
background it is needed to extend the image minimum 400*300
(200:150=2:1.5, multiply by 2 will 400*300, mind that if height
increases, width also will be increased proportionally)if we make the image 200*150 to 333.33*250, width will be not covered. (though
height is ok)if background image size u used is 800*500 or 200*125 or same proportion to it, no portion of image will be cut down, will see
whole imageFor, 8000*500 size image, it will compressed to cover 400*250 sized background, no portion will cut down but image will be compressed to fit.
Finally, background-size cover property will large or compress the image until all background will be covered, it don't care how waste the image will be.
CSS: Full Size background image
Your screen is obviously a different shape to your image. This is not uncommon, and you should always cater to this case even if your screen is the same shape (aspect ratio), because other people's screens will not always be. To deal with this, you have only one of three options:
- You can choose to completely cover the screen with your image, but not distort the image. In this case, you will need to cope with the fact that edges of your image will be cut off. For this case, use:
background-size: cover
- You can choose to make sure the entire image is visible, and not distorted. In this case, you'll need to cop with the fact that some of the background will not be covered by your image. The best way to deal with this is to give the page a solid background, and design your image to fade into the solid (although this is not always possible). For this case, use:
background-size: contain
- You can choose to cover the entire screen with your background, and distort it to fit. For this case, use:
background-size: 100% 100%
Difference between background-size:cover and background-size:contain
You can consider looking at the pseudocodes that govern the output. The values allotted to the image's size depend directly on the aspect ratios of container wrt aspect ratio of the background image.
Note: Aspect ratio = width / height
Contain
if (aspect ratio of container > aspect ratio of image)
image-height = container-height
image-width = aspect-ratio-preserved width
else
image-width = container width
image-height = aspect-ratio-preserved height
Cover
if (aspect ratio of container > aspect ratio of image)
image-width = container width
image-height = aspect-ratio-preserved height
else
image-height = container height
image-width = aspect-ratio-preserved width
You see the relation? In both cover
and contain
, aspect ratio is preserved. But the if - else conditions reverse in both the cases.
This is what makes cover
to cover full page, without any white portion visible. When aspect ratio of container is greater, scaling image so that its width becomes equal to container width. Now, height will be greater, as aspect ratio is smaller. Thus it covers the whole page without any white portion.
Q. Can they be replaced by percentages?
No, not simply by percentages. You'll need conditioning.
Q. In which situations should I prefer one over the other?
When you are creating a website, you wouldn't want any white portion in the fixed background. So use cover
.
contain
on the other can be used when you are using a repeating background (e.g. when you have a pattern image with very high aspect ratio wrt veiwport/container you can use contain
and set background-repeat
to repeat-y
). But a more appropriate use for contain
would be for a fixed height/width element.
Related Topics
How to Make Entire Div Change Color on Hover Using CSS
Vertical Align Inside CSS Grid
Vscode - Change Highlight Color of Current File
Rem Font Size Not Adjusting Below Arbitrary Threshold
Absolutely Positioned Flexbox Doesn't Expand to Fit Contents
Wget Downloads CSS @Import, But Ignores Files Referenced Within Them
What Is The Use of @Namespace in CSS
Sass Importing Without Compiling
Ie7 and "Inherit": Ignoring Entire Rule
How to Resolve The CSS Warnings for Browser Specific Selectors in Bootstrap 3
CSS Color Rendering Different in Safari
Using CSS Clip with Percentage
Setting The Scrollbar Color in Safari for Lion (Os X 10.7)
CSS - Floating Two Elements Side by Side