CSS background-size: cover + background-attachment: fixed clipping background images - css

I have a list of figures containing background images. Something like the following:
<ul>
<li>
<figure style="background-image: url(...);"></figure>
</li>
<li>
<figure style="background-image: url(...);"></figure>
</li>
<li>
<figure style="background-image: url(...);"></figure>
</li>
</ul>
Each of these images has their background-size set to cover and background-attachment set to fixed.
figure {
width: 100%;
height: 100%;
background-size: cover;
background-attachment: fixed;
}
When each of the figures takes up the entire viewport, this works fine, but if there is an offset of any kind the background-image gets clipped.
As far as I can tell this is by design (https://developer.mozilla.org/en-US/docs/Web/CSS/background-size#Values).
I would like the images to either clip vertically or horizontally but not both, and be centred by the size of the figure itself.
I know there are javascript solutions but is there a way to do this using CSS?
Here is a working example: http://codepen.io/Godwin/pen/KepiJ

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.

There's a jQuery fix for this: http://jsfiddle.net/QN9cH/1/
I know it's not optimal but at least it works :)
$(window).scroll(function() {
var scrolledY = $(window).scrollTop();
$('#container').css('background-position', 'left ' + ((scrolledY)) + 'px');
});

Nick Noordijk's answer put me on the right track, but I like to avoid scripts that perform a calculation every time the scroll event happens. Here's my version that only performs the calculation when page loads or screen size changes:
html:
<div class="fake-img"></div>
css:
.fake-img {
display: block;
height: 280px; /* set the height here */
width: 100%;
background-image: url('http://example.com/path/to/image.jpg');
background-repeat: no-repeat;
background-position: center 68px;
background-size: auto 50%; /* make a "best guess" here as a default */
background-attachment: fixed;
position: relative;
}
jQuery:
$(window).on('resize load orientationchange', function(){
responsive_calc();
});
var responsive_calc = function(){
// get the viewport height
var h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
// get the element height
var bannerHeight = $('.fake-img').height();
// get the integer percentage value difference between them
var bgHeightPercent = Math.ceil(bannerHeight/h*100);
// set background-size height to match the element instead of the viewport
$('.fake-img').css('background-size', 'auto ' + bgHeightPercent + '%');
}
Note that this really only works with landscape "banner" images - using background-size: auto nn% doesn't have the same advantage of background-size: cover in working no matter if your image has excess in either direction.

background: url(<image>) center top no-repeat fixed;
background-size: auto <width size in %>;
There is no real solution. However, you could make size height of the image auto instead of cover. And adjust the width size in % in your element until it bites the border.
You see if you resize your window, it won't be clipped. Instead, it will always keep the original image size format. With this above you basically 'zoom' it but doesn't 'cover' it up.

The background-size: cover; property is indeed clipping the image in order for it to fill the area and not have any empty space.
The background-size: contain; property is determining which dimension is larger and scales according to that. So if you have a 100px x 100px block and a background image of 200x150px, setting the background-size to contain will scale the image to 100x75px. In this scenario however, you will have empty space if the element's aspect ratio is different than the image's.
You can also manually control which proportion has priority, assuming you know the image's aspect ratio.
So if you know that your image is always 100x200px, this means that the width is always the small dimension and the height the large one.
Now setting the background-size: 100% auto; will ensure that you will not get empty space but you will end up with clipping. If you set it to background-size: auto 100%; it will ensure that no clipping takes place and the height will never have empty space ( but the width will).
If you do want clipping and just center the image, use background-position: 50%;.

Another very simple solution is to use of the vw and vh units (which, in case you didn't know, has totally passable browser support for most cases). For example, instead of doing background-size: cover, do background-size: auto 100vh.
If you're not familiar with vw and vh, they're viewport units, and they correspond to viewport width and viewport height. The values correspond to a percentage of the viewport height or width. For example, 50vw means 50% of the viewport width.
For our purposes, we can simply tell the background to be 100% of the viewport height.
Here's a fiddle.
If you need to accommodate for different aspect ratios you can take advantage of the aspect-ratio #media rules.

An example of parallax effect for separately arranged elements (not for fullscreen elements):
html:
<div style="background-image: url('/path/to/image.jpg')">Content</div>
css:
#element_to_scroll {
background-repeat: no-repeat;
background-size: cover;
background-position-x: center;
background-position-y: 0;
}
js:
$(window).scroll(function() {
var realImageWidth = 1280;
var realImageHeight = 1024;
var viewportBottom = $(window).scrollTop() + $(window).height();
$('#element_to_scroll').each(function(){
var scrollAmountPx = realImageHeight/(realImageWidth/$(this).outerWidth())-$(this).outerHeight();
var elementOffsetFromBottom = viewportBottom-$(this).offset().top;
var scrollAreaHeight = $(this).outerHeight() + $(window).height();
if(elementOffsetFromBottom>0 && elementOffsetFromBottom<scrollAreaHeight) {
var backgroundPositionOffset = Math.ceil(scrollAmountPx/scrollAreaHeight*elementOffsetFromBottom);
//$(this).css('background-position-y',"-"+backgroundPositionOffset+"px");
$(this).clearQueue().animate({'background-position-y':"-"+backgroundPositionOffset+"px"},50);
}
});
});

Update in July 2018: There is now a 1-line fix for this problem
I had this same problem until I read this article, which taught me that I could add this line to my CSS to make it work:
will-change: transform;
It worked!
Now my CSS looks like this:
.myClass{
position: relative;
background: hsla(300, 100%, 90%, 0.1);
overflow: hidden;
&::before {
background-image: url(/img/bg.jpg);
background-size: cover;
background-size: cover !important;
-webkit-background-size: cover !important;
background-repeat: repeat repeat !important;
background-attachment: scroll !important;//"fixed" is the desired effect, but mobile browsers find it too "expensive" and disabled it, so use "scroll"
background-position: 30% 50%;
#media(min-width: $screen-sm-min){
background-attachment: fixed !important;
background-position: 30% 20%;
will-change: transform;
}//768
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.1;
}
}
It's working for me on Windows Chrome, Edge, and Safari. But not Firefox.

I did a version with Responsive background image.
.flexslider .slides > li {
background-position: center center;
background-repeat: no-repeat;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
#slider,
.alink {
min-height: 300px
}
.alink {
display: block
}
http://jsfiddle.net/onigetoc/grpku1gk/

Related

Set background image in the center for all window size

according to the window size, the picture should both cover the window and even if the window height is greater than the height of the picture, let the picture be centered and fully covered.
But I don't want like this (Because the image is not centered, it just starts from the corner.):
background-size: center cover;
Your attempt looks like you try to do it with a OneLiner.
body {
background: url(https://via.placeholder.com/500/green) transparent no-repeat center center / cover;
height: 100vh;
}
<body>
<div>
hello World
</div>
</body>
background-size sets the size of background images for the element. The size of the image can be constrained, completely or partially in order to maintain its aspect ratio.
then remove the margin and padding from the element's parent
try to separate each term, like this
background-size: cover;
background-position: center;
try using margins
I have defined a css for you
.image{
width: 40%;
height: 40vh;
margin-top:30vh;
margin-left: 30%;
}
u can change the width and height of image but remember change margin top and margin left by half.
I used this for a div with an image inside of it. should work just fine. it will get smaller/larger depending on the window size and it will be in the exact center of the page.
background-image: url(path/to/image);
background-size: cover;
background-position: center center;

My background image is cut off at one side, how do I display the full image correctly? [duplicate]

I have a background image in the following div, but the image gets cut off:
<div style='text-align:center;background-image: url(/media/img_1_bg.jpg);background-repeat:no-repeat;width:450px;height:900px;' id="mainpage" align="center">
Is there a way to show the background image without cutting it off?
You can achieve this with the background-size property, which is now supported by most browsers.
To scale the background image to fit inside the div:
background-size: contain;
To scale the background image to cover the whole div:
background-size: cover;
JSFiddle example or runnable snippet:
#imagecontainer {
background: url("http://3.bp.blogspot.com/_EqZzf-l7OCg/TNmdtcyGBZI/AAAAAAAAAD8/KD5Y23c24go/s1600/homer-simpson-1280x1024.jpg") no-repeat;
width: 100px;
height: 200px;
border: 1px solid;
background-size: contain;
}
<div id="imagecontainer"></div>
There also exists a filter for IE 5.5+ support, as well as vendor prefixes for some older browsers.
If what you need is the image to have the same dimensions of the div, I think this is the most elegant solution:
background-size: 100% 100%;
If not, the answer by #grc is the most appropriated one.
Source:
http://www.w3schools.com/cssref/css3_pr_background-size.asp
You can use this attributes:
background-size: contain;
background-repeat: no-repeat;
and you code is then like this:
<div style="text-align:center;background-image: url(/media/img_1_bg.jpg); background-size: contain;
background-repeat: no-repeat;" id="mainpage">
background-position-x: center;
background-position-y: center;
you also use this:
background-size:contain;
height: 0;
width: 100%;
padding-top: 66,64%;
I don't know your div-values, but let's assume you've got those.
height: auto;
max-width: 600px;
Again, those are just random numbers.
It could quite hard to make the background-image (if you would want to) with a fixed width for the div, so better use max-width. And actually it isn't complicated to fill a div with an background-image, just make sure you style the parent element the right way, so the image has a place it can go into.
Chris
try any of the following,
background-size: contain;
background-size: cover;
background-size: 100%;
.container{
background-size: 100%;
}
The background-size property specifies the size of the background images.
There are different syntaxes you can use with this property: the keyword syntax ("auto", "cover" and "contain"), the one-value syntax (sets the width of the image (height becomes "auto"), the two-value syntax (first value: width of the image, second value: height).
percentage - Sets the width and height of the background image in percent of the parent element.
cover - Resize the background image to cover the entire container, even if it has to stretch the image or cut a little bit off one of the edges
contain - Resize the background image to make sure the image is fully visible
For more: https://www.w3schools.com/cssref/css3_pr_background-size.asp
Alternative:
background-size: auto 100%;
you can also try this, set background size as cover and to get it look nicer also set background position center like so :
background-size: cover;
background-position: center ;

Background with position fixed and size contain, relative to container

So I came across this today.
I have a section that is longer than the viewport, which has a background image with background-attachment: fixed;. This background is also using the background-size: cover; property. (needed for responsive purposes)
With the fixed position applied to the background, it crops off the image to fit it within the current viewport height and overflows the top of the tag.
Is there a way to make the image sit in the correct place (i.e. same position as if it wasn't fixed) and maintain the cover propery.
.hero {
background-image: url(http://lorempixel.com/output/food-q-c-1920-1920-1.jpg);
background-size: cover;
background-position: 50% 50%;
/* set the height of the hero. */
height: 125vh;
}
.fixed {
background-attachment: fixed;
}
<h4>With the fixed position</h4>
<section class="hero fixed"></section>
<h4>Without the fixed position</h4>
<section class="hero"></section>
I'm guessing as fixed elements are fixed to the viewport, the answer is no, but wasn't sure as it's a background image.
I wondered if perhaps anyone has found a workaround?
The Problem is, that the background area is fixed to 100% view port if you use fixed - You can enlarge the background area by adding background-size:
.hero {
background-image: url(http://lorempixel.com/output/food-q-c-1920-1920-1.jpg);
/*background-size: cover;*/
background-position: 50% 50%;
/* set the height of the hero. */
background-size: 125vh;
height: 125vh;
}

CSS Background fit every resolution

Ok, so I am a newbie. I want my background (which is a image), to fit every resolution of the Web Browser no matter the browser resolution. I found this trick:
html {
background: url(images/bg.jpg) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
BUT all it does is fits the background to the full size of the display, not the browser. So if the display is 1366x768 and the browser is maximized, then the background is properly showing as "full". However if I then adjust the browser , the background image is not showing correctly.
So what do I need to do, so the background image is adjusted with the browser? So if the browser is 1300x700, the background image is 1300x700 but if the browser is 900x600 then the backgroud image is 900x600. Again, Im a newbie so please provide some examples.
cover This keyword specifies that the background image should be scaled to be as small as possible while ensuring both its dimensions are greater than or equal to the corresponding dimensions of the background positioning area.
contain This keyword specifies that the background image should be scaled to be as large as possible while ensuring both its dimensions are less than or equal to the corresponding dimensions of the background positioning area. So try using contain instead of cover
100% This will scale 100% to both of height and width without any cropping.
html {
background: url(images/bg.jpg) no-repeat center center fixed;
-webkit-background-size: contain;
-moz-background-size: contain;
-o-background-size: contain;
background-size: contain;
}
This may help you: http://www.w3schools.com/cssref/playit.asp?filename=playcss_background-size&preval=contain
And this https://developer.mozilla.org/en-US/docs/Web/CSS/background-size
You can actually work around this by inserting the background image you want with height and width attributes on it and setting 100% width on it. Then you can place your content on top of that image.
<div class="container">
<img class="background-image" src="whatever.png" width="NATURAL WIDTH" height="NATURAL HEIGHT">
<div class="content">
This stuff will be on top of the image.
</div>
</div>
<style>
/* This element will == the height of the image */
.container {
position: relative;
}
/* This element is the background image */
.background-image {
width: 100%;
height: auto;
position: static;
}
/* This element contains the content which will be placed on top of the background image */
.content {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
}
</style>

Css first div page full height

How can I make the first page of a one page website full height with a background image like this website? http://avathemes.com/HTML5/De7igner/image.php
Why not use the vh unit?
The vw and vh units stand for the percentage of the width and height
of the actual viewport. They can take a value between 0 and 100
according to the following rules:
100vw = 100% of viewport width 1vw = 1% of viewport width
100vh = 100% of viewport height 1vh = 1% of viewport height
.class_name
{
height: 100vh;
}
Looking at the website in the link provided, they have only put the background image on only a specific part of the website (the countdown time). So if you want to follow them, you can put the required area in a wrapper div and then use the css3 background properties.
.wrapper {
width: 100%;
height: 100%;
background-image: url(bg.jpg);
background-repeat: no-repeat;
background-position: center center;
-webkit-background-size: cover;
background-size: cover;
background-attachment: fixed;
}
If you want the whole page to have a background, then you can just change the .wrapper selector to body.
I am using the background-size property as in covered in this article http://css-tricks.com/perfect-full-page-background-image/, check it out. Here is the js fiddle http://jsfiddle.net/Br4fZ/ for what you wanted.

Resources