I am trying to fix our parallax effect on our demo site however for the life of me I cannot get it working correctly. The parallax effect works perfectly however the positioning of the image repeats below. The issue occurs when the browser window is not full width.
background: URL(http://www.oddpandadesign.co.uk/albaband/wp-content/uploads/2014/03/parallax_head.png) 50% 0 fixed;
background-size: cover;
jQuery
jQuery(document).ready(function(){
// cache the window object
$window = jQuery(window);
jQuery('section[data-type="background"]').each(function(){
// declare the variable to affect the defined data-type
var $scroll = jQuery(this);
jQuery(window).scroll(function() {
// HTML5 proves useful for helping with creating JS functions!
// also, negative value because we're scrolling upwards
var yPos = -($window.scrollTop() / $scroll.data('speed'));
// background position
var coords = '50% '+ yPos + 'px';
// move the background
$scroll.css({ backgroundPosition: coords });
}); // end window scroll
}); // end section function
}); // close out script
/* Create HTML5 element for IE */
document.createElement("section");
I am not sure if its the image (though we have tried several) or the code is incorrect.This is not the first experience with parallax and it generally is simple so im a bit confused
Thanks for any help
I had to change
background: URL(http://www.oddpandadesign.co.uk/albaband/wp-content/uploads/2014/03/parallax_head.png) 50% 0 fixed;
to
background: URL(http://www.oddpandadesign.co.uk/albaband/wp-content/uploads/2014/03/parallax_head.png) fixed;
background-position: center top!important;
Related
I'm wondering if it's possible to use only CSS to create a parallax scrolling background that meets the following specifications.
It works on an element that sits inside an otherwise static layout (i.e. my whole page layout isn't a group of parallaxing items)
The background isn't entirely fixed in place; it moves, just not as fast as the rest of the page.
I've looked up tons of tutorials for parallaxing backgrounds, and have found some seemingly great tutorials, but they all have one of the following problems.
They rely on the whole page being a parallax group so that you're actually scrolling over a container via an "overflow: auto" specification
The background is totally fixed in place
they use JavaScript.
Sooo, I can accomplish what I want with JavaScript fairly easily. Here's a full working example on JSFiddle that you can try out.
CSS
.parallax-row {
background-image: url(http://lorempixel.com/output/nature-q-c-781-324-3.jpg);
background-size: auto 150%;
}
JavaScript
/**
* Update the parallaxing background img to partially scroll
*/
jQuery(document).ready(function($) {
$(window).on('scroll', function() {
$('.parallax-row').each(function(index, el) {
var $el = $(el);
var fromTop = $el.offset().top + ($el.outerHeight() / 2) - $(window).scrollTop();
var windowHeight = $(window).height();
var percent = (fromTop * 100 / windowHeight);
$el.css('background-position', '0 ' + percent + '%');
});
});
});
Is it possible to accomplish that same effect with just CSS?
I'm trying to emulate the CTRL+F functionality from Chrome that highlights matches on the page in the scrollbar, but for certain fields in a form. Using page offsets and percentages, I have blocks of color which correspond to the relative locations of those fields on the page.
In my prototype, the blocks of color sit to the left of the scrollbar. Ideally, they'd sit UNDERNEATH the scrollbar, and the scrollbar's track would be transparent so that it looks like they're part of the scrollbar track.
Can the default scrollbar be set to allow for overflow content to show underneath it (or allow page content to go over it)? I know this could be accomplished if I just rolled my own scroll, but I'd like to use the default ones provided by the browser if at all possible.
It's clearest if you just look at this Prototype.
CSS:
::-webkit-scrollbar {
width: 14px;
height: 18px;
background-color:transparent;
}
::-webkit-scrollbar-track,
::-webkit-scrollbar-track-piece {
background:none;
}
::-webkit-scrollbar-thumb {
height: 6px;
border: 4px solid rgba(0, 0, 0, 0);
background-clip: padding-box;
-webkit-border-radius: 7px;
background-color: #333
}
::-webkit-scrollbar-button {
width: 0;
height: 0;
display: none;
}
::-webkit-scrollbar-corner {
background-color: transparent;
}
I thought of rendering the matches on the trackbar similarly to what browsers do today before. The idea is simple by using linear-gradient background for the ::-webkit-scrollbar-track. However I did not try implementing this. Right after reading your question, I've tried it and looks like it's not such easy.
You can use the linear-gradient background OK, but if you try rendering more than 1 match (a line), it sometimes can't be rendered (especially when the window's size is changed) and the line is not rendered smoothly. Such as this seems to be OK:
//render 2 lines, one is at 50px and the other is at 100px
background: linear-gradient(transparent 50px, red 50px, red 51px, transparent 51px,
transparent 100px, red 100px, red 101px, transparent 101px);
but it's not stable, as I said when you try resizing the window, at some size, some line won't be rendered (at least I tried on Opera). When the window's height is large, the line even becomes blurred (not sharp) and thicker. I don't really understand this, because the color stops are set fixedly (by px, not by %). This issue is even worse when the number of lines is larger. You have a linear-gradient with many corresponding color stops. That seems to be a neat way to solve the problem. Just because of the undesired issue, we can't use that approach.
The new approach: So I tried using multi-backgrounds feature instead. Each background just renders 1 line, the background-size is the same for all the background is just about 2px height and the background-position should be different. Here is the equivalent code (to the above clean code) using this approach:
background: linear-gradient(red, red), linear-gradient(red, red);
background-repeat: no-repeat;
background-size: 100% 2px;
background-position: 0 50px, 0 100px;
The new approach of course requires that the browser has to support multi-backgrounds features (looks like just IE8- do not support this cool feature).
So that's almost what you need to solve this problem. Now we need to find how to apply that style using script. We can't select a pseudo-element (or something like that) via script. We can just use the window.getComputedStyle() method to get the read-only style of a pseudo-element. However we always have a way to modify the CSS directly. That's is by using pure JS with the help of document.styleSheets and cssRules. They allow us to insert/remove/modify a rule.
That looks great. But there is still another issue. When changing the style using that method, the style is not applied right (at least it happens to the ::-webkit-scrollbar-track, it may not happen to other elements). Only when you move the mouse over the scrollbar, the new style is applied. I've just found a simple way to invalidate that scrollbar by setting the overflow of document.documentElement (the html) to hidden and set it back to auto. That works almost well.
Here is the code:
var requiredTb = $(".required input");
var invalids = requiredTb;
var offsets = [];
//init offsets to highlight on the trackbar later
requiredTb.each(function() {
offsets.push(($(this).offset().top)/document.body.scrollHeight * 100);
});
//find the rule styling the -webkit-scrollbar-track
//we added in the CSS stylesheet, this is done just 1 time
var sheets = document.styleSheets;
var trackRule;
for(var i = 0; i < sheets.length; i++){
var rules = sheets[i].cssRules || sheets[i].rules;
for(var j = 0; j < rules.length; j++){
var rule = rules[j];
if(rule.selectorText == "::-webkit-scrollbar-track:vertical"){
trackRule = rule; break;
}
}
}
//define an invalidate() method, we need to use this method
//to refresh the scrollbars, otherwise the newly applied style is not affected
window.invalidate = function(){
$(document.documentElement).css('overflow','hidden');
setTimeout(function(e){
$(document.documentElement).css('overflow','auto');
},1);
};
//this is the main function to set style for the scrollbar track.
function setTrackHighlights(positions, color){
positions.sort();//ensure that the input array should be ascendingly sorted.
trackRule.style.cssText = "";
var gradient = "background: ", backPos = "background-position: ";
var winHeight = $(window).height();
$.each(positions, function(i,pos){
gradient += "linear-gradient(" + color + ", " + color + "),";
backPos += "0 " + pos + "%,"
});
gradient = gradient.substr(0,gradient.length-1) + ";";
backPos = backPos.substr(0,backPos.length -1) + ";";
trackRule.style.cssText += gradient + backPos + "background-repeat:no-repeat; background-size:100% 2px";
invalidate();
}
//initially set the highlights on the trackbar
setTrackHighlights(offsets,'red');
//handle the oninput event to update the highlights accordingly
requiredTb.on('input', function(e){
var required = $(this).closest('.required');
var refreshHighlights = false;
if(this.value && !required.is('.ok')) {
required.addClass('ok');
refreshHighlights = true;
invalids = invalids.not(this);
}
if(!this.value && required.is('.ok')) {
required.removeClass('ok');
refreshHighlights = true;
invalids = invalids.add(this);
}
if(refreshHighlights){
offsets.splice(0);
invalids.each(function() {
offsets.push(($(this).offset().top)/document.body.scrollHeight * 100);
});
setTrackHighlights(offsets,'red');
}
});
You have to add an empty ::-webkit-scrollbar-track:vertical rule (we need to deal only with the vertical scrollbar) in the CSS code, it should be appended at the last to override any similar rule before. We can in fact use the insertRule() method (of a CSSRuleList which can be accessed via cssRules property) to add a new rule instead of looping through the styleSheets, and through the cssRules (of each sheet) to find the empty rule ::-webkit-scrollbar-track:vertical.
The code I posted here can be improved, such as you can add another method setTrackHighlights to allow to add more lines (instead of rendering all the lines each time we need to add/remove just 1 line)...
Note that by using the term line, I mean the rendering representation of a match on the trackbar.
Demo
I am working on a Parallax/Scrolling Timeline project and I am having a problem with the CSS3 Background-size cover property.
The div has these properties:
background: url(../images/timeline/back-6.jpg) no-repeat top center black;
background-size: cover;
padding-top: 90px;
height: 1855px;
position: relative;
Using jQuery I switch the background-attachment to fixed. When I do this the background image jumps "in" (meaning that parts of the image that were past the edge of the screen are now visible). Which isn't the desired result.
In testing I can switch the div to use background-size: 100% cover but it is causing different vertical jumping issues when scrolling.
Any ideas of how to prevent it from jumping in when I switch the background to fixed? (It also happens in reverse when I set the background to scroll).
I sadly can't link to a demo of this code as the page isn't ready to be deployed yet.
I had the same issue, when setting background-size to cover or contain
Setting a fixed height, in example for smaller screens via #media prevents the background-image from jumping. After my tests I came to the conclusion, that the jumping is due to the orientation of the element after setting background-attachment to fixed
Setting it to fixed, the size is calculated by the size of the viewport, not the element containing the background-image. This is where the jumping comes from and why setting a fixed height or width for the background-size solves this issue.
I had the same problem while creating a one page layout i wanted to use with a scrollTo-Plugin and so on....
The page layout was devided in two parts:
Left side for the background image which should change/scroll with the content on the right side.
So i used to make a kind of jquery Plugin to combine both "background-position: fixed" and "background-size: cover".
you just need to define the element by class/id for aligning the background-images.
dont complain about the code. im relatively new to javascript/jquery. but its working ;)
there it is:
function fixedResize() {
var targetEl = $('element where bg-images are in');
var targetWidth = targetEl.width();
var targetHeight = targetEl.height();
var targetPosX = targetEl.offset().left;
var targetPosY = targetEl.offset().top;
var leftRatio = targetWidth / targetHeight;
//console.log('TargetWidth', targetWidth, 'TargetHeight', targetHeight, 'Offset', targetPosX, targetPosY, 'leftRatio', leftRatio);
targetEl.each(function(){
var imgTarget = $(this);
var url = $(this).css('background-image').replace('url(', '').replace(')', '').replace("'", '').replace('"', '');
var bgImg = $('<img />'); // make background-image as image tag for getting width and height of the image
imgTarget.css('background-attachment','fixed');
bgImg.hide();
bgImg.bind('load', function(){
var imgHeight = $(this).height();
var imgWidth = $(this).width();
var imgRatio = imgWidth / imgHeight;
$(this).remove(); // remove img Tags again
// Calculate resize dimensions
if (imgRatio > leftRatio) {
var currentWidth = imgRatio * targetHeight; // image width after resize
var currentHeight = (currentWidth/imgWidth)*imgHeight;
var setToLeft = ((currentWidth - targetWidth)/2);
var imgPosX = targetPosX - setToLeft;
var imgPosY = (currentHeight - targetPosY - currentHeight/2 - targetHeight/2)* -1;
var resizeImg = 'background-size: auto '+ targetHeight +'px;';
} else if (imgRatio < leftRatio){
var currentWidth = targetWidth;
var currentHeight = (currentWidth/imgWidth)*imgHeight;
var imgPosX = targetPosX;
var imgPosY = (currentHeight - targetPosY - currentHeight/2 - targetHeight/2)* -1;
var resizeImg = 'background-size: '+ targetWidth +'px auto;'; // resize background
}
imgTarget.attr('style','background-attachment: fixed; background-position: '+ imgPosX +'px '+ imgPosY +'px;' + resizeImg);
console.log('imgWidth', imgWidth, 'imgHeight', imgHeight, 'imgRatio', imgRatio, 'currentWidth', currentWidth, 'currentHeight', currentHeight, 'setToLeft', setToLeft);
console.log('imgPos', imgPosX, imgPosY, 'setToLeft', setToLeft, targetPosX);
});
$(this).append(bgImg);
bgImg.attr('src', url);
});
}
fixedResize(); // initiate function
$(window).resize(function() {
fixedResize(); // initiate function for window resize (Fluid behavior)
});
or
jsfiddle.net/rowphant/eXb6e/14/
How can I load images to cover the whole background like some websites, using CSS. Not the usual background-image property but I want to load the images quickly.
Examples:
http://www.marinayachting.it/
http://alexandraowen.co.nz/
background-image is the only way to place images in CSS. If you want it to be vary large put it on the body element or a container div that fills the entire viewport.
body {
margin: 0;
padding: 0;
width: 100%;
background-image: url('my_big_image.jpg') norepeat;
}
If you use a container div you can set position:fixed; top:0; left:0 and the image will remain stationary when the page scrolls.
There's no magic to it. As far as getting it to load quickly I don't think there's much you can do if it doesn't repeat. If it does repeat then make sure your image is the size of one module. This can be as little as one pixel tall or wide depending on the content.
There is no magic to making a background image load quickly, you just:
Have a fast server.
Compress the image as much as possible.
Make your page HTML small so that the rest can start loading as soon as possible.
Don't have many other images that also has to load.
Don't have a lot of scripts and other external files that has to load.
I found this tutorial helpful. ->
http://css-tricks.com/perfect-full-page-background-image/
Bing is loading a normal background image with a fixed size. It´s not particularly fast (for me...), but perhaps it seems fast because the image is cached after the first time you load it.
You can set the style inline so that the image can start downloading without waiting for any css file to be ready.
If you set an image let's say a picture as a background you need to make it large enough to accommodate large screen sizes. You don't want the experience on your site to be, that your picture repeats multiple times on the screen. Probably at the least width should be 1260px. If background is just a simple gradient, you can cut a small part of it in photoshop and apply it on the body like this:
body {
margin:0;
padding:0;
background:#fff url(your/image/location.jpg) repeat-x scroll 0 0;
}
This method could be applied to divs too, Good luck.
In your second example site, alexandraowen.co.nz, if you took a second to look at the JS they use, you would have seen the following:
// backgrounds --------------------------------------------------------------//
var Backgrounds = {};
Backgrounds.init = function()
{
$('body').each
(
function()
{
var imgsrc = $(this).css('background-image');
if(imgsrc != 'none')
{
imgsrc = imgsrc.slice( imgsrc.indexOf('(') + 1 , -1);
$(this).css('background-image', 'none');
$(this).prepend('');
if($.browser.msie)
{
// ie 7 is the slow kid and we have to strip out quote marks ffs!
$(this).find('div.bg img').attr('src', imgsrc.split('"').join(''));
}
else
{
$(this).find('div.bg img').attr('src', imgsrc);
}
}
}
);
Backgrounds.resizeHandler();
$(window).resize(Backgrounds.resizeHandler);
$('div.bg img').load(Backgrounds.resizeHandler);
}
Backgrounds.resizeHandler = function()
{
var w = $(window).width();
var h = $(window).height();
$('div.bg img').each
(
function()
{
var wr = w / $(this).width();
var hr = h / $(this).height();
var r = Math.max(wr, hr);
var imgw = Math.round($(this).width() * r);
var imgh = Math.round($(this).height() * r);
$(this).width( imgw );
$(this).height( imgh );
var l = Math.round((w/2) - (imgw/2));
$(this).css('margin-left', l+'px');
}
);
}
As well as the HTML on the page:
<body style="background-image: none; ">
If you dig into their scripts a bit more, you can see what they did. But I guarantee you it's nothing faster than just setting the background-image property.
<img id="foo" src="bar" alt=""> with #foo { width: 100%; height: 100%; }(use position: absolute; / position: relative; & z-index for layering as desired)
Here's an old example.
Hi I have big background images 1200 by 1200, what i would like to do is expand the images when the user resizes the browser but constrain it so they never scale any smaller than the original size.
There all lots of scalable bg images out there but none I can find that do this, any help would be appreciated.
background-size: cover;
there you go
The following CSS + Javascript + JQuery combination has worked for me.
Thanks to ANeves for the above answer which was helpful.
CSS:
body
{
background: url(background.jpg) center center fixed;
background-size: 100% auto;
}
Javascript (JQuery):
jQuery (function ($)
{ // ready
$(window).resize (function (event)
{
var minwidth = 1200;
var minheight = 1024;
var bodye = $('body');
var bodywidth = bodye.width ();
if (bodywidth < minwidth)
{ // maintain minimum size
bodye
.css ('backgroundSize', minwidth + 'px' + ' ' + minheight + 'px')
;
}
else
{ // expand
bodye
.css ('backgroundSize', '100% auto')
;
}
});
});
another possibility would be to use media queries. set the image size to be say..1280x450 and then use a media query of background-size:100% auto; for all window sizes over 1280px wide.
there is some code which also handles image resizing with IE, however ive admittedly had limited success with it...
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/beach_2.png',sizingMethod='scale');
-ms-filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../images/beach_2.png',sizingMethod='scale')" ;
if anybody has any add ons or fixes for the above then feel free to contribute.
hope this helps someone out there...
For background images, I usually set a minimum width for the html tag which would be the original width of the image or less, this stops the image from shrinking too far.
Put image in div and give size to it.
Apply following property to img tag
background-repeat: no-repeat;
background-size: 100% 100%;
You seem to be looking for CSS3's background-size property. You can constraint the minimum size to the container, if you know that the images are 1200x1200.
I don't believe it'll work on IE though, so it might not be an option for you.
In that case, I suggest you take a peek at http://www.markschenk.com/cssexp/background/scaledbgimage.html