How to center one image over another - css

I have 2 images - one is the main image and the other is like a picture frame that I'd like to position over the top of the main image.
The picture frame image is a png with a transparent center so the main image shows through.
The dimensions of the images are important - the inner main image has to be smaller than the frame so it is only visible through the center:
main.jpg = 367 x 550
frame.png = 405 x 597
I thought I had it with the following code...
<div style="background-image:url('/main.jpg') no-repeat scroll center center transparent;">
<img style="width:100%; max-width:100%;" src="/frame.png">
</div>
...which works great until you see the screen on a mobile phone; the frame.png stretches because I've given the width as 100% but the background main.jpg doesn't stretch along with it.
I need the design to be fluid, so I need the images to stretch.
Is there a way to make sure the background stretches the same as the main image?
I've tried all kinds of different methods to get this working, absolutely positioning the frame in a div floating over the main image, etc but I couldn't get the main image to appear centered horizontally and vertically when I did that.
Is there any way to achieve what I want without resorting to javascript?
The reason I'm using 2 images by the way is because of file size. I need the main image to be jpg so I can keep it small, but I also need the transparency on the frame so that has to be png :(

I usually use this:
HTML:
<div id="frame">
<img id="myImg" src="main.jpg">
</div>
CSS:
#frame {
position: relative;
width: 597px;
height: 405px;
background-image: url(frame.png);
background-position: center;
background-size: cover; }
#myImg {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: block;
margin: auto; }
This works for all images and other elements with fixed dimensions, or a set max-width and max-height.
I hope this works for you :)

I've created a fiddle for you.
http://jsfiddle.net/avrahamcool/4VQzP/
in my fiddle, the frame is just a black background, and the img is just a red background. as you can see, no need for transparent frame (because the img is above it)
instead of centering the frame above the img, I'm centering the img above the frame.
(if I understood correctly, this also serves your purpose)
HTML:
<div id="Frame">
<span class="Centerer"></span><img src="http://i.imgur.com/CbcmRLC.jpg"/>
</div>
CSS:
#Frame
{
width: 405px;
height: 597px;
background: url('http://i.imgur.com/uRvKrNR.jpg') no-repeat;
text-align: center;
}
.Centerer
{
display: inline-block;
height: 100%;
vertical-align: middle;
}
#Frame > img
{
vertical-align: middle;
}

I generally use another image absolute positioned as background. like:
<div>
<img class="background-img" width="100%" height="100%" style="position:absolute; top:0; left:0">
<img class="second-img" width="100%" height="100%" />
<!-- Then do the positioning with classes -->
</div>
Give it a shot, hope it works as you want

If you set the image as absolute; it is going to lift out of it's container.
Floating may do the same.
What about z-index:1; and x-index:2; with margin:auto; ?

Related

Centering a div on a VERY SIMPLE PAGE

Yes. This has been asked a billion times. But nobody has given an answer that works for me.
It's so stupid. I have a SPLASH PAGE.. which has almost NO code on it. All it has is some js and a series of photos that fade in, one by one.
No matter what i do, it aligns top left of the screen. Here's the code.
<div style="height:100%; width=100%; margin: 0px auto;" id="these">
<img src="photos/splash/Y.png" height="250px" style="padding: 20px;">
<img src="photos/splash/I.png" height="250px" style="padding: 20px;">
<img src="photos/splash/K.png" height="250px" style="padding: 20px;">
<img src="photos/splash/M.png" height="250px" style="padding: 20px;">
<img src="photos/splash/U.png" height="250px" style="padding: 20px;">
<img src="photos/splash/N.png" height="250px" style="padding: 20px;">
</div>
I want it to align in the very center of any screen, regardless of resolution. ID="these" is related to the javascript that displays them and not to any css-level styles or positioning.
Ridiculously simple right?? Yeah. It's always showing up on the top left.
I don't feel it's necessary to post the js (also it's breaking my post) but if you want it, ask. It works fine. I'm a backend coder who HATES (as in detests) HTML/CSS. So you'll have to really walk me through it and not just make vague suggestions.
I even tried a table! With a valign center. That centered it but each image showed up in the center and then was pushed left as the next image faded in. Obviously not what i want.
What i want is for each image to show up, one after the other, in it's own position. But will work for any screen resolution.
I'm losing my mind.
Thanks.
Your example shows you centering inline elements within a block level element. So all you need to do is this:
these { text-align:center; }
Ex: http://jsfiddle.net/87zqf/
If you want to center the div within its parent, that div must have some width less than 100%. For example:
div#these {
width: 350px;
margin: 0px auto;
border: solid red 1px;
}
For example: http://jsfiddle.net/nRKYV/
100% height on a div will not work, which is one of the shortcomings of CSS (in my opinion).
In the end, it can only be done if you know the height of your <div>. What you want to do then is to position it absolutely, 50% off the top and left of your screen and with a margin of half its height/width.
Check out the following JSFiddle for an idea of how it can be done:
http://jsfiddle.net/Lsh6j/1/
Note that you could also use percentages for the height and width on the surrounding <div>, but for the percentage-based height to work, the <div>'s parent element's height must be set/known.
Using this tutorial as a guideline. First add a centered class with this css.
.centered {
position: fixed;
top: 50%;
left: 50%;
}
Add this class to your div:
<div class="centered" id="these">
...images....
</div>
The problem is this centers the top left of the div. So you need to subtract off half of the width from the margin-left and half of the height from the margin-top.
Add this javascript (uses jQuery, let me know if thats a problem) to do the adjustment
<script>
function adjust() {
var height = $("#these").height();
var width = $("#these").width();
$("#these").css("margin-top", "-" + height/2 + "px");
$("#these").css("margin-left", "-" + width/2 + "px");
}
$(window).on("resize", adjust);
adjust();
This sets the margins appropriately on a resize, as well as calls the adjust method on the initial load.
The simplest solution (fiddle):
html, body {
height: 100%; /* necessary to make the window height be 100% */
margin: 0;
}
body {
display: table;
width: 100%;
}
#these {
display: table-cell;
vertical-align: middle; /* for table cells, it aligns their content */
text-align: center;
}
Another option (fiddle):
html, body {
height: 100%; /* necessary to make the window height be 100% */
margin: 0;
}
#these {
text-align: center; /* images are text content */
white-space: nowrap;
}
#these:after {
content: '';
display: inline-block; /* adding invisible inline placeholder after images */
height: 100%; /* make it 100% tall */
vertical-align: middle; /* and align the whole line to its vertical center */
}
img {
vertical-align: middle; /* align vertical centers of images to the middle of the line */
}
Unless you have some other css that'll mess this up, just add
#these {
text-align: center;
}
to the div wrapper and toggle visibility on/off to keep them in place: http://jsfiddle.net/63cHS/

Background image stretch y-axis only, keep repeat-x

I have an image set as a background image of a div. The DIV size is changing and inside their is the image which is a gradient.
CSS:
#scroller_shadow{
background-image:url(../img/ui/shadow.png);
background-repeat:repeat-x;
background-position:top;
}
I need a cross-browser solution for making the image fit the height of the div in the y-axis only, keeping the repeat-x. The DIV is being resized dynamically via JQuery.
Their might be a cross-browser option using JQuery. I don't mind using scripts to achieve that in order to get cross-browser support (IE7+). I don't want to stretch the image because it loses the intensity when you stretch the image on the x-axis, making a semi-transparent png image almost transparent.
Thanks.
I had this problem too. It's easy in most browsers, but IE8 and below it's tricky.
Solution for modern (anything not IE8 and below) browsers:
#scroller_shadow {
background: url(../img/ui/shadow.png) center repeat-x;
background-size: auto 100%;
}
There are jQuery plugins that can mimic background-size for IE8 and below, specifically backgroundSize.js but it doesn't work if you want it to repeat.
Anyways thus begins my terrible hack:
<div id="scroller_shadow">
<div id="scroller_shadow_tile">
<img src="./img/ui/shadow.png" alt="" >
<img src="./img/ui/shadow.png" alt="" >
<img src="./img/ui/shadow.png" alt="" >
...
<img src="./img/ui/shadow.png" alt="" >
</div>
</div>
Make sure to include enough <img>'s to cover the area needed.
CSS:
#scroller_shadow {
width: 500px; /* whatever your width is */
height: 100px; /* whatever your height is */
overflow: hidden;
}
#scroller_shadow_tile {
/* Something sufficiently large, you only to make it unreasonably wide if the width of the parent is dynamic. */
width: 9999px;
height: 100%;
}
#scroller_shadow_tile img {
height: 100%;
float: left;
width: auto;
}
Anyways, the idea is to create the stretch effect from the images.
JSFiddle.
background-position: left top;
background-repeat-y: repeat;
background-size: 100%;

How to horizontally center an img in a narrower parent div

I need to center images that will be wider than the parent div that contains them. the parent div is a fixed width and has the overflow set to hidden.
<div style='overflow:hidden; width:75px height:100px;'>
<img src='image.jpg' style='height:100px;' />
</div>
I must use an image as the child element because I need to resize the thumbnail dimensions and cannot rely on background-size since it is not supported on older versions of mobile safari which is a requirement. I also cannot use javascript for this, so it must be a css solution.
One more thing to note is that widths will vary between images, so I can't just use absolute positioning on the child element at a hard-coded offset.
Is this possible?
UPDATE:
for posterity, I've just found out that this can be accomplished on the older versions of mobile safari by using
-webkit-background-size:auto 100px;
of course, the background will be set as usual using 50% for left positioning. If you need this to work on another browser, the accepted solution is probably the best, but since this question was related to the iphone, this solution is a little cleaner.
How adverse are you to extra markup? Also, is there a max size for the images? For example, if your max image width is 225px then you could try:
<div class="frame">
<div>
<img src="image.jpg"/>
</div>
</div>
.frame {
overflow: hidden;
width: 75px;
height: 100px;
position: relative;
}
.frame > div {
position: absolute;
left: -5075px;
width: 10225px;
text-align: center;
}
.frame img {
height: 100px;
display: inline-block;
}
A fiddle example here: http://jsfiddle.net/brettwp/bW4xD/
Wouldn't using a background image still work? You shouldn't need to resize it.
Does something like this make sense? http://jsfiddle.net/QHRHP/44/
.container{
margin:0 auto;
width:400px;
border:2px solid #000;
height:250px;
background:url(http://placekitten.com/800/250) center top no-repeat;
}
Well if you know the width of the div and the width of the image, you can simply do some math.
Let's say the div is width 200px and the image is width 300px:
div.whatever {
width: 200px;
}
img.someImg {
left: -50px;
position: relative;
}
We know that since the width of the div is 200 pixes, then 100 pixels will be cropped from the image. If you want to center the image, then 50 pixels be hidden past the boundaries of the div on either side. Thus, we set the left position of the image to -50px.
Example (knowing the image size): http://jsfiddle.net/7YJCD/4/
Does that make sense?
If you don't know the image size or the div size, you can use javascript to detect these values and do the same thing.
Example (not knowing the image size, using jQuery javascript): http://jsfiddle.net/K2Rkg/1/
Just for reference, here's the original image.

div tag should not take up space

#decoration extend a bit outside of #wrapper. The problem is that if the browser viewport is 910px a vertical scroll bar appears.
How do I make it so that #decoration to not occupy space so the vertical scroll bar do not appear.
EDIT:
Check out this link to see what I want. Just in such a way no vertical scroll bar is there.
http://jsfiddle.net/HLqwN/
Using overflow:hidden will clip part of #decoration so that do not work.
<head>
<style>
#wrapper {
width: 900px;
position: relative;
}
#decoration {
position: absolute;
width: 542px;
height: 126px;
top: 0;
left: 660px;
}
</style>
</head>
<body>
<div id="wrapper">
<img id="decoration" src="/images/decoration.png" alt="" title="" />
<div id="content">
Some content
</div>
</div>
</body>
You could set overflow: hidden as the other answers are suggesting.
However, a "decoration" image should not be an <img>, it should be a CSS background-image.
Like this:
#wrapper {
height: 126px;
background: #ccc url(http://dummyimage.com/542x126/f0f/fff) 660px 0 no-repeat
}
See: http://jsfiddle.net/rdSJH/
if it is a decorative image, perhaps you should use it as a background image on the wrapper rather than in HTML source, you can still position it 660px left and it will not then cause a content scroll bar as it's not content.
#wrapper {
width: 900px;
position: relative;
background: url(background.png) no-repeat 660px 0;
}
[update after your clarification]
OK so you want the decoration to overlap the wrapper if there's space available to do so, like a pop-out?
is so try this, fiddle
notes: the span holding the background image should be outside the wrapper, no width on the span use your left co-ordinate and right: 0; or whatever margin from the right you might like, and still use the image as a background image. the span can sit down the bottom of your HTML out of the way
You could use overflow: hidden; on your wrapper
You might want to wrap a div around the decoration image and set overflow:hidden on that. Setting overflow:hidden on your wrapper might cause other content to be clipped depending on your layout.
If it's just a decoration you should try doing it with a background image though, then you don't have to worry about the clipping.

How to get div height to auto-adjust to background size?

How do I get a div to automatically adjust to the size of the background I set for it without setting a specific height (or min-height) for it?
There is a very nice and cool way to make a background image work like an img element so it adjust its height automatically. You need to know the image width and height ratio. Set the height of the container to 0 and set the padding-top as percentage based upon the image ratio.
It will look like the following:
div {
background-image: url('http://www.pets4homes.co.uk/images/articles/1111/large/feline-influenza-all-about-cat-flu-5239fffd61ddf.jpg');
background-size: contain;
background-repeat: no-repeat;
width: 100%;
height: 0;
padding-top: 66.64%; /* (img-height / img-width * container-width) */
/* (853 / 1280 * 100) */
}
You just got a background image with auto height which will work just like an img element. Here is a working prototype (you can resize and check the div height): http://jsfiddle.net/8m9ur5qj/
Another, perhaps inefficient, solution would be to include the image under an img element set to visibility: hidden;. Then make the background-image of the surrounding div the same as the image.
This will set the surrounding div to the size of the image in the img element but display it as a background.
<div style="background-image: url(http://your-image.jpg);">
<img src="http://your-image.jpg" style="visibility: hidden;" />
</div>
There is no way to auto adjust for background image size using CSS.
You can hack around it by measuring the background image on the server and then applying those attributes to the div, as others have mentioned.
You could also hack up some javascript to resize the div based on the image size (once the image has been downloaded) - this is basically the same thing.
If you need your div to auto-fit the image, I might ask why don't you just put an <img> tag inside your div?
This answer is similar to others, but is overall the best for most applications. You need to know the image size before hand which you usually do. This will let you add overlay text, titles etc. with no negative padding or absolute positioning of the image. They key is to set the padding % to match the image aspect ratio as seen in the example below. I used this answer and essentially just added an image background.
.wrapper {
width: 100%;
/* whatever width you want */
display: inline-block;
position: relative;
background-size: contain;
background: url('https://upload.wikimedia.org/wikipedia/en/thumb/6/67/Wiki-llama.jpg/1600px-Wiki-llama.jpg') top center no-repeat;
margin: 0 auto;
}
.wrapper:after {
padding-top: 75%;
/* this llama image is 800x600 so set the padding top % to match 600/800 = .75 */
display: block;
content: '';
}
.main {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
color: black;
text-align: center;
margin-top: 5%;
}
<div class="wrapper">
<div class="main">
This is where your overlay content goes, titles, text, buttons, etc.
</div>
</div>
I looked at some of the solutions and they're great but I think I found a surprisingly easy way.
First, we need to get the ratio from the background image. We simply divide one dimension through another. Then we get something like for example 66.4%
When we have image ratio we can simply calculate the height of the div by multiplying the ratio by viewport width:
height: calc(0.664 * 100vw);
To me, it works, sets div height properly and changes it when the window is resized.
Maybe this can help, it's not exactly a background, but you get the idea:
<style>
div {
float: left;
position: relative;
}
div img {
position: relative;
}
div div {
position: absolute;
top:0;
left:0;
}
</style>
<div>
<img src="http://antwrp.gsfc.nasa.gov/apod/image/0903/omegacen_davis.jpg" />
<div>Hi there</div>
</div>
Pretty sure this will never been seen all the way down here. But if your problem was the same as mine, this was my solution:
.imaged-container{
background-image:url('<%= asset_path("landing-page.png") %> ');
background-repeat: no-repeat;
background-size: 100%;
height: 65vw;
}
I wanted to have a div in the center of the image, and this will allow me of that.
There is a pure CSS solution that the other answers have missed.
The "content:" property is mostly used to insert text content into an element, but can also be used to insert image content.
.my-div:before {
content: url("image.png");
}
This will cause the div to resize its height to the actual pixel size of the image. To resize the width too, add:
.my-div {
display: inline-block;
}
The recently introduced CSS aspect-ratio attribute (~2020-2021) is a great way to do this without padding hacks and is supported on all evergreen browsers.
Since we need to know the aspect ratio of the image ahead of time, and in many usecases you'll be able to predetermine the image dimension ratio ahead of time (but not always for user generated content), you can either hardcode a single style or inline the css when necessary.
aspect-ratio will calculate the height when the width is specified, based on the provided ratio (or calculate width, if the height is specified).
div {
aspect-ratio: 3 / 2; /*common ratio, like an 800*600px image */
width: 200px; /* computed height will be 133.33px, which is width/aspect-ratio */
background: red; /* so any image bleed is shown*/
background-image: url('https://images.unsplash.com/photo-1631163190830-8770a0ad4aa9?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80');
}
<div></div>
You can do it server side: by measuring the image and then setting the div size, OR loading the image with JS, read it's attributes and then set the DIV size.
And here is an idea, put the same image inside the div as an IMG tag, but give it visibility: hidden + play with position relative+ give this div the image as background.
I had this issue and found Hasanavi's answer but I got a little bug when displaying the background image on a wide screen - The background image didn't spread to the whole width of the screen.
So here is my solution - based on Hasanavi's code but better... and this should work on both extra-wide and mobile screens.
/*WIDE SCREEN SUPPORT*/
#media screen and (min-width: 769px) {
div {
background-image: url('http://www.pets4homes.co.uk/images/articles/1111/large/feline-influenza-all-about-cat-flu-5239fffd61ddf.jpg');
background-size: cover;
background-repeat: no-repeat;
width: 100%;
height: 0;
padding-top: 66.64%; /* (img-height / img-width * container-width) */
/* (853 / 1280 * 100) */
}
}
/*MOBILE SUPPORT*/
#media screen and (max-width: 768px) {
div {
background-image: url('http://www.pets4homes.co.uk/images/articles/1111/large/feline-influenza-all-about-cat-flu-5239fffd61ddf.jpg');
background-size: contain;
background-repeat: no-repeat;
width: 100%;
height: 0;
padding-top: 66.64%; /* (img-height / img-width * container-width) */
/* (853 / 1280 * 100) */
}
}
As you might have noticed, the background-size: contain; property doas not fit well in extra wide screens, and the background-size: cover; property does not fit well on mobile screens so I used this #media attribute to play around with the screen sizes and fix this issue.
This Worked For Me:
background-image: url("/assets/image_complete_path");
background-position: center; /* Center the image */
background-repeat: no-repeat; /* Do not repeat the image */
background-size: cover;
height: 100%;
If it is a single predetermined background image and you want the div to to be responsive without distorting the aspect ratio of the background image you can first calculate the aspect ratio of the image and then create a div which preserves it's aspect ratio by doing the following:
Say you want an aspect ratio of 4/1 and the width of the div is 32%:
div {
width: 32%;
padding-bottom: 8%;
}
This results from the fact that padding is calculated based on the width of the containing element.
Adding to the original accepted answer just add style width:100%; to the inner image so it will auto-shrink/expand for mobile devices and wont end up taking large top or bottom margins in mobile view.
<div style="background-image: url(http://your-image.jpg);background-position:center;background-repeat:no-repeat;background-size: contain;height: auto;">
<img src="http://your-image.jpg" style="visibility: hidden; width: 100%;" />
</div>
How about this :)
.fixed-centered-covers-entire-page{
margin:auto;
background-image: url('https://i.imgur.com/Ljd0YBi.jpg');
background-repeat: no-repeat;background-size:cover;
background-position: 50%;
background-color: #fff;
left:0;
right:0;
top:0;
bottom:0;
z-index:-1;
position:fixed;
}
<div class="fixed-centered-covers-entire-page"></div>
Demo: http://jsfiddle.net/josephmcasey/KhPaF/
I would do the reverse and place the image inside of the main div with a width of 100%, which will make both the div and image responsive to screen size,
Then add the content within an absolute positioned div with width and height of 100% inside of the main div.
<div class="main" style="position: relative; width: 100%;">
<img src="your_image.png" style="width: 100%;">
<div style="position: absolute; width: 100%; height: 100%; display: flex...">
YOUR CONTENT
</div>
</div>
May be this can help, it's not exactly a background, but you get the simple idea
<style>
div {
float: left;
position: relative;
}
div img {
position: relative;
}
div div {
position: absolute;
top:0;
left:0;
}
</style>
<div>
<img src="http://www.planwallpaper.com/static/images/recycled_texture_background_by_sandeep_m-d6aeau9_PZ9chud.jpg" />
<div>Hello</div>
</div>
You can do something like that
<div style="background-image: url(http://your-image.jpg); position:relative;">
<img src="http://your-image.jpg" style="opacity: 0;" />
<div style="position: absolute;top: 0;width: 100%;height: 100%;">my content goes here</div>
</div>
If you know the ratio of the image at build time, want the height based off of the window height and you're ok targeting modern browsers (IE9+), then you can use viewport units for this:
.width-ratio-of-height {
overflow-x: scroll;
height: 100vh;
width: 500vh; /* width here is 5x height */
background-image: url("http://placehold.it/5000x1000");
background-size: cover;
}
Not quite what the OP was asking, but probably a good fit for a lot of those viewing this question, so wanted to give another option here.
Fiddle: https://jsfiddle.net/6Lkzdnge/
Suppose you have some thing like this:
<div class="content">
... // inner HTML
</div>
and you want add a background to it, but you do not know the dimension of the image.
I had a similar problem, and I solved it by using grid:
HTML
<div class="outer">
<div class="content">
... // inner HTML
</div>
<img class="background" />
</div>
CSS
.outer{
display: grid;
grid-template: auto / auto;
// or you can assign a name for this block
}
.content{
grid-area: 1 / 1 / 2 / 2;
z-index: 2;
}
.background{
grid-area: 1 / 1 / 2 / 2;
z-index: 1;
}
z-index is just for placing image actually at the background, you can of course place img.background above the div.content.
NOTE: it might cause the div.content has same height of the picture, so if div.content have any children that placed according to its height, you might want set a number not something like 'auto'.
inspired by the most liked answer, I ended up coming up with a solution using min-height and 'vw' unit
I had an image in a very unusual proportion
through experimentation I ended up using
min-height: 36vw;
that value must change, according to the ratio of your image
css code used im my actual page:
background:url('your-background-image-adress') center center no-repeat;
background-size: 100%;
background-position: top center;
margin-top: 50px;
width: 100%;
min-height: 36vw;
code pen example https://codepen.io/viniciusrad/pen/GRNPXoL
Had this issue with the Umbraco CMS and in this scenario you can add the image to the div using something like this for the 'style' attribute of the div:
style="background: url('#(image.mediaItem.Image.umbracoFile)') no-repeat scroll 0 0 transparent; height: #(image.mediaItem.Image.umbracoHeight)px"
I have been dealing with this issue for a while and decided to write a jquery plugin to solve this problem.
This plugin will find all the elements with class "show-bg" (or you can pass it your own selector) and calculate their background image dimensions.
all you have to do is include this code, mark the desired elements with class="show
Enjoy!
https://bitbucket.org/tomeralmog/jquery.heightfrombg
The best solution i can think of is by specifying your width and height in percent . This will allow you to rezise your screen based on your monitor size. its more of responsive layout..
For an instance.
you have
<br/>
<div> . //This you set the width percent to %100
<div> //This you set the width percent to any amount . if you put it by 50% , it will be half
</div>
</div>
This is the best option if you would want a responsive layout, i wouldnt recommend float , in certain cases float is okay to use. but in most cases , we avoid using float as it will affect a quite of number of things when you are doing cross-browser testing.
Hope this helps :)
actually it's quite easy when you know how to do it:
<section data-speed='.618' data-type='background' style='background: url(someUrl)
top center no-repeat fixed; width: 100%; height: 40vw;'>
<div style='width: 100%; height: 40vw;'>
</div>
</section>
the trick is just to set the enclosed div just as a normal div with dimensional values same as the background dimensional values (in this example, 100% and 40vw).
I solved this using jQuery. Until new CSS rules allow for this type of behavior natively I find it is the best way to do it.
Setup your divs
Below you have your div that you want the background to appear on ("hero") and then the inner content/text you want to overlay on top of your background image ("inner"). You can (and should) move the inline styles to your hero class. I left them here so it's quick and easy to see what styles are applied to it.
<div class="hero" style="background-image: url('your-image.png'); background-size: 100%; background-repeat: no-repeat; width: 100%;">
<div class="inner">overlay content</div>
</div>
Calculate image aspect ratio
Next calculate your aspect ratio for your image by dividing the height of your image by the width. For example, if your image height is 660 and your width is 1280 your aspect ratio is 0.5156.
Setup a jQuery window resize event to adjust height
Finally, add a jQuery event listener for window resize and then calculate your hero div's height based off of the aspect ratio and update it. This solution typically leaves an extra pixel at the bottom due to imperfect calculations using the aspect ratio so we add a -1 to the resulting size.
$(window).on("resize", function ()
{
var aspect_ratio = .5156; /* or whatever yours is */
var new_hero_height = ($(window).width()*aspect_ratio) - 1;
$(".hero").height(new_hero_height);
}
Ensure it works on page load
You should perform the resize call above when the page loads to have the image sizes calculated at the outset. If you don't, then the hero div won't adjust until you resize the window. I setup a separate function to do the resize adjustments. Here's the full code I use.
function updateHeroDiv()
{
var aspect_ratio = .5156; /* or whatever yours is */
var new_hero_height = ($(window).width()*aspect_ratio) - 1;
$(".hero").height(new_hero_height);
}
$(document).ready(function()
{
// calls the function on page load
updateHeroDiv();
// calls the function on window resize
$(window).on("resize", function ()
{
updateHeroDiv();
}
});
If you can make an image on Photoshop where the main layer has an opacity of 1 or so and is basically transparent, put that img in the div and then make the real picture the background image. THEN set the opacity of the img to 1 and add the size dimensions you want.
That picture is done that way, and you can't even drag the invisible image off the page which is cool.
just add to div
style="overflow:hidden;"

Resources