Entry
How to have a floating link (that is repositioned when scrolling)?
Jan 30th, 2001 06:21
Martin Honnen,
Use css absolute positioning to get a positionable page element, then
use setInterval for NN4+ and Opera 5 and onscroll for IE
to reposition the element to float at a fixed position in the viewport.
The following positions a link in the top right corner of the window:
<HTML>
<HEAD>
<TITLE>
fix element in viewport
</TITLE>
<STYLE>
#fixed {
position: absolute;
visibility: hidden;
z-index: 10;
}
</STYLE>
<SCRIPT>
var delay = 25;
var Opera = window.opera ? true : false;
var fixedElement, elWidth, elHeight, tid;
function initFixing (id) {
if (document.layers) {
fixedElement = document[id];
elWidth = fixedElement.document.width;
elHeight = fixedElement.document.height;
}
else if (document.getElementById && !Opera) {
fixedElement = document.getElementById(id);
elWidth = fixedElement.offsetWidth;
elHeight = fixedElement.offsetHeight;
}
else if (document.all && !Opera) {
fixedElement = document.all[id];
elWidth = fixedElement.offsetWidth;
elHeight = fixedElement.offsetHeight;
}
else if (Opera) {
fixedElement = document.getElementById(id);
elWidth = fixedElement.style.pixelWidth;
elHeight = fixedElement.style.pixelHeight;
}
fixPosition();
if (document.layers)
fixedElement.visibility = 'show';
else
fixedElement.style.visibility = 'visible';
if (document.all && !Opera)
window.onscroll = fixPosition;
else
tid = setInterval('fixPosition()', delay);
}
function fixPosition () {
if (document.layers) {
fixedElement.left =
window.pageXOffset + window.innerWidth - elWidth - 15;
fixedElement.top =
window.pageYOffset;
}
else if (document.all && !Opera) {
fixedElement.style.pixelLeft =
document.body.scrollLeft + document.body.clientWidth - elWidth;
fixedElement.style.pixelTop =
document.body.scrollTop;
}
else if (document.getElementById && !Opera) {
if (elWidth == 0) // workaround for bug of NN6 to compute width
elWidth = fixedElement.offsetWidth;
fixedElement.style.left =
(window.pageXOffset + window.innerWidth - elWidth - 30) + 'px';
fixedElement.style.top =
(window.pageYOffset) + 'px';
}
else if (Opera) {
fixedElement.style.pixelLeft =
window.pageXOffset + window.innerWidth - elWidth;
fixedElement.style.pixelTop =
window.pageYOffset;
}
}
</SCRIPT>
</HEAD>
<BODY>
<SPAN ID="fixed">
<A HREF="javascript: void 0"
ONCLICK="window.scrollTo(0, 0); return false"
ONMOUSEOVER="window.status = 'top'; return true;"
ONMOUSEOUT="window.status = ''; return true;"
>
top
</A>
</SPAN>
<SCRIPT>
initFixing('fixed');
</SCRIPT>
What follows here is just example page content to fill the page so that
scrollbars appear.
<SCRIPT>
for (var i = 0; i < 100; i++)
document.write(i + ' Kibology<BR>');
</SCRIPT>
<IMG SRC="kiboInside.gif" WIDTH="1000">
</BODY>
</HTML>
Here is more generalized code that allows to specify the corner to
which you want to fix the element or link to. It works with NN4, Opera
5 and IE4+ for all four corners of the window, and due to bugs in
NN6/Mozilla only for the top left and the bottom left corner while
positioning to the right corners is not working as intended.
<HTML>
<HEAD>
<TITLE>
fixed positioning
</TITLE>
<STYLE>
.fixedLink {
background-color: blue;
color: white;
}
</STYLE>
<STYLE>
.toBeFixed {
position: absolute;
visibility: hidden;
z-index: 10;
}
</STYLE>
<SCRIPT>
FixElement.interval = 25;
var Opera = window.opera ? true : false;
function FixElement (id, vertical, horizontal) {
this.elementId = id;
this.vertical = vertical ? vertical : 'top';
this.horizontal = horizontal ? horizontal : 'left';
this.id = FixElement.elements.length;
FixElement.elements[this.id] = this;
this.init();
}
function FixElement_init () {
if (document.layers) {
this.element = document[this.elementId];
this.width = this.element.document.width;
this.height = this.element.document.height;
}
else if (Opera) {
this.element = document.getElementById(this.elementId);
this.width = this.element.style.pixelWidth;
this.height = this.element.style.pixelHeight;
}
else if (document.all) {
this.element = document.all[this.elementId];
this.width = this.element.offsetWidth;
this.height = this.element.offsetHeight;
}
else if (document.getElementById) {
this.element = document.getElementById(this.elementId);
this.width = this.element.offsetWidth;
this.height = this.element.offsetHeight;
}
this.fixPosition();
this.makeVisible();
/* want here
if (!Opera && document.all)
window.onscroll = fixElements;
else if (this.id == 0)
FixElement.tid = setInterval('fixElements()',
FixElement.interval);
but due to a initial positioning problem with IE we don't use
onscroll
*/
if (this.id == 0)
FixElement.tid = setInterval('fixElements()', FixElement.interval)
}
FixElement.prototype.init = FixElement_init;
function FixElement_fixPosition () {
if (document.layers) {
if (this.horizontal == 'left')
this.element.left = window.pageXOffset;
else
this.element.left =
window.pageXOffset + window.innerWidth - this.width - 15;
if (this.vertical == 'top')
this.element.top = window.pageYOffset;
else
this.element.top =
window.pageYOffset + window.innerHeight - this.height - 15
}
else if (Opera) {
if (this.horizontal == 'left')
this.element.style.pixelLeft = window.pageXOffset;
else
this.element.style.pixelLeft =
window.pageXOffset + window.innerWidth - this.width;
if (this.vertical == 'top')
this.element.style.pixelTop = window.pageYOffset;
else
this.element.style.pixelTop =
window.pageYOffset + window.innerHeight - this.height;
}
else if (document.all) {
if (this.horizontal == 'left')
this.element.style.pixelLeft = document.body.scrollLeft;
else
this.element.style.pixelLeft =
document.body.scrollLeft + document.body.clientWidth -
this.width;
if (this.vertical == 'top')
this.element.style.pixelTop = document.body.scrollTop;
else
this.element.style.pixelTop =
document.body.scrollTop + document.body.clientHeight -
this.height;
}
else if (document.getElementById) {
if (this.horizontal == 'left')
this.element.style.left = window.pageXOffset + 'px';
else
this.element.style.left =
(window.pageYOffset + window.innerWidth - this.width - 60)
+ 'px';
if (this.vertical == 'top')
this.element.style.top = window.pageYOffset + 'px';
else
this.element.style.top =
(window.pageYOffset + window.innerHeight - this.height - 40)
+ 'px';
}
}
FixElement.prototype.fixPosition = FixElement_fixPosition;
function FixElement_makeVisible () {
if (document.layers)
this.element.visibility = 'show';
else
this.element.style.visibility = 'visible';
}
FixElement.prototype.makeVisible = FixElement_makeVisible;
function fixElements () {
for (var e = 0; e < FixElement.elements.length; e++)
FixElement.elements[e].fixPosition();
}
FixElement.elements = new Array();
</SCRIPT>
</HEAD>
<BODY>
<SPAN ID="topLink" CLASS="toBeFixed">
<A HREF="javascript: void 0"
CLASS="fixedLink"
ONMOUSEOVER="window.status = 'scroll to top';
return true;"
ONMOUSEOUT="window.status = '';
return true;"
ONCLICK="window.scrollTo(0, 0);
return false;"
>
top
</A>
</SPAN>
<SCRIPT>
new FixElement('topLink', 'top', 'right');
</SCRIPT>
<SPAN ID="bottomLink" CLASS="toBeFixed">
<A HREF="javascript: void 0"
CLASS="fixedLink"
ONMOUSEOVER="window.status = 'scroll to bottom';
return true;"
ONMOUSEOUT="window.status = '';
return true;"
ONCLICK="if (document.layers)
var bottom = window.document.height;
else if (Opera)
var bottom = 1000;
else if (document.all)
var bottom = document.body.scrollHeight;
else if (document.getElementById)
var bottom = window.document.height;
window.scrollTo(0, bottom);
return false;"
>
bottom
</A>
</SPAN>
<SCRIPT>
new FixElement('bottomLink', 'bottom', 'right');
</SCRIPT>
Here follows content to fill the page so that scrollbars appear.
<BR>
<SCRIPT>
for (var i = 0; i < 50; i++)
document.write(i + ' Kibology<BR>');
if (document.all && !Opera)
var width = document.body.offsetWidth;
else
var width = window.innerWidth;
document.write('<IMG SRC="kiboInside.gif" WIDTH="' + (width + 100)
+ '">');
</SCRIPT>
</BODY>
</HTML>