JavaScript Scrolling Box Marquee Replacement
Published by philipnorton42 on Tue, 01/29/2008 - 14:34Having a Marquee on a web page is a nightmare from an XHTML validation point of view, so here is a neat function that will produce the same effect as a vertical scrolling marquee, that passes XHTML validation, and built entirely from JavaScript and CSS.
Vertical Scrolling
Take the following HTML code. Don't worry about reading it. It is just 7 p tags (2 of which act as spacers) contained within a div tag.
1 2 3 4 5 6 7 8 9 | <div id="marquee_replacement" onmouseout="startit();" onmouseover="stop();"> <p class="spacer"></p> <p>Lorem ipsum dolor sit amet consectetur enim proident in elit est. Culpa sit ad aliquip laboris sit ad tempor in dolore proident. Ut ut deserunt laboris ut exercitation sit consectetur nisi sunt incididunt. Nisi non et qui adipisicing labore tempor consequat anim id dolore. Veniam velit aliquip laborum. cillum dolor amet sed dolore laborum. in. Magna deserunt veniam anim ut deserunt est ut ut.</p> <p>Aute enim quis duis exercitation magna cupidatat ullamco duis voluptate ullamco. Ad eu est in commodo occaecat mollit officia sit elit excepteur. Elit sint duis excepteur reprehenderit consequat cupidatat quis esse occaecat elit. Officia tempor laborum. dolore dolore nulla ea adipisicing pariatur irure deserunt. Enim ullamco mollit ut eu lorem elit ex sit cillum pariatur. Laboris laboris tempor ex ad officia eu.</p> <p>Elit est laboris nisi nostrud incididunt exercitation qui in excepteur eiusmod. Exercitation eu occaecat mollit amet esse enim consectetur non veniam occaecat. Ea occaecat commodo dolore sunt ullamco veniam incididunt aliqua labore minim. Velit et amet nulla consectetur enim eiusmod enim ut in cupidatat. Velit do excepteur dolor sed nostrud cillum ad ea veniam sint. Culpa ex sed esse exercitation sed do in lorem ea proident. Ullamco labore.</p> <p>Eiusmod id quis exercitation officia sit aliquip enim in in aliquip. Lorem adipisicing officia elit pariatur proident ut irure aute id dolor. Tempor cillum non dolore lorem enim in velit et pariatur consequat. Excepteur ad ex fugiat est esse dolore consectetur ut ut dolor. Mollit consequat culpa laborum. aliquip sunt nostrud dolore consequat cillum labore. Dolor officia lorem do sunt nostrud aliqua velit voluptate.</p> <p>Eiusmod id quis exercitation officia sit aliquip enim in in aliquip. Lorem adipisicing officia elit pariatur proident ut irure aute id dolor. Tempor cillum non dolore lorem enim in velit et pariatur consequat. Excepteur ad ex fugiat est esse dolore consectetur ut ut dolor. Mollit consequat culpa laborum. aliquip sunt nostrud dolore consequat cillum labore. Dolor officia lorem do sunt nostrud aliqua velit voluptate.</p> <p class="spacer"></p> </div> |
The following style sheet will make the div look like a little box and will allow the JavaScript to turn it into a marquee. The spacer p tags are also set here so that they are the same size as the div.
1 2 3 4 5 6 7 8 9 10 11 | <style type="text/css">
#marquee_replacement{
border:1px solid #000;
width:200px;
height:150px;
overflow:auto;
}
#marquee_replacement p.spacer{
height:150px;
}
</style> |
Here is the JavaScript.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <script type="text/javascript">
// <!--
var speed = 5; // change scroll speed with this value
/**
* Initialize the marquee, and start the marquee by calling the marquee function.
*/
function init(){
var el = document.getElementById("marquee_replacement");
el.style.overflow = 'hidden';
scrollFromBottom();
}
var go = 0;
var timeout = '';
/**
* This is where the scroll action happens.
* Recursive method until stopped.
*/
function scrollFromBottom(){
clearTimeout(timeout);
var el = document.getElementById("marquee_replacement");
if(el.scrollTop >= el.scrollHeight-150){
el.scrollTop = 0;
};
el.scrollTop = el.scrollTop + speed;
if(go == 0){
timeout = setTimeout("scrollFromBottom()",50);
};
}
/**
* Set the stop variable to be true (will stop the marquee at the next pass).
*/
function stop(){
go = 1;
}
/**
* Set the stop variable to be false and call the marquee function.
*/
function startit(){
go = 0;
scrollFromBottom();
}
// -->
</script> |
You will also need to set an onload event on the body tag so that the init() function is run when the page loads. The init() function sets the overflow of the div to be hidden so that no scroll bar appears on it. This has to be done after the page has loaded as it doesn't seem to do anything when set in the main style sheet. The init() function then calls the scrollFromBottom() function which just moves the text a littler higher up the page and then calls itself to repeat the process. Once the bottom of the text goes past the top of the div the height is reset and the process repeats.
You need a <p class="spacer"></p> at the start end end of the marquee. This creates a buffer zone which makes the marquee look more natural, but not only that the height of the elements is worked out with the spacer classes in mind. You also need to make sure that you give the spacer tags a specific height. For instance, in the code above I have set the height of the spacer tags to be 150px. You must then make sure that the scrollHeight of the marquee is subtracted by the height of a spacer tag. Take a look at line 12 of the JavaScript.
The div tag is also the given two events of on mouse out and on mouse over. These functions are in place to stop the text from scrolling when a user moves their mouse over it. This can be left out or kept in depending on what you want the marquee to do, but is replicates the original functionality of the HTML marquee.
Have a look at the example of vertical scrolling JavaScript marquee.
Horizontal Scrolling
Horizontal scrolling is slightly different. It uses the scrollLeft property of the main containing div but there is some initial set up needed to figure out how much scrolling is needed. In order to get the text inside the div to scroll you need to use a inner div, which contains a set of p tags, two of which are spacer tags. The inner div is used to keep the p tags in a single line. Here is the HTML code used to the horizontal scrolling marquee.
1 2 3 4 5 6 7 | <div id="marquee_replacement" onmouseout="startit();" onmouseover="stop();"> <div id="start"><p class="spacer"></p> <p>Lorem ipsum dolor sit amet consectetur enim proident in elit est. Culpa sit ad aliquip laboris sit ad tempor in dolore proident. Ut ut deserunt laboris ut exercitation sit consectetur nisi sunt incididunt. Nisi non et qui adipisicing labore tempor consequat anim id dolore. Veniam velit aliquip laborum. cillum dolor amet sed dolore laborum. in. Magna deserunt veniam anim ut deserunt est ut ut.</p> <p>Aute enim quis duis exercitation magna cupidatat ullamco duis voluptate ullamco. Ad eu est in commodo occaecat mollit officia sit elit excepteur. Elit sint duis excepteur reprehenderit consequat cupidatat quis esse occaecat elit. Officia tempor laborum. dolore dolore nulla ea adipisicing pariatur irure deserunt. Enim ullamco mollit ut eu lorem elit ex sit cillum pariatur. Laboris laboris tempor ex ad officia eu.</p> <p class="spacer"></p> </div> </div> |
Next you will need to set some styles up in order to make the p tags appear in a line.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <style type="text/css">
#marquee_replacement{
border:1px solid #000;
width:1000px;
height:20px;
overflow:auto;
}
#marquee_replacement div#start p{
padding:0;
margin:0;
left:0;
width:auto;
display:inline;
float:left;
white-space: nowrap;
height:15px;
}
#marquee_replacement div#start p.spacer{
width:1100px;
}
#marquee_replacement div#start{
display:block;
height:10px;
}
</style> |
Finally here is the JavaScript needed. It works in the same way as the vertical scroller except that the required width of the inner div tag is worked out before the scrolling is started. The script takes all of the p tags in the inner div and totals how wide each of them is. The looping function then only has to go as far as that, minus the width of the marquee_replacement div.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | <script type="text/javascript">
// <!--
var pWidth = 0;
var speed = 5; // change scroll speed with this value
/**
* Get a collection of all of the objects of a particular type, can pass in an object that they should be collected from.
*/
function getElementsByTagNames(list,obj) {
if (!obj) var obj = document;
var tagNames = list.split(',');
var resultArray = new Array();
for (var i=0;i<tagNames.length;i++) {
var tags = obj.getElementsByTagName(tagNames[i]);
for (var j=0;j<tags.length;j++) {
resultArray.push(tags[j]);
};
};
var testNode = resultArray[0];
if(!testNode){
return [];
};
if(testNode.sourceIndex){
resultArray.sort(function(a,b){
return a.sourceIndex - b.sourceIndex;
});
}else if(testNode.compareDocumentPosition){
resultArray.sort(function(a,b){
return 3 - (a.compareDocumentPosition(b) & 6);
});
};
return resultArray;
}
/**
* Initialize the marquee, and start the marquee by calling the marquee function.
*/
function init(){
var div = document.getElementById("marquee_replacement");
div.style.overflow = 'hidden';
var ps = getElementsByTagNames('p',div);
for(var j=0;j<ps.length;j++){
pWidth += ps[j].offsetWidth;
}
var startdiv = document.getElementById("start");
startdiv.style.width = pWidth+'px';
div.scrollLeft = 0;
setTimeout("scrollFromBottom()",50);
}
var go = 0;
var timeout = '';
/**
* This is where the scroll action happens.
* Recursive method until stopped.
*/
function scrollFromSide(){
clearTimeout(timeout);
var el = document.getElementById("marquee_replacement");
if(el.scrollLeft >= pWidth-1000){
el.scrollLeft = 0;
};
el.scrollLeft = el.scrollLeft+speed;
if(go == 0){
timeout = setTimeout("scrollFromSide()",50);
};
}
/**
* Set the stop variable to be true (will stop the marquee at the next pass).
*/
function stop(){
go = 1;
timeout = '';
}
/**
* Set the stop variable to be false and call the marquee function.
*/
function startit(){
go = 0;
scrollFromSide();
}
// -->
</script> |
Have a look at the example of horizontal scrolling JavaScript marquee.
Debugging
If you are stuck as to why the marquee isn't working then you can do the following.
Add this line of HTML anywhere in your page, preferably near to where you have put the marquee.
<p id="test"></p>
Add the following line of JavaScript to your marquee script. You will want to put it just after the function declaration for scrollFromBottom() for vertical Scrolling and scrollFromSide() for horizontal scrolling.
document.getElementById('test').innerHTML = el.scrollTop+ ' ' +el.scrollHeight;
This should print out two numbers. The second will be the height of the marquee element and will remain constant. The first number will increase (or decrease if you have created a backwards scrolling marquee) as the scrolling takes place. The first number will be reset when it gets to the end of the marquee. If it doesn't, or it gets to a certain value and stops then you need to look at the following line of code (from scrollFromBottom() in this case).
1 2 3 | if(el.scrollTop >= el.scrollHeight-150){
el.scrollTop = 0;
}; |
The value of 150 here needs to be the same as the height you set for the <p class="spacer"></p> tag in your CSS. If it is less than the value then it will never repeat itself. If it is greater than the value then it will repeat before it gets to the bottom.
Update
30/01/2007 - Added both vertical and horizontal scrolling.
22/05/2008 - Small bug noticed in the getElementsByTagNames() function due to a encoding typo. Also needed to start the marquee off in the init() function.
28/08/2008 - Added some helpful descriptions and comments.
11/02/2009 - Fixed the crazy moving faster bug. It seems that by adding a call to clearTimeout() at the start of the scrolling function it stops JavaScript trying to set lots of setTimeout() calls and therefore call this function more and more times. I have updated the code and the examples to reflect this change.
Comments
Hi, How would you make this
Lisa (not verified) - Wed, 01/30/2008 - 05:32Lisa, Thanks for the comment.
philipnorton42 - Wed, 01/30/2008 - 17:58That is a good replacement
Kursad Olmez (not verified) - Wed, 05/21/2008 - 16:21This script can have only one
Pram (not verified) - Tue, 08/12/2008 - 12:35Nice elegant and compact
Roland (not verified) - Tue, 04/15/2008 - 05:34I have seen this behaviour
philipnorton42 - Tue, 04/15/2008 - 08:55@Genie - Glad to help. Send
philipnorton42 - Tue, 08/12/2008 - 15:20Good replacement for the
Pram (not verified) - Wed, 08/06/2008 - 11:43If you have the right onload
philipnorton42 - Wed, 05/21/2008 - 17:04how to change the speed of
ruby (not verified) - Mon, 05/19/2008 - 12:34Each script has a variable,
philipnorton42 - Mon, 05/19/2008 - 15:58var speed = 5;This is the amount of scrolling that each script does, so the higher the speed variable, the more the box scrolls by on each iteration and the faster the scrolling appears to be.Great script. Is there a way
Genie (not verified) - Sun, 08/10/2008 - 16:03It is quite easy. All you
philipnorton42 - Wed, 08/06/2008 - 17:12Realy a usefull codes for me
Yash (not verified) - Sat, 07/05/2008 - 22:00Are you sure it stops when it
philipnorton42 - Mon, 08/11/2008 - 08:50timeout = setTimeout("scrollFromSide()",50);This is currently set to 50, which means that 50 milliseconds pass before the function is called. you can get different levels of speed and smoothness using this value and the speed variable. Setting them both to 1 seems to create a smooth scrolling speedy marquee, but the speed varaible doesn't seem to work fully with numbers lower than 1. Hope that helps!That does make it smoother,
Genie (not verified) - Tue, 08/12/2008 - 11:40Nice, it's working for me. I
entiretheweb (not verified) - Wed, 04/08/2009 - 10:48Hello, I have a question on
Anson Kwok (not verified) - Tue, 04/14/2009 - 10:44@Jackie - You have either
philipnorton42 - Sun, 09/21/2008 - 01:09I was wondering if anyone
Erika (not verified) - Sun, 09/14/2008 - 00:39@Erika - I haven't been able
philipnorton42 - Mon, 09/15/2008 - 08:51I just want to say thank you
Genie (not verified) - Thu, 08/28/2008 - 02:01@Genie - You are very
philipnorton42 - Thu, 08/28/2008 - 09:42I used your code and when it
Jackie (not verified) - Sat, 09/20/2008 - 04:55I may have just had a
Juanita (not verified) - Fri, 01/02/2009 - 07:29I've modified the script to
Juanita (not verified) - Fri, 01/02/2009 - 06:40You just have to put a call
philipnorton42 - Tue, 12/23/2008 - 19:12I need a marquee to stop
me (not verified) - Tue, 12/23/2008 - 17:56Juanita, I would be
Bob Ellington (not verified) - Sun, 01/18/2009 - 16:12indeed a good script. just
SVK (not verified) - Wed, 12/17/2008 - 07:55Incorporating data from a
philipnorton42 - Wed, 12/17/2008 - 16:20You'll need to call the
philipnorton42 - Tue, 04/14/2009 - 10:49It sounds like you haven't
philipnorton42 - Fri, 03/13/2009 - 11:01Hello Great script :) I have
Who? (not verified) - Thu, 03/12/2009 - 17:20Thanks for your reply! I know
Anson Kwok (not verified) - Wed, 04/15/2009 - 03:36Oh yes, good point! You will
philipnorton42 - Wed, 04/15/2009 - 08:40some text marqeeing up and
manoj (not verified) - Sun, 05/10/2009 - 13:38Hey wonderful script, the
Hadith (not verified) - Fri, 02/12/2010 - 18:28Wonderful...
Matt (not verified) - Mon, 06/21/2010 - 08:38You just need to stick a call
philipnorton42 - Mon, 06/21/2010 - 09:59Please send me "cript to handle multiple marquees"
Sanjib (not verified) - Sun, 08/29/2010 - 15:47An Effective Way
Philips Tel (not verified) - Wed, 09/21/2011 - 09:15Why I should use your script, I think there is a simple way makin a marquee text, something like this:
<marquee direction='left' behaviour='scroll' scroolamount='1' delay='1'>This is a marquee text</marquee>Could explain to me I use don't use that script?
You don't have to use it if
philipnorton42 - Wed, 09/21/2011 - 09:47You don't have to use it if you don't want to. I wrote this code years ago and it was just a way of getting to grips with JavaScript at the time.
Add new comment