CSS background fixed + cover stretches the picture (not covering properly) - css

I am using fixed background images in my ReactJS website. The image I am using in header area is getting weirdly stretched (zoomed-in, only a small part of picture is visible) even though the same CSS properties for different elements work well.
App.js
return (
<div id="main">
<div id="header">
...
</div>
...
<div id="bg-img1" className="background_image">
...
App.css
#header {
background-image: url("img/svatba.jpg");
background-position: center center;
background-size: cover;
background-attachment: fixed;
height: 300px;
background-repeat: no-repeat;
}
...
.background_image {
background-size: cover;
background-position: center;
text-align:center;
min-height: 326px;
background-repeat: no-repeat;
}
#bg-img1 {
background: url('img/svatba2.jpg');
background-attachment: fixed;
background-repeat: no-repeat;
}
...
Now the image in the "header" element shows up zoomed, not covering the viewport as it should. The image in the "bg-img1" element is displayed properly.
What am I missing?

When you set the background-size to "cover", you are telling it to take that image and resize it (or "zoom it in" as you're saying) so that it covers the entire section (here #header).
If your hope is to have a header 300px high that spans the whole width of the page without losing any portions of your image, You would need to serve an image that shares the same proportions as your header.
For example, if your header is 300 x 1000, you could load an image of the same dimensions or of 120 x 400, keeping an aspect ratio of 3:10.

background-attachment
The way that background-attachment: fixed is commonly used is as a way to prevent a background image from moving relative to the viewport whenever the document is scrolled.
Note: For the purposes of this explanation, the viewport can be thought of as being equivalent to the browser window, although this isn't strictly the case.
CSS does this by basically taking the element's background image and attaching it to the viewport instead of to the element itself.
Since the viewport doesn't change its position when the user scrolls, the image will be statically positioned relative to the window. So far, so good.
background-size
Where we get into trouble with attachment is when we try to combine it with background-size: cover (or contain). Because background-attachment has already sent the background image to the viewport, any background position changes made through the CSS become relative to the viewport.
This is normally fine, but it means that when you try to use either a percentage value or a predefined size operator like cover, the background will also be sized to the viewport.
While writing up this summary, I discovered that this behavior is mentioned in the MDN documentation. The only problem is that it's just two sentences jammed in the middle of the percentage paragraph in the Values section of the background-size page. Yikes.
Demo
I've created an interactive demo to show the results of this behavior. To view it, click here.
The demo will display four panels, each with a different combination of sizing and attachment. Move your mouse over each of these panels to see how the background image is positioned in the container, and what's been hidden.
Fun fact: I made over 300 revisions to this demo before I was comfortable calling it done :P
Conclusion
In one of your comments below, you said (emphasis mine):
Cover was the culprit - but I have a little idea why. All the images
are landscape. The elements have min-height. I expected that the cover
will fix the width to the viewport, and that contain would fix the
height to the element height. Instead I see the cover zooming absurdly
(not matching any of the dimensions) and contain matches the width
(which is what I wanted). But why?
CSS often subverts expectations, and this is no different. For the cases below, assume we're using background-repeat: no-repeat.
cover scales the background image so it fits the element's largest dimension exactly and overflows the smaller one. This will generally cause it to be much larger than the element, showing only a portion of the image.
contain sizes the background image so it fits the element's smallest dimension and leaves blank space on either side of the image in the larger dimension.
But when you use background-attachment: fixed...
When you use cover, what you're actually seeing is the image being scaled to match the height of the viewport, since the height is smaller. With a landscape image, the height of the image will be scaled to the height of the viewport, which is why it appears so large.
When you use contain, the image is scaled to match the width of the viewport. If your element takes up the full width of the viewport, this will cover the element, cutting off the image's height, if necessary.
If you want to size the image using element-relative cover or contain, your two options, essentially, are to remove background-attachment: fixed, or to resize the source image so that your background-size declaration isn't necessary. Unfortunately, no CSS solution currently exists to enable attachment and keyword-based sizing at the same time.

Related

Images inside absolute positioned elements

I stumbled across a solution to a problem I was having with a website layout but wasn't sure if it was standard CSS practice or not. I've tested it on multiple platforms and browsers and it seems to be widely supported.
You can see what I'm talking about on this page.
The website linked to isn't my website but uses the same theme. I'm unable to post a link to my website as I'm working on it in a local environment.
The featured images are inside an element with position: absolute and the images themselves are set to width: 100% and object-fit: cover, and are unpositioned (i.e., static positioning).
The problem was I'm using product images and the object-fit: cover style setting was causing the images to get cut off.
The solution was to simply change the object-fit: cover setting to object-fit: contain which I understand is the default setting. This also centered the image even though the width of the images is less than the containing element.
It is happening because, when you use background-size: cover; it expands the image to cover the width of the div or element. In your case, image is being positioned center center that is why you have some top and bottom portion not visible. The only way I see to make this work is to increase the size of the element respectively with image or else resize the image to fit to the div.
If you want to check how it works. you can do this.
inspect element
change background-size: cover to contain
add css property height: 962px;
However, it is not a good idea.
I would suggest the keep it the way you have it now and adjust the background-position: if you want particular area of the image to be covered. or use the image that fit that div.
Also, the height of the div is being controlled with the content inside so make sure you have control on those content too. Easy way is to set min-height for the parent div with background image.
Let me know if this was helpful.

Banner and heading

I just want to create image with title and button on top.
Text and button should be in container with set width. I just want to know what is the best way to do that.
There are lots of way that makes you confuse on internet and I don't know which one is best!
If your background image has always the same aspect ratio, you can make the height of the container proportional to the width of the background image.
Let's say your background image is 2000 x 1000 px. And let's say the screen is currently 800px wide. Then you want the container with the background image to be 400px high. To achieve this without setting hard coded breakpoints, you can use the "padding trick". If you set the padding (top or bottom) of a child element in percent, it calculates the height as a percentage of the parent element's width. So if you set the the container's padding-top to 50%, it will be half as high as the the parent element is wide. So in the case of 2000 x 1000 px: 1000 / 2000 * 100 = 50%.
.parent_w_bg {
background-image: url(...);
width: 100%;
}
.container {
width: 500px;
margin: 0 auto;
padding-top: 50%; // Assuming the background image's aspect ratio is 1:2
}
<div class="parent_w_bg">
<div class="container">
Header and button etc.
</div>
</div>
In such a scenario you should position the container relatively and it's children absolute, for example the header with a top value and the button with a bottom value.
Here a simple fiddle: https://jsfiddle.net/mmcc5rnk/
Using multiple image sizes for different breakpoints can be useful, but also problematic. Depends on your specific case, the size of your image(s) and the amount of breakpoints you want to use (and the differences). Using different images according to some specified breakpoints is fine and can be used regardless of the implementation.
Setting a height for an entire section is never a good idea, unless specified in the project requirements. Always depend on the inner content to stretch your section vertically.
About the background - if you are using multiple images, you can apply different sizes and positions for them in one common background setting so that they can scale an re-arrange when the viewport resizes, or if you have one big image, you can simply set the image background size to cover like so:
background: url('images/image.jpg') no-repeat center center/cover;
There are many ways to achieve your goal, but the most up to date way of doing things is using the Flexbox model.
All flexbox properties must be prefixed, so they can work across all browsers.
Explaining how Flex works is too broad for an answer, so you will have to learn it from the ground up.
Here is a Fiddle that represents your aim.
No need to add different images for each breakpoint,
image will resize automatically, you can add dynamic height by using jQuery
Demo here

How to make a responsive "self cropping" background image?

I'm developing a wordpress theme and I'm having a bit of a problem.
In my homepage I want a wide background image with some text centered on it. So far pretty standard.
The thing is, I want the height to stay the same and as the browser gets smaller, the image should crop from both sides accordingly so the image stay centered.
Here is a great example I found, try resizing it and look at the big image at the top:
http://www.shopstyle.com/
How can I get this effect?
Thanks in advance! :)
You can use property background-size with value cover, which was made for that purpose
cover
A keyword that is the inverse of contain. Scales the image as large as possible and maintains image aspect ratio (image doesn't get squished). The image "covers" the entire width or height of the container. When the image and container have different dimensions, the image is clipped either left/right or top/bottom.
set the height you need (you can set different height for FHD, HD, Tablet, Mobile with media queries) and the image will be cropped from sides and zoomed if needed (if it's shorter than height you set)
Additionally to using background-size: cover;
You should use view port height to control the height of the image. This way it will always be a certain percentage of the view port height, no matter if it's a desktop, laptop, phone, etc. It's the more fluid way to display a height.
Example (covers the whole screen):
.yourelement {
height: 100vh;
}
Example (covers half the screen):
.yourelement {
height: 50vh;
}
Adjust accordingly.

Adjust image to div and centering it

well, I have a div holder with dimensions width:200px and height:110px.
When i load an image, normally it exceeds such dimensions, so i need to adjust the image to such content by width or height depending of the dimensions of the image. So, if its adjusted by with, three situations may occur:
1.- height is higher than 110px, so as the div overflow is set to hidden, it will need to center it vertically.
2.- height is equal than 110px, no problem.
3.- (The issue) height is less than 110px. What's suponed i should do in this situation? because I want to cover all the div content.
Thanks.
If you load the image as a background for the container, you can mess around with background-size: cover or background-size: contain and use background-position: center center to keep it in the middle regardless of size.
Alternatively, you might want to use a table cell, as these allow contents to be vertically aligned inside (either use a table with one cell, or display: table-cell on the container).

Footer Background Image - Entire Page Width?

I have an image that I want to use as a background-image for my footer. Its sort of a gradient image, so the will be white, and the image will fade from its color, to white. It's not really a repeatable image though.
If I want it to always span the entire width of the page, is this possible without a background-repeat? Or, because of different monitor sizes, will this be impossible?
The background image I want should only be in the footer of the page. Like a sticky-footer, it should always stick to the bottom and the content will push it down as needed. It's about 400px in height.
It could still be a background (positioned bottom-center) but it can;t take up the whole height, just the width. And it need to be able to be pushed down (not fixed)
If you're comfortable using CSS3 you can use
background: #fff url(image.jpg) center center fixed no-repeat;
background-size:cover;
to have the image cover the screen. You'll want to be careful that it is at least a decent resolution though.

Resources