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.
Related
Modern browsers seem to have a feature where the viewport sticks to bottom when page height increases. What actually happens is that browser scrolls the viewport at the same rate as height being increased when initial position is at (or very close to) the bottom of the page. This results in appearance as if page is expanding upwards instead of downwards.
How can this feature be disabled for a certain page using CSS or JS, so that the page would always visually expand downwards?
This of course, also happens when added element's height is expanded animated. For this reason, if possible, I would want to avoid resetting scroll position afterwards to prevent visible jump. The demo of this "feature" (that seems to happen only within rare conditions) interacting with the viewport and drop animation can be observed in the gif below.
I know there must be a way, otherwise every site with infinite scroll would suffer from an infinite loop. Counter argument: Chrome appears not to do this for containers that surpass certain height limit. So maybe infinite-scroll sites don't even bother addressing this in their sites.
Check this fiddle. You can observe that in Chrome, the first container snaps to the bottom, while the other divs has a scroll relative to the top. In Firefox or IE 11, you cannot observe this behavior.
This happens when the top bound of the last element on a scroll container is above the top bound of the container. The browser decides that the last element is what the user is interested in and decides to stay in that position.
The last div doesn't snap to the bottom because the scroll happens relative to the top bound of the last element and the last element is growing.
If you want a different behavior, I would not suggest handling it with Javascript, but I would suggest changing your layout considering these rules. For example the last div should be the growing one, instead of the previous siblings of it.
Obligatory code:
var div = document.querySelectorAll('.growing');
var height = 500;
setInterval(function(){
height += 100;
div[0].style.height = height + 'px';
div[1].style.height = height + 'px';
div[2].style.height = height + 'px';
},1000);
.start, .end{
height: 110px;
}
.start{
background: red;
}
.end{
background: green;
}
.growing{
background: yellow;
}
.cnt1,.cnt2,.cnt3{
overflow: auto;
border: 5px solid black;
margin: 5px 0;
scroll-snap-type: mandatory;
}
.cnt1{
height: 100px;
}
.cnt2{
height: 120px;
}
.cnt3{
height: 100px;
}
<div class="cnt1">
<div class="start"></div>
<div class="growing"></div>
<div class="end"></div>
</div>
<div class="cnt2">
<div class="start"></div>
<div class="growing"></div>
<div class="end"></div>
</div>
<div class="cnt3">
<div class="start"></div>
<div class="end"></div>
<div class="growing">
Content
</div>
</div>
Edit:
If the bounds of the growing div is in the visible area, the scroll is relative to the top of the growing div. So you can hack CSS to show the growing div, but actually not show it.
In this fiddle I have used two different CSS hacks. First one is adding a negative margin bottom and a positive padding bottom at same amount. The second hack is adding an :after element to the growing div but hide its visibility.
for click events, use blur, avoid scrollTo
It seems like this issue is focus-related. I came across a similar bug and when the element that triggered a height change was switched to an unfocusable element, like a div, the screen jumping disappeared. This clearly isn't a great solution because we should be able to use buttons! It also implicates focus in this strange behavior. Further experimentation led to blurring the trigger element before the height change, which solves the problem without moving the viewport. I've only tried this with click events so I'm not sure if it works for drag n drop.
codepen that showcases viewport jumping with accordions and a blur fix
function handleClick(e) {
e.currentTarget.blur();
// code to change height
}
Do you mean that when you scroll to the bottom, and a piece of content gets added, you stay at the bottom? Because the solution for that is real simple:
Option 1
Store the current scrolloffset to the top (eg how many px you've scrolled down)
Add new content
Set scrolloffset to the top to the stored value
Those last two steps can be done so fast that the user wont notice.
Option 2
Not 100% sure this works, but i'm guessing it does:
When the visitor scroll to the bottom, always scroll them back 3px. This way, they're not at the bottom at the point where new content gets added, so the browser stays where it is.
As per my understanding regarding your requirement, I have given a working jsfiddle sample.
Hope it would help to you.
If you expect something more, feel free to add comment.
Cool!
$(function(){
var height = 200;
var pos = 0;
setInterval(function(){
if($(document).height() >= $(window).height()){
var height = $('.container1').height();
$('.container1').height(height + 20);
pos = pos + 20;
$(window).scrollTop(pos);
}
}, 1000);
});
.container1 {
border: 1px solid #ccc;
min-height: 200px;
background: #ccc;
height: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container1">
<p>11</p>
<p>12</p>
<p>13</p>
</div>
All of your draggable elements are in a container with no auto overflow, when you drag and drop your elements the whole page scrolls due to dragging.
Instead of that do as:
<div class="container">
<!-- Place all your draggable elements here -->
</div>
set a max-height and overflow of the container class as:
.container {
max-height: 400px;
overflow: auto;
}
Now when you drag and drop your elements, instead of the whole page, the only container will scroll.
After implementing this solution, it will look like this.
Before dragging.
While dragging.
Hope this helps you.
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;
}
What is the best approach to restricting an absolutely positioned element's position, ideally in pure CSS?
I know that the following isn't possible but I guess what I'm looking for would look something like:
.stickyElement{
bottom-max:auto;
bottom-min:0px;
top-max: auto;
top-min: 100px;
}
That would allow an element to move to a position no less than 100px from the top of it's containing, positioned element.
An example (and my initial) use case for this is a menu that scrolls as part of a page but stops scrolling when it hits the top of a viewport. (Sticky menus?) an example of which can be seen on this page:
http://spektrummedia.com/startups
I fully expect that this is not possible without using some Javascript but I thought I'd put it out there.
position: sticky
There have been discussions in the W3C about this in recent years. One proposal is the addition of a sticky value for the position property.
.content {
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
position: sticky;
top: 10px;
}
This is currently supported in Chrome 23.0.1247.0 and later as an experimental feature. To enable it, enter about:flags for the URL address and press enter. Then search for "experimental WebKit features" and toggle it between enabled and disabled.
On the html5rocks website, there's a working demo.
Strictly speaking, this is an implementation of sticky content, and not a general-purpose way to limit the minimum or maximum position of an element relative to another element. However, sticky content might be the only practical application for the type of the behavior you're describing.
As there is no way to build this for all major browsers without the use of JavasScript I made my own solution with jQuery:
Assign position:relative to your sticky-top-menu. When it reaches the top of the browser window through scrolling the position is changed to positon:fixed.
Also give your sticky-top-menu top:0 to make sure that it sticks to the top of your browser window.
Here you find a working JSFiddle Example.
HTML
<header>I'm the Header</header>
<div class="sticky-top-menu">
<nav>
Page 1
Page 2
</nav>
</div>
<div class="content">
<p>Some content...</p>
</div>
jQuery
$(window).scroll(function () {
var headerTop = $("header").offset().top + $("header").outerHeight();
if ($(window).scrollTop() > headerTop) {
//when the header reaches the top of the window change position to fixed
$(".sticky-top-menu").css("position", "fixed");
} else {
//put position back to relative
$(".sticky-top-menu").css("position", "relative");
}
});
CSS
.sticky-top-menu {
position:relative;
top: 0px;
width: 100%;
}
I know this post is old, and I might be a little late to it, but to anyone still wondering how to do this i would suggest checking out the clamp() method in CSS, you could do something like this:
top: clamp(30px, 10vw, 50px);
Which would set the min top value to 30px, the ideal value to 10vw, and the max value to 50px.
A media query expression that defines the distance between body 0X 0Y and browser-window 0X 0Y would allow elements to be made sticky after page is scrolled
No such expression has otherwise been proposed and is not supported by any browser, to my knowledge, but it would be a useful expression to allow dynamic configuration of sticky elements, such as menu bars that are sticky after page is scrolled past head, without use of JavaScript.
.this element {
position: absolute;
top: 200px;
}
#media (max-scroll: 200px 0) {
.this.element {
position:fixed;
top: 0;
}
}
To my knowledge, there is no way to restrict an element that was positioned using absolute positioning using solely CSS.
The user enters the site.
At this point, the div is in the middle of the page.
As he scrolls down the page, the div first begins to move upward, but once it hits the top, it stays there.
As he scrolls further down the page, the div stays near the top, always visible to the user.
As he scrolls up the page all the way to the top, the div once again stays back in position where it was originally.
You can hook the scroll event on the window object. When processing the event, look at the vertical scroll position of the window/document (see this answer on SO for how to do that). Use absolute positioning for your div and update its top as coordinate as necessary.
FWIW, I would be very careful doing this. Usually when a user scrolls, it's because they want to look at different content than what's on the page. Personally, I hate boxes that follow me around on web pages. :-) But that doesn't mean there isn't a good reason for doing this on occasion.
Very basic example (live copy):
// Make sure this is in a script tag at the end of the body,
// just prior to the closing </body> tag.
function getScrollTop() {
if (typeof window.pageYOffset !== "undefined" ) {
// Most browsers
return window.pageYOffset;
}
var d = document.documentElement;
if (typeof d.clientHeight !== "undefined") {
// IE in standards mode
return d.scrollTop;
}
// IE in quirks mode
return document.body.scrollTop;
}
window.onscroll = function() {
var box = document.getElementById("box");
var scroll = getScrollTop();
if (scroll <= 28) {
box.style.top = "30px";
} else {
box.style.top = (scroll + 2) + "px";
}
};
#box {
/* Position absolutely, 30px down from the top */
position: absolute;
top: 30px;
/* In my case I'm centering it in the window; do what you like */
margin-left: -100px;
left: 50%;
width: 200px;
/* These are just for my example */
height: 1.25em;
border: 1px solid #bbb;
text-align: center;
}
<div id='box'>I'm the box</div>
<div style="height: 1000px"></div>
(In my case, I'm always keeping it 2 pixels below the top, but if you don't want that you can adjust the numbers accordingly.)
As you can see other people provided ready scripts, but if you want to make one your self (waste of time) [or you may want to learn].. here is a good point to start:
var hscroll = (document.all ? document.scrollLeft : window.pageXOffset);
var vscroll = (document.all ? document.scrollTop : window.pageYOffset);
This solution is a lot simpler and might work just as good for some. Position: Fixed or Position: Sticky could do the job.
<div class="col" style="position:fixed; top: 250px; left: 50%">
<p>this box follows me while scrolling down</p>
</div>
http://jsfiddle.net/25rgq/
This is an old implementation of your desired functionality, which I've used. It's one of the first scripts I wrote, so JS & jQuery knowing people will most likely vomit. I wrote it mainly due all the examples I found online were centered on moving the DIV rather than setting it to fixed, and incrementally adding to the top-margin of the box resulted in really choppy movement.
Basicly it changes to fixed as the specified element is a custom set margin from the top of the browser window, and stops moving down once it hits a custom offset before our footer (we wanted to constrain the followbox to not move past our sidebar space).
Hope it is of any use, and if a plugin to handle this nowadays exists, you would probably be better of using it.
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;