Background-image resize after window-size - javascript

I'm pretty new to web-development and web-design, and I'm working on a website for a company right now(www.momentium.no). They want to have the background image(s) at the top recognize the browsers window-size, so that the image(s) fills the whole screen and don't show the content below before you scroll down when you load the website.
Could anyone of you check this out? Would be great to get a little bit of help!
Thanks,
Yngvar

Setting the height to 100% using CSS will work, but you'll have to revise your HTML structure in order to maintain it's flow when the window is resized.
Otherwise, you can try the following code snippets:
JS:
var $imageWrapper = $('#background-image'),
$contentSpacer = $('section#wrapper > header'),
// Some buffer value, adjust this to get the rest of the content aligned properly
buffer = 200;
// Set the div height on pageload
$(document).ready(function() {
var windowHeight = $(window).height();
$imageWrapper.height( windowHeight );
$contentSpacer.height( windowHeight );
});
// Change the div height on window resize
$(window).resize(function() {
var $this = $(this),
thisHeight = $this.height();
// Set the height of the image container to the window height
$imageWrapper.height( thisHeight );
$contentSpacer.height( thisHeight - buffer );
});
CSS:
#background-image {
background-size: cover;
// Change this to the minimum height your page will support
min-height: 600px;
}
The rest of the code you have seems correct, so adding these should fix things up. A couple of things to keep in mind here:
The JS isn't placing any limitation on the height being applied here, so the CSS will still apply even if the window is resized to 10px height. Most designs have a minimum height/width before breaking, so using a min-height on your #background-image div might be a good idea.
Check the browser support before implementing, if you need to support one of the unsupported browsers, you'll need to either write a fallback or restructure your code in such a way that it degrades gracefully. IE9+, Chrome21+ and FF26+ should be good enough though.
Looks like you're using a spacer in the main section to ensure that the page content comes in after the main slider. The structure of the page can be modified so that you don't have to modify two element heights. As I mentioned at the beginning, you can probably use the pure CSS solution if you restructure.

You can have 2 solutions :
As Pete says, you can use "background-size" css3, but it will not be compatible for older browser
You can use javascript with $(window).height() and $(window).width

The Only Way is create a repponsive design for your company..all the problem will be solved by responsive design...
Change the image size depends upon the browser window size Other wise
change the image to another one also possible

You can set the height of your "background-image" div to 100%, it will work.
Check this code:
#background-image {
width: 100%;
height: 100% !important;
position: absolute !important;
overflow: hidden;
text-align: center;
background: #000;
}

Related

Prevent percentage height from increasing when the browser navigation bars are hidden in Safari [duplicate]

I have a very odd issue... in every browser and mobile version I encountered this behavior:
all the browsers have a top menu when you load the page (showing the address bar for example) which slide up when you start scrolling the page.
100vh sometimes is calculated only on the visible part of a viewport, so when the browser bar slide up 100vh increases (in terms of pixels)
all layout re-paint and re-adjust since the dimensions have changed
a bad jumpy effect for user experience
How can avoid this problem? When I first heard of viewport-height I was excited and I thought I could use it for fixed height blocks instead of using javascript, but now I think the only way to do that is in fact javascript with some resize event...
you can see the problem at: sample site
Can anyone help me with / suggest a CSS solution?
simple test code:
/* maybe i can track the issue whe it occours... */
$(function(){
var resized = -1;
$(window).resize(function(){
$('#currenth').val( $('.vhbox').eq(1).height() );
if (++resized) $('#currenth').css('background:#00c');
})
.resize();
})
*{ margin:0; padding:0; }
/*
this is the box which should keep constant the height...
min-height to allow content to be taller than viewport if too much text
*/
.vhbox{
min-height:100vh;
position:relative;
}
.vhbox .t{
display:table;
position:relative;
width:100%;
height:100vh;
}
.vhbox .c{
height:100%;
display:table-cell;
vertical-align:middle;
text-align:center;
}
<div class="vhbox" style="background-color:#c00">
<div class="t"><div class="c">
this div height should be 100% of viewport and keep this height when scrolling page
<br>
<!-- this input highlight if resize event is fired -->
<input type="text" id="currenth">
</div></div>
</div>
<div class="vhbox" style="background-color:#0c0">
<div class="t"><div class="c">
this div height should be 100% of viewport and keep this height when scrolling page
</div></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Unfortunately this is intentional…
This is a well know issue (at least in safari mobile), which is intentional, as it prevents other problems. Benjamin Poulain replied to a webkit bug:
This is completely intentional. It took quite a bit of work on our part to achieve this effect. :)
The base problem is this: the visible area changes dynamically as you scroll. If we update the CSS viewport height accordingly, we need to update the layout during the scroll. Not only that looks like shit, but doing that at 60 FPS is practically impossible in most pages (60 FPS is the baseline framerate on iOS).
It is hard to show you the “looks like shit” part, but imagine as you scroll, the contents moves and what you want on screen is continuously shifting.
Dynamically updating the height was not working, we had a few choices: drop viewport units on iOS, match the document size like before iOS 8, use the small view size, use the large view size.
From the data we had, using the larger view size was the best compromise. Most website using viewport units were looking great most of the time.
Nicolas Hoizey has researched this quite a bit: https://nicolas-hoizey.com/2015/02/viewport-height-is-taller-than-the-visible-part-of-the-document-in-some-mobile-browsers.html
No fix planned
At this point, there is not much you can do except refrain from using viewport height on mobile devices. Chrome changed to this as well in 2016:
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/BK0oHURgmJ4
https://developers.google.com/web/updates/2016/12/url-bar-resizing
You can try min-height: -webkit-fill-available; in your css instead of 100vh. It should be solved
in my app I do it like so (typescript and nested postcss, so change the code accordingly):
const appHeight = () => {
const doc = document.documentElement
doc.style.setProperty('--app-height', `${window.innerHeight}px`)
}
window.addEventListener('resize', appHeight)
appHeight()
in your css:
:root {
--app-height: 100%;
}
html,
body {
padding: 0;
margin: 0;
overflow: hidden;
width: 100vw;
height: 100vh;
#media not all and (hover:hover) {
height: var(--app-height);
}
}
it works at least on chrome mobile and ipad. What doesn't work is when you add your app to homescreen on iOS and change the orientation a few times - somehow the zoom levels mess with the innerHeight value, I might post an update if I find a solution to it.
Demo
Look at this answer: https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
// First we get the viewport height and we multiple it by 1% to get a value for a vh unit
let vh = window.innerHeight * 0.01;
// Then we set the value in the --vh custom property to the root of the document
document.documentElement.style.setProperty('--vh', `${vh}px`);
// We listen to the resize event
window.addEventListener('resize', () => {
// We execute the same script as before
let vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
body {
background-color: #333;
}
.module {
height: 100vh; /* Use vh as a fallback for browsers that do not support Custom Properties */
height: calc(var(--vh, 1vh) * 100);
margin: 0 auto;
max-width: 30%;
}
.module__item {
align-items: center;
display: flex;
height: 20%;
justify-content: center;
}
.module__item:nth-child(odd) {
background-color: #fff;
color: #F73859;
}
.module__item:nth-child(even) {
background-color: #F73859;
color: #F1D08A;
}
<div class="module">
<div class="module__item">20%</div>
<div class="module__item">40%</div>
<div class="module__item">60%</div>
<div class="module__item">80%</div>
<div class="module__item">100%</div>
</div>
For me such trick made a job:
height: calc(100vh - calc(100vh - 100%))
We have new viewport units lvh, svh and dvh to the rescue. This was demonstrated in the latest Google I/O 2022 video on web works.
You would probably want to stick with dvh for the browser to adapt to the mobile device's hidden tabs while scrolling. It works the similar way for width with dvw, lvw and svw units.
Here is a neat illustration from the video: https://youtu.be/Xy9ZXRRgpLk?t=982
Can I use?
This was currently working on my Chrome canary with the flag "Experimental features" enabled.
You can do this by adding following script and style
function appHeight() {
const doc = document.documentElement
doc.style.setProperty('--vh', (window.innerHeight*.01) + 'px');
}
window.addEventListener('resize', appHeight);
appHeight();
Style
.module {
height: 100vh; /* Fallback for browsers that do not support Custom Properties */
height: calc(var(--vh, 1vh) * 100);
}
Set your body position to fixed, set the height to 100%
body { position: fixed; height: 100% }
That's it, then the mobile browser will understand what you want.
Now the body will grow or shrink following the browser's view height, no matter if there is a URL bar or not, or if there are tabs (like in mobile safari) or not. The body will always get full view.
For many of the sites I build the client will ask for a 100vh banner and just as you have found, it results in a bad "jumpy" experience on mobile when you begin to scroll. This is how I solve the problem for a smooth consistent experience across all devices:
I first set my banner element CSS to height:100vh
Then I use jQuery to get the height in pixels of my banner element and apply an inline style using this height.
var viewportHeight = $('.banner').outerHeight();
$('.banner').css({ height: viewportHeight });
Doing this solves the issue on mobile devices as when the page loads, the banner element is set to 100vh using CSS and then jQuery overrides this by putting inline CSS on my banner element which stops it from resizing when a user begins to scroll.
However, on desktop if a user resizes their browser window my banner element won't resize because it now has a fixed height set in pixels due to the above jQuery. To address this I use Mobile Detect to add a 'mobile' class to the body of my document. And then I wrap the above jQuery in an if statement:
if ($('body').hasClass('mobile')) {
var viewportHeight = $('.banner').outerHeight();
$('.banner').css({ height: viewportHeight });
}
As a result, if a user is on a mobile device the class 'mobile' is present on the body of my page and the above jQuery is executed. So my banner element will only get the inline CSS applied on mobile devices meanwhile on desktop the original 100vh CSS rule remains in place.
I came up with a React component – check it out if you use React or browse the source code if you don't, so you can adapt it to your environment.
It sets the fullscreen div's height to window.innerHeight and then updates it on window resizes.
As I was looking for a solution some days, here is mine for everyone using VueJS with Vuetify (my solution uses v-app-bar, v-navigation-drawer and v-footer):
I created App.scss (used in App.vue) with the following content:
.v-application {
height: 100vh;
height: -webkit-fill-available;
}
.v-application--wrap {
min-height: 100vh !important;
min-height: -webkit-fill-available !important;
}
You can try giving position: fixed; top: 0; bottom: 0; properties to your container.
#nils explained it clearly.
What's next then?
I just went back to use relative 'classic' % (percentage) in CSS.
It's often more effort to implement something than it would be using vh, but at least, you have a pretty stable solution which works across different devices and browsers without strange UI glitches.
The the problem still remains to this date, unfortunately. And the biggest misleading it's impossible to represent the situation by using browser's devices toolbar.
I've just solved the issue like so (tested on PC, iOS and android browsers):
.your_class {
height: 100vh,
max-height: 100%, // <-- add the line
...some other props,
}
I hope it'll save your time.
The following code solved the problem (with jQuery).
var vhHeight = $("body").height();
var chromeNavbarHeight = vhHeight - window.innerHeight;
$('body').css({ height: window.innerHeight, marginTop: chromeNavbarHeight });
And the other elements use % as a unit to replace vh.
As I am new, I can't comment on other answers.
If someone is looking for an answer to make this work (and can use javascript - as it seems to be required to make this work at the moment) this approach has worked pretty well for me and it accounts for mobile orientation change as well. I use Jquery for the example code but should be doable with vanillaJS.
-First, I use a script to detect if the device is touch or hover. Bare-bones example:
if ("ontouchstart" in document.documentElement) {
document.body.classList.add('touch-device');
} else {
document.body.classList.add('hover-device');
}
This adds class to the body element according to the device type (hover or touch) that can be used later for the height script.
-Next use this code to set height of the device on load and on orientation change:
if (jQuery('body').hasClass("touch-device")) {
//Loading height on touch-device
function calcFullHeight() {
jQuery('.hero-section').css("height", $(window).height());
}
(function($) {
calcFullHeight();
jQuery(window).on('orientationchange', function() {
// 500ms timeout for getting the correct height after orientation change
setTimeout(function() {
calcFullHeight();
}, 500);
});
})(jQuery);
} else {
jQuery('.hero-section').css("height", "100vh");
}
-Timeout is set so that the device would calculate the new height correctly on orientation change. If there is no timeout, in my experience the height will not be correct. 500ms might be an overdo but has worked for me.
-100vh on hover-devices is a fallback if the browser overrides the CSS 100vh.
I just found a web app i designed has this issue with iPhones and iPads, and found an article suggesting to solve it using media queries targeted at specific Apple devices.
I don't know whether I can share the code from that article here, but the address is this: http://webdesignerwall.com/tutorials/css-fix-for-ios-vh-unit-bug
Quoting the article: "just match the element height with the device height using media queries that targets the older versions of iPhone and iPad resolution."
They added just 6 media queries to adapt full height elements, and it should work as it is fully CSS implemented.
Edit pending: I'm unable to test it right now, but I will come back and report my results.
Do not use recommended approaches such as -webkit-fill-available.
I just spent all day rushing around to fix this "bug".
Add a class when your app is loaded with a browser with a "chin".
JavaScript
// Angular example but applicable for any JS solution
#HostBinding('class.browser-has-chin') browserHasChin: boolean = false;
public ngOnInit(): void {
this.browserHasChin = this._isMobileSafari();
}
private _isMobileSafari() {
return navigator.userAgent.match(/(iPod|iPhone|iPad)/) && navigator.userAgent.match(/AppleWebKit/) ? true : false;
}
CSS
.browser-has-chin {
#media screen and (max-device-width: 767px){
// offset with padding or something
}
}
NOTES:
There are major issues with the -webkit-fill-available prop for cross-browser compatibility.
I was able to get it working in Chrome and iOS Safari to fix the chin/height calculation issue. However it broke Android Chrome and Firefox had bugs with it too.
It seems that -webkit-fill-available was rushed into webkit at some point and perhaps adopted haphazardly by Apple as a fix for chin/height calculation?
It relies on intrinsic sizing which is NOT safe to use yet.
I have created two examples below:
To showcase how height: 100vh as height can lead to scroll in mobile chrome browsers:
code : https://codesandbox.io/embed/mobile-viewport-100vh-issue-nxx8z?fontsize=14&hidenavigation=1&theme=dark
demo: https://nxx8z.csb.app/
Solution using position: fixed to resolve the issue and with purely CSS:
code : https://codesandbox.io/s/mobile-viewport-100vh-issue-fix-forked-ypx5x?file=/index.html
demo : https://ypx5x.csb.app/
The VH 100 does not work well on mobile as it does not factor in the iOS bar (or similar functionality on other platforms).
One solution that works well is to use JavaScript "window.innerHeight".
Simply assign the height of the element to this value e.g.
$('.element-name').height(window.innerHeight);
Note: It may be useful to create a function in JS, so that the height can change when the screen is resized. However, I would suggest only calling the function when the width of the screen is changed, this way the element will not jump in height when the iOS bar disappears when the user scrolls down the page.
React hooks solution with useEffect and useState
function App() {
const [vh, setVh] = useState(window.innerHeight);
useEffect(() => {
const updateVh = () => {
setVh(window.innerHeight);
};
window.addEventListener('resize', updateVh);
return () => window.removeEventListener('resize', updateVh);
}, []);
return (
<div style={{ height: vh }}>
{vh} px
</div>
);
}
Demo: https://jsfiddle.net/poooow/k570nfd9/
Because it won't be fixed, you can do something like:
# html
<body>
<div class="content">
<!-- Your stuff here -->
</div>
</body>
# css
.content {
height: 80vh;
}
For me it was the fastest and more pure solution than playing with the JavaScript which could not work on many devices and browsers.
Just use proper value of vh which fits your needs.
The following worked for me:
html { height: 100vh; }
body {
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100vw;
}
/* this is the container you want to take the visible viewport */
/* make sure this is top-level in body */
#your-app-container {
height: 100%;
}
The body will take the visible viewport height and #your-app-container with height: 100% will make that container take the visible viewport height.
Using vh on mobile devices is not going to work with 100vh, due to their design choices using the entire height of the device not including any address bars etc.
If you are looking for a layout including div heights proportionate to the true view height I use the following pure css solution:
:root {
--devHeight: 86vh; //*This value changes
}
.div{
height: calc(var(--devHeight)*0.10); //change multiplier to suit required height
}
You have two options for setting the viewport height, manually set the --devHeight to a height that works (but you will need to enter this value for each type of device you are coding for)
or
Use javascript to get the window height and then update --devheight on loading and refreshing the viewport (however this does require using javascript and is not a pure css solution)
Once you obtain your correct view height you can create multiple divs at an exact percentage of total viewport height by simply changing the multiplier in each div you assign the height to.
0.10 = 10% of view height
0.57 = 57% of view height
Hope this might help someone ;)
Here's a work around I used for my React app.
iPhone 11 Pro & iPhone Pro Max - 120px
iPhone 8 - 80px
max-height: calc(100vh - 120px);
It's a compromise but relatively simple fix
A nice read about the problem and its possible solutions can be found in this blog post: Addressing the iOS Address Bar in 100vh Layouts
The solution I ended up in my React application is utilising the react-div-100vh library described in the post above.
Brave browser on iOS behaves differently (buggy?). It changes viewport height dynamically accordingly to showing/hiding address bar. It is kind of annoying because it changes page's layout dependent on vw/vh units.
Chrome and Safari is fine.
I solved it by putting the most outer div at position: absolute and then just setting the height to 100%:
CSS:
.outer {
position: absolute;
height: 100%;
}
HTML:
<div class="outer">
<!-- content -->
</div>
It seems like CSS fix is unreliable and JS one works fine but the element is jumping when user opens the page.
I solved the issue using JS from other answers + fadeIn animation to hide jumping.
This won't fit all the use cases, but for some of them, like a button that has to be at the bottom, could be a good solution.
The people who found this answer and are struggling with an issue of wiered jumping of elements on mobile view when scrolling downward/upward whose position is fixed w.r.t the root element need to specify the property in terms of bottom rather than top and should give a field value in px. This solves the issue
change this:
element{
position: fixed;
top: 90vh;
left: 90vh;
transform: translate(-95%, -95%);
}
to this:
element{
position: fixed;
bottom: 90px; /* this is the change */
left: 90vh;
transform: translate(-95%, -95%);
}

Setting the height of a button as a % of the window

I'm trying to set the height of a button as a % of the user's window. It seems this works :
#mybutton {
padding: 10%;
}
But obviously doesn't quite achieve what I need (in addition, it's not responsive to the browser's size).
This doesn't work :
#mybutton {
height: 10%;
}
I've also tried doing it with javascript (I really don't master it), but none of those two tries work either.
document.getElementById('mybutton').style.height = "10%";
document.getElementById('mybutton').style.height = window.outerHeight / 10;
How can I do that ?
PS : I've also tried with fixed values (100px) to see if I could change the height, and it seems I can't at all.
NB : I'd like it to be responsive to the user's window, meaning that if I reduce the size of my browser, the button should keep a height of 10% of it.
Thanks.
You can use viewport units:
#mybutton {
height: 10vh;
}
Viewport-relative lengths are supported by all modern browsers.
Though the answer has been selected I wanted to note three things here.
Note #1
#mybutton {
height:10%;
}
does not work because the height is relative to the parent and the parents, html and body, are not 100%. Checkout this fiddle, http://jsfiddle.net/3sLafksx/1/
Note #2
The reason padding worked is because padding is not relative to the parent's height but to the parent's width. Which in case of a div element or plainly in the body is 100% of the window size.
Refer: https://stackoverflow.com/a/8211457/1799502 and http://www.w3schools.com/cssref/pr_padding.asp
Note #3
Using the viewport height vh and viewport width vw units is a very good idea but #rnevius was not kidding when he said all modern browsers, you need at least IE9 or Android 4.4
IF your element is a span, it won't work like you wish, but using a div, your code will work.
document.getElementById('b').style.height = (window.outerHeight / 10) + 'px';
Using css, your button will be X% of your parent container, so if you have a parent container with 300px height, your button'll be 30px height (using height: 10%).
You can also use the vh unit like #rnevius pointed out. But remember that a span won't work as you want, because it isn't a block element. (unless you force it by using display: (inline-)block).
Try putting a !important
#mybutton {
height: 10% !important;
}

Responsive Galleria

I'm trying to use this plugin Galleria in its responsive mode, which basically means it will re draw itself based on its container size as the window re-sizes. The demo on the link I've provided shows a really good example. You can see that, as you resize your window, the whole gallery adjusts accordingly. Now my issue is, the plugin won't let me initialize the gallery unless a height has been specified for the DOM element that is used as its container. This means, I've had to write a whole lot of javascript code to respond window resizes - it destroys the point of it having a responsive mode quite a bit - but in the website above, nowhere can I find an explicit height specified. Can someone explain to me where I'm going wrong?
I figured it out by myself. Posting my answer -
When initializing the gallery - specify your height in percentages - as below. I'm guessing it takes 50% of window height as its value in this case. This way, you don't need to explicitly specify heights anywhere and it works as advertised
Galleria.run('#gallery', {responsive:true, height:0.5, debug:false});
Galleria needs a height to initialise correctly. You can do this either via CSS or JS.
If you would like it to fill the width and height of the screen, I would recommend setting a width and height of 100% via CSS. And its parent container needs to be 100%. See below.
**JS:**
Galleria.run('#galleria', {
responsive:true,
showCounter:true,
thumbnails:false,
trueFullscreen:true,
});
**CSS:**
#galleria{
width:100%;
height: 100%;
position: fixed;
z-index: 9999;
top:0px;
bottom: 0px;
}
body,html{
height:100%;
width:100%;
}
The height option ( if it's < 2.0) is relative to the width of the container. So height:0.5 would have a height that is half the width of the container (w=2, h=1).
height:1.5 would result in (w=2, h=3)
To keep it responsive you can use max-width rather than width when styling the container.
If the height option is set to 2.0 or more, it is interpreted as pixels. So height:2.0 will only be 2px tall.

Dynamic Background Scrolling

Here's a link to what I'll be referring to.
I'm having some trouble getting the background image to work the way I'd like it to.
I want the background to auto resize based on the width of the window, which it is already doing correctly. If you make your window smaller you'll see the background shrink with it.
Here's the issue. If you make your window wide (short) then the background will resize and go too high so you can't see the top of the background anymore (since the background is bottom positioned).
I want the background to be top position when you are at the top of the page, and as you scroll down it will slowly move to be bottom positioned. Sort of like the effect of an Android phone's background when you move left and right. Of course, keep in mind that I still want the background to auto-resize when you make the window smaller.
html {
background-color: #70d4e3;
height: 100%;
}
body {
height: 100%;
}
.background {
margin-top: 45px;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: -9999;
}
.banner {
margin: 0px auto;
width: 991px;
margin-bottom: -9px;
}
.content {
background: url("http://i.imgur.com/daRJl.png") no-repeat scroll center center transparent;
height: 889px;
margin: 0 auto;
width: 869px;
}
.innerContent {
padding: 30px;
}
<img src="http://i.imgur.com/6d5Cm.jpg" alt="" class="background" />
<div class="banner">
<img src="http://i.imgur.com/JptsZ.jpg" alt="" />
</div>
<div class="content">
<div class="innerContent">
testing
</div>
</div>
Maybe some javascript or jquery would be needed to achieve this.
Well, this was fun, thanks!
I hope you don't mind me taking the liberty to use percentages to make my life a little bit easier and possibly the script slightly more robust since I can reliably use floats with percentages.
What I did is make the layout, html and css comply with the rules you need for the bg to be animated properly, they stayed largely the same from what you had.
Then it was just a question of figuring out the calculations needed with the right properties to figure out the percentage you were from the top, the *20 is actually the amount of space 'left' to fill by the background image in percentages (as the background height is 80%).
They I moved the calculations to a function so I could call that on scroll and on window resize, making sure it's initiated on any event that modifies the window somehow...
Didn't do extensive testing but it worked in Chrome and I'm tired :p
I believe this is what you are looking for:
http://jsfiddle.net/sg3s/RSqrw/15/ See edit 2
If you wanted this the other way arround just make the page background start at the top and modify that:
http://jsfiddle.net/sg3s/RSqrw/14/ See edit 2
Edit:
As a bonus, and since I had never actually written jquery script as a 'plugin', I decided to convert this into one. What I came up with should be easy to implement and use!
http://jsfiddle.net/sg3s/RSqrw/52/ See Edit 3
Functionality successfully tested in Chrome, Firefox 3.6, IE9 + compatibility mode
Edit 2:
Reading the question again checking if I did it right I noticed I didn't quite do what you want, so I updated the link in the first edit which gives you a plugin in which you can have several options for the scrolling background. It retains my 'old' interpetation while also doing what you want... Read comments in code for some extra descriptions.
Edit 3:
As I went to work today I was bothered with the fact that my plugin 'try' was a little bloated. And as you mentioned in the comment it didn't quite fit the requirements.
So I rewrote it to only do what you want and not much more, tested in Chrome Firefox, IE9 +compat etc etc.. This script is a lot cleaner.
http://jsfiddle.net/sg3s/vZxHW/
You can chose to make the background stick to the top or bottom if the height fits in the window. Nothing else, but that is already more than enough to do some pretty cool stuff :p
An exact solution: Fiddle: http://jsfiddle.net/srGHE/2/show/
View source
Thanks for the challenge. See below for the solution, which is complying with all requirements, including recommended yet optional (with steps on how to remove these) features. I only show the changed parts of your page, with an explanation after each section (CSS, HTML and JavaScript):
CSS (changes):
html,body{
margin: 0;
height: 100%;
padding: 0;
}
body{
background-color: #70d4e3;
}
#background { /*Previously: .background*/
/*Removed: margin-top: 45px;
No other changes*/
}
#banner /*Previously: .banner; no other changes */
#content /*Previously: .content; no other changes */
#innerContent /*Previously: .innerContent; no other changes */
Explanation of CSS revisions:
margin-top:45px at the background is unnecessary, since you're absolutely positioning the element.
All of the elements which are unlikely to appear more than once should be selected via the id (#) selector. This selector is more specific than the class selector.
HTML (changes):
All of the class attributes have been replaced by id. No other changes have been made. Don't forget to include the JQuery framework, because I've implemented your wishes using JQuery.
JavaScript (new):
Note: I have added a feature which you didn't request, but seems logical. The code will automatically reserve sufficient margin at the left side of the window in order to always display the background. Remove anything between the marked comments if you don't want this feature.
$(document).ready(function(){
//"Static" variables
var background = $("#background");
var marginTop = parseFloat(background.css("margin-top")) || 0;
var bannerWidth = $("#banner").width(); /*Part of auto left-margin */
var extraContWidth = (bannerWidth - $("#content").width())/2; /*Same as above*/
function fixBG(){
var bodyWidth = $("body").width();
var body_bg_width_ratio = bodyWidth/1920;
var bgHeight = body_bg_width_ratio * 926; //Calcs the visible height of BG
var height = $(document).height();
var docHeight = $(window).height();
var difHeight = bgHeight - docHeight;
var scrollDif = $(document).scrollTop() / (height - docHeight) || 0;
/*Start of automatic left-margin*/
var arrowWidth = body_bg_width_ratio * 115; //Arrow width
if(bodyWidth - bannerWidth > arrowWidth*2){
$("body > div").css("margin-left", "auto");
} else {
$("body > #banner").css("margin-left", arrowWidth+"px");
$("body > #content").css("margin-left", (arrowWidth+extraContWidth)+"px");
}
/*End of automatic left-margin*/
if(difHeight > 0){
background.css({top:(-scrollDif*difHeight-marginTop)+"px", bottom:""});
} else {
background.css({top:"", bottom:"0"});
}
}
$(window).resize(fixBG);
$(window).scroll(fixBG);
fixBG();
});
Explanation of the JavaScript code
The size of the background is determined by calculating the ratio of the background and document width. The width property is used, because it's the most reliable method for the calculation.
Then, the height of the viewport, document body and background is calculated. If applicable, the scrolling offset is also calculated, to prepare the movement of the background, if necessary.
Optionally, the code determines whether it's necessary to adjust the left margin (to keep the background visible at a narrow window).
Finally, if the background arrow has a greater height than the document's body, the background is moved accordingly, taking the scrolling position into account. The arrow starts at the top of the document, and will move up as the user scrolls (so that the bottom side of the arrow will be the bottom of the page when the user has fully scrolled down). If it's unnecessary to move the background, because it already suits well, the background will be positioned at the bottom of the page.
When the page has finished loading, this functionality is added to the Resize and scroll events, so that the background is always at the right location.
If you've got any other questions, feel free to ask them.
well, I'm not sure if I understand you and why do you want to do that, but you can try adding 2 backgrounds (see http://www.css3.info/preview/multiple-backgrounds/ ), one with the top bg and another with the bottom bg but I think that if the page is not too long it will cause issues, so the other answer with pure CSS is as follows: first add 3 horizontal divs with 100% width. Top div will have your top bg and its height, middle div will be transparent and auto height and bottom div will have your bottom bg and its height. All divs will have a 0 z-index. Then create a higher z-index div to act as a container and you'll be set. If I understand your question right, that's the close I can think of to achieve that. This being said, I'm pretty sure you can do this with JQuery with way better results
Using jQuery I was able to give you what I think you're asking for:
$(window).scroll(function() {
var h = Math.max($(document).height(), $(window).height());
var bottom = h - $(".background").height() - $(window).height();
$(".background").css("top", (($(window).scrollTop() / h) * bottom) + "px");
});
EDIT: Forgot to account for the way scrollTop reports position.
Or maybe:
.background {
margin-top: 45px;
max-width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: -9999;
max-height: 100%;
}
I reccomend using jQuery Background Parallax
http://www.stevefenton.co.uk/Content/Jquery-Background-Parallax/
The function is as simple as
$("body").backgroundparallax();
Ask if you don't get it to work.
#abney; as i understand your question may that's you want http://jsfiddle.net/sandeep/RSqrw/60/
you need only css for this:
#background {
position: fixed;
width: 100%;
height:100%;
top: 0;
left:0;
z-index: -1;
}
The solution to your issue is a nice little lightweight plugin by Scott Robin. You can get more info, download it, and make your life easier for all of your projects by visiting his project page here.

How to keep a <div> constant in size as the user zooms in and out on the page?

Is there an html / css / javascipt way to maintain a <div> at a constant size in the face of the user's zooming the page in and out? That is, using control-plus to increase text size and control-minus to reduce it.
EDIT: The kicker, I guess, is that I want the content of the <div> to stay the same size, too.
Thanks!
EDIT: My goal was (and is) to keep an AdSense <div> from expanding so much as to obscure a lot of the real content on the page. But come to find out (thank you #thirtydot) there's really no good way to do this. The answer, for me (thank you #Neal!): give the <div> overflow:scroll so as to sacrifice its content rather than the content I'm trying to show.
.box {
background: red;
width: 5vw;
height: 10vh;
position: absolute;
top: 10vh;
left: 5vw;
}
<div class="box"></div>
There is no good way (read: reliable) to do this. Sorry.
What you're asking for basically boils down to detecting the zoom level of the browser, and there's a great answer here (confirming just how difficult this is):
How to detect page zoom level in all modern browsers?
As stated in that answer, there is a "kinda" cross-browser crazy way involving the use of Flash, but there are downsides:
It uses Flash.
It's not reliable if the user loads your page already zoomed in.
It uses Flash. Yes, this is so bad that I said it twice. Think of all those iPhones/iPads.
Anyway, it's here:
http://blog.sebastian-martens.de/2009/12/how-to-detect-the-browser-zoom-level-change-browser-zoo/
I am not sure what you mean, just use css:
div#id {
width: 100px; /*or some other #*/
height: 100px; /*or some other #*/
}
html:
<div id="id">some content</div>
To make the div size invariant of zooming (But not contents inside it) do the following :
Inside your css for that div :
min-width: 100%;
max-width: 100%;
This will freeze the width, you can do the same for height too.
You should just be ablemto set a width and height in css using a px measurement
Eg
div
{
width:100px; height:200px;
}
I read in another post a solution that I didn't test yet...
Maintain div size (relative to screen) despite browser zoom level
that's the used javascript:
//This floating div function will cause a div to float in the upper right corner of the screen at all times. However, it's not smooth, it will jump to the proper location once the scrolling on the iPhone is done. (On my Mac, it's pretty smooth in Safari.)
function flaotingDiv(){
//How much the screen has been zoomed.
var zoomLevel = ((screen.width)/(window.innerWidth));
//By what factor we must scale the div for it to look the same.
var inverseZoom = ((window.innerWidth)/(screen.width));
//The div whose size we want to remain constant.
var h = document.getElementById("fontSizeDiv");
//This ensures that the div stays at the top of the screen at all times. For some reason, the top value is affected by the zoom level of the Div. So we need to multiple the top value by the zoom level for it to adjust to the zoom.
h.style.top = (((window.pageYOffset) + 5) * zoomLevel).toString() + "px";
//This ensures that the window stays on the right side of the screen at all times. Once again, we multiply by the zoom level so that the div's padding scales up.
h.style.paddingLeft = ((((window.pageXOffset) + 5) * zoomLevel).toString()) + "px";
//Finally, we shrink the div on a scale of inverseZoom.
h.style.zoom = inverseZoom;
}
//We want the div to readjust every time there is a scroll event:
window.onscroll = flaotingDiv;

Categories

Resources