I'm building a site with a fluid layout, and therefore need to use percentages in my Jquery sizes and animations. The problem, as I've discovered, is that Jquery doesn't understand percentages. Here's an example of what I'm after:
The page <body> is 100% wide.
<article> is the width of 71% of the page body.
<hgroup> is the width of 33.2% of <article>
I would like <article> to be the same width as <hgroup> on page load (so that only <hgroup> is showing), then expand to 71% of the page width again when <hgroup> is clicked, allowing the rest of the content within <article> to show. At the same time, I'd like <article> to slide left by the width of <hgroup>, hiding <hgroup>.
Is there any way to make this kind of calculation, or will I have to resort to pixels?
Well, you can define
article {
width: 23.6%;
/* that's 33.2% of 71% of 100 */
}
hgroup {
width: 100%;
/* that's in relation to article */
}
plus whatever positioning you need
then
$('article').width($('body').width() / 100 * 71);
$('hgroup').width($('article').width() / 100 * 33.2);
plus whatever effects you need
After much frustration and lamentation, I finally got it sorted out. Here's the code I came up with which, miraculously, works:
$(document).ready(function() {
$('section').hide();
//Capture widths on page load
var bwidth = $('body').width();
var awidth = $('article').width();
var hgwidth = $('hgroup').width();
$('hgroup').width(hgwidth);
$('article').width(hgwidth);
$('hgroup').click(function(){
//Hide open article
var close = $('section:visible').parent();
$(close).children('section').hide().end().width(hgwidth);
$(close).removeClass('active').css('marginLeft', '+=' +hgwidth).detach().appendTo('body');
//Hide last Article
$('body article').last().hide();
//Show current
$(this).parent().addClass('active')
$('.active').animate({
width: awidth,
marginLeft: '-=' + hgwidth
},500);
$(this).next().delay(500).fadeIn(50);
$(this).css('box-shadow','0px 0px 8px #666');
//Show Next Hgroup
$(this).parent().nextAll('article:first').show();
});
});
I think you are looking for slide effect. Take a look at jquery ui slide effect http://docs.jquery.com/UI/Effects/Slide. It might help you without much coding.
Related
What would be the best way to achieve the following:
I would like to get a big centered logo, to shrink and move to the top left of the page as you scroll down and become part of the nav bar.
I would also like a nav bar to fade down from the top.(I only know how to do this timed not dependent on scroll)
When the site loads it will look like just a logo with a simple background. When you scroll down the logo will shift to the top left and the nav bar will ease in and the background picture will also move up out of sight.
Is there any way that you can do the transformation dependent on how far you have scrolled. So that if you stop half way your transformation will also stop?
If I understand you correctly, you want to make a transition to the nav bar / header and the logo dependent on how much you have scrolled, while you are scrolling? If so, it is not as hard is it might sound.
First we have to find out, how many pixels you have scrolled on the page and how many pixels to scroll before the transition is complete. Se code example below.
$(window).on("scroll", function() {
var yPos = $(this).scrollTop(),
yPer = (yPos / 120);
if (yPer > 1) {
yPer = 1;
}
});
Here the y position of the page is found yPos and the transition is set to complete when scrolled down 120 pixels. With these informations we can then calculate the percentage of scrolled pixels until reaching 120 pixels; yPer.
0px = 0%, 60px = 50%, 120px = 100%
In the if-statement we make sure, that the percentage cannot exceed 100%.
HTML and CSS part
Before we go any further with the JavaScript part, let’s setup the HTML and CSS.
HTML structure:
<header></header>
<img class="logo" src="http://oi68.tinypic.com/2z5m4pu.jpg" />
In this case the logo is not inside the header, since we are going to hide the header by default, which would also hide all the child-elements including the logo, which we do not want.
Hiding the header/nav bar:
header {
width: 100%;
height: 60px;
background: #FFF;
position: fixed;
top: -60px;
opacity: 0;
}
Since you want the header to fade in from the top while scrolling, top is set to the negative height of the header itself and the opacity to 0.
Centering the logo:
img.logo {
height: 200px;
position: fixed;
top: 50%;
left: 50%;
transform: translate3d(-50%, -50%, 0);
}
In this way we are going to center the logo in the middle of the screen, no matter the size and resolution of the browser window. If the values in top, left and translate3d all where set to 0, the logo would be in the top left corner. That's why this is a good way to do it in our situration.
JavaScript part - continued
Now we're ready the continue with the JavaScript part.
Store heights in variables:
var header = $("header"),
headerHeight = header.height(),
logo = $(".logo"),
logoHeight = logo.height();
$(window).on("scroll", function() {
// Rest of our code
});
To make it a lot easier for us self later on, we are going to automatically find the height of both the header and the logo, and store those in variables. By doing this we don’t have to change anything in the JavaScript code, if we later on in the future wants to change the height of our elements. We only have to change it, in the CSS.
We are going to set those variables before our scroll-function since, they do not change while scrolling as seen above.
The Calculations:
var logoPos = ( -1*(yPer * 50) + 50),
logoSize = ((headerHeight * yPer) - (logoHeight * yPer) + logoHeight),
headerPos = ((yPer * headerHeight) - headerHeight);
This is a very important part of our code. These expressions are the once that calculates how the elements should animate as we scroll.
logoPos: Calculating the new position of the logo as we scroll. We know that the top, left and translate3d always has
a value of "50". | Starts on 50, ends on 0.
logoSize: Calculating the size of the logo as we scroll. | Starts on the height of the logo, ends on the height of the
header.
headerPos: Calculating the position of the header as we scroll. | Starts on the negative height of header, ends on 0.
NOTE: If we didn’t stored the heights of your elements like before, we had to manually change them in calculations if we later wanted to change them.
Add the new styles:
logo.css({
top: logoPos + "%",
left: logoPos + "%",
transform: "translate3d(-" + logoPos + "%,-" + logoPos + "%,0)",
height: logoSize
});
header.css({
top: headerPos,
opacity: yPer
});
Here we using all our calculations to style our elements as we scroll. On the logo at translate3d we have to remember to put a minus before the logoPos. Else the logo will start moving from the bottom right instead of the center.
For the opacity, we don't have to calculate anything. We just use the yPer.
Well that’s basically it. Hope this could help you out.
You can se the full code in context and with comments in this fiddle:
Working Fiddle
If I understand your question correctly then you should use $(window).scrollTop().
For example in your javascript file,
$(document).ready(
function () {
setInterval(function () {
if ($(window).scrollTop() >= 650) {
// Move your logo to where you want
}
else{
//Move the logo back to the original position
}
}, 1000);
});
This code will check if the current top of your scroll is past 650px and will trigger that code. If it's less than 650px they it will trigger the other code to move your picture back. The setInterval is used so it will constantly check every 1 second but you can change that to suit your needs.
Change the 650 to whatever you think fits best.
It kind of hard to figure out your problem without providing any code but I hope this helps.
see demo url of the framework i'm using: http://alvarotrigo.com/fullPage/examples/navigationH.html#secondPage
However,using almost same kind of code from above,
when I try to achieve below effect in which title text is excluded from slider. (title text to be static, and content is sliding)
jsfiddle url: http://jsfiddle.net/097wvnot/8/
I can't scroll to see all the content; what's the best code to achieve this effect?
if i want to use the top framework, must i do a lot of hack into its core functions?
if not hacking the top animation framework , what are other recommendations to this effect
Use an absolute positioned element for your title. Fullpage.js calculates the height of your content inside the slide elements. (as they are suppose to be full height...).
If you place anything outside any slide, it would have to be absoluted positioned.
Take a look at the solution I propose: http://jsfiddle.net/097wvnot/11/
I added the following style to your title:
#demo{
position:absolute;
top:50px;
margin: 0;
left:0;
right:0;
text-align:center;
}
It looks like the plugin is calculating the height of the fp-scrollable incorrectly. At least for your use case. I was able to get it looking good by just manually adjusting the fp-scrollable's height attribute to a smaller amount (obviously that is not a long term fix, just something I was doing for testing). I'm not sure if the calculating takes into account your font size, and things like that, so that might effect it.
If you want to hack on the plugin, generally the place you need to make your changes is fairly restricted, and wouldn't be too bad. From the github page. https://github.com/alvarotrigo/fullPage.js/blob/master/jquery.fullPage.js
All you need to do is fix the value being placed into the scrollHeight variable. I'm not sure exactly what it's not accounting for in the scroll height calculation (the scrollHeight needs to be smaller in your case, it's too big), but I think that's an exercise you can try your hand at first :) I've got to get to bed z.z
You also may need to mess with the calculation for the contentHeight, since ostensibly you'll be shrinking the scrollHeight, and the script only puts the scroll bar on there if the content is bigger than the scroll.
function createSlimScrolling(element){
//needed to make `scrollHeight` work under Opera 12
element.css('overflow', 'hidden');
//in case element is a slide
var section = element.closest('.fp-section');
var scrollable = element.find('.fp-scrollable');
//if there was scroll, the contentHeight will be the one in the scrollable section
if(scrollable.length){
var contentHeight = scrollable.get(0).scrollHeight;
}else{
var contentHeight = element.get(0).scrollHeight;
if(options.verticalCentered){
contentHeight = element.find('.fp-tableCell').get(0).scrollHeight;
}
}
var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
//needs scroll?
if ( contentHeight > scrollHeight) {
//was there already an scroll ? Updating it
if(scrollable.length){
scrollable.css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
}
//creating the scrolling
else{
if(options.verticalCentered){
element.find('.fp-tableCell').wrapInner('<div class="fp-scrollable" />');
}else{
element.wrapInner('<div class="fp-scrollable" />');
}
element.find('.fp-scrollable').slimScroll({
allowPageScroll: true,
height: scrollHeight + 'px',
size: '10px',
alwaysVisible: true
});
}
}
//removing the scrolling when it is not necessary anymore
else{
removeSlimScroll(element);
}
//undo
element.css('overflow', '');
}
I have a #banner that holds content, basically what i want to do is show a certain amount of the content and then have a more button that will show the rest of the content if clicked. This in turn will also animate the height of #banner, I have set the #banner height at 300px but want to find the height of the content #inner and animate this accordingly. At the moment I have the following version but reckon Im using a lot of #ids / to achieve the effect, can anyone advise how I can make this better?
Fiddle here: http://jsfiddle.net/43gTt/1/
Thanks
Kyle
I suggest you compute the height of the inner div and use that to animate.
var $tmpInner = inner.clone().appendTo('body');
var divHeight = $tmpInner.outerHeight();
$tmpInner.remove();
Below will compute the height of the innerDiv based on the content of the div.
Also, updated the css style for the banner to overflow:hidden so that you don't need separate animate for the banner.
DEMO
CSS:
#banner{background:#dedede;overflow: hidden; }
#outer{margin:0 auto;width:200px;}
#middle{height:200px;overflow:hidden}
#inner{width:200px;margin:0 auto;}
.entry{display:none;}
JS:
$(document).ready(function() {
var outer = $('#outer'),
middle = $('#middle'),
inner = $('#inner'),
/*innerH = inner.height(),*/
banner = $('#banner'),
more = $('#more');
var $tmpInner = inner.clone().appendTo('body');
var divHeight = $tmpInner.outerHeight();
$tmpInner.remove();
// animate banner and #middle to reveal additional content
more.on('click', function(e) {
middle.animate({
height: divHeight
}, 300);
/*banner.animate({
height: innerH
}, 300);*/
});
});
Note: I am not sure why you need that many wrappers div, but I presume that would be part of your HTML. Also I will leave the code cleanup to you.
I'm trying to create a website with main content area and a sidebar, something like here on Stack Overflow. The goal is that when you scroll down, the sidebar stays visible.
I have seen two approaches to this:
position:fixed;
JavaScript manipulation with the DOM
Approach no. 1, as far as I know, will have a problem when the viewport is smaller than the sidebar contents so I guess that can't be used reliably and JavaScript scripts that I have seen are usually animated or generally "slow" (you can see that there is redrawing going on after each scroll).
Can someone point out a JavScript library / CSS approach that would not suffer from the aforementioned issues?
Edit: an example would be this page but with the sidebar sticking to the top without an animation and correctly handling the situation when the sidebar is higher than content / viewport.
I don't like heavy JS solutions, so important thing to ask is - preferred compatibility. In IE8+ it is possible instead of
var $window = $(window),
$sidebar = $(sidebar);
$window.on('resize', function(){
$sidebar.height($window.innerHeight());
});
$window.resize();
do something like this (pure CSS solution):
#sidebar {
position: fixed;
left: 0; /* or right */
top: 0;
bottom: 0;
overflow: auto;
}
When you have top&bottom / left&right value at the same time, box will be stretched. (JSFiddle demo)
Got it. It is Javascript based, but I'm sure that's nothing heavy and even IE8 should solve it pretty fine.
var top = $('#sidebar').offset().top;
var height = $('#sidebar').height();
var winHeight = $(window).height();
var gap = 10;
$(window).scroll(function(event) {
var scrollTop = $(this).scrollTop();
// sidebar reached the (end - viewport height)
if (scrollTop + winHeight >= top + height + gap) {
// if so, fix the sidebar and make sure that offset().top will not give us results which would cancel the fixation
$('#sidebar').addClass('fixed').css('top', winHeight - height - gap + 'px');
} else {
// otherwise remove it
$('#sidebar').removeClass('fixed').css('top', '0px');
}
});
demo
You could catch client window's height and giving it to your sidebar like this :
var sidebarHeight = $(window).innerHeight();
$('#sidebar').css('height',sidebarHeight);
With the proper CSS for the sidebar :
#sidebar {
position: fixed;
right: 0;
top: 0;
width: 200px;
overflow: hidden;
}
Here is a working JSFiddle.
You could also watch for window resizing to avoid a mess on resize :) Here is the way to go with jQuery
Good luck
Not sure if you have this figured out but I have created a contained sticky sidebar jQuery plugin. It's really simple and allows you to invoke with just one line of jQuery. Take a look here: http://mojotech.github.com/stickymojo/
It starts by position: fixed; then uses javascript to handle any resizes, scrolls and even allows you to specify a footer element that it should not intersect. By combining these approaches you will get a smooth looking fixed element. Plus, we made it easy for you.
Code and demo here: http://closure-library.googlecode.com/svn/docs/class_goog_ui_ScrollFloater.html
I would like to create an interface with 3 columns, each having mixed content (text, image, and video), and would like to have them scroll vertically with different speeds at the same time. Is there a relatively simple way of accomplishing this with html, css, and/or javascript?
PS. I know about the parallax scrolling, but the implementations I came across seem to be mostly about using images as background to create a dimensional illusion.
Something like: http://jsfiddle.net/KVWuS/.
$.fn.makeScroll = function(speed) {
var elem = this,
i = 0;
setInterval(function() {
elem.scrollTop(i++); // increment scroll top
}, speed); // run every 'speed' ms (so lower is faster)
};
You can enable it like:
$('div:eq(0)').makeScroll(75); // moderate speed
You want to actually scroll the content?
$('.column').animate({
scrollTop: $('.column').height() - $(window).height()
}, 1000);
This will scroll your column down in 1 second. Adjust the speed per column.
EDIT:
I was assuming your columns were the height of the window. If not, you'll have to adjust the scrollTop.
I think a simple workaround would be to create 3 div Elements with the following Attributes:
overflow: hidden;
width: x px (fixed width)
height: x px (fixed height)
top: 0px;
left: x px;
Then you have to capture the onscroll event and set the top-Attribute.
E.g.
div1: top: -100px
div2: top: -300px
div3: top: -500px
I hope my description is clear.. :)
That should work