Reinspire

Safari CSS/JavaScript Overflow Issues

If you’ve seen my portfolio lately you’ll know that it’s currently undergoing some changes, but the latest project to have its URL land there is one that caused me a bit of grief in Safari. What I’ve been able to gather based on more than a few Google searches and discussions with other web professionals is that Safari seems to have a big problem when trying to adjust the overflow property of an element with JavaScript.

Before I go any further though, let me set up the scenario and describe what I had been trying to accomplish. The site’s design concept called for a fixed width and height with a custom-designed scrolling interface. Being the standards-aware developer that I am, I immediately looked at the requirements from a low level perspective. Custom scrolling always requires the use of JavaScript (unless you count IE’s ability to change the colours of its scrollbars… which I don’t), but what should you do when users don’t have JavaScript enabled? Mostly all of the pages on the site would have too much content to fit into the allotted space, so I knew I’d need to use a div and have CSS set its dimensions and overflow property:

#copy {
    width: 300px;
    height: 295px;
    overflow: auto;
}

Rather than setting the overflow value to ‘scroll’ (which will always show scrollbars in most browsers—both vertical and horizontal—even if they’re not needed) I decided to use the value of ‘auto’ which basically tells the browser to only show scrollbars when it absolutely needs to. Once I knew how I was going to tackle the site’s scrollable content, I went on to develop the entire site without the custom scroller.

Once the site was finished (sans-scroller) I went on to do a good round of browser testing to make sure everything was good to go before I started on the custom scrolling interface.

With my first round of browser testing complete, I then set out to create the custom scroller. One of the other decisions I had already made was that the scrolling functionality would only ever be present if the user already had JavaScript enabled. What that means is that the actual XHTML markup for the scrolling component doesn’t actually exist in the page until JavaScript explicitly inserts it (using DOM Scripting) and ultimately there would be absolutely no un-needed markup on the page for users viewing the site without JavaScript and/or CSS enabled.

When I started building the JavaScript I knew I’d need to accomplish (in order) 3 basic steps:

  1. When the page loads, switch the overflow property of the copy div to ‘hidden.’ Because I was making a custom scrolling interface, I didn’t need the scrollbars that the overflow: auto; value provides.
  2. Check to see if the copy div has more content than what can be seen in the visible area.
  3. Using DOM Scripting, insert the controls for the scroller, but only if the condition in step #2 was met. These controls would have unique IDs and have their appearance controlled by the site’s CSS.

The abbreviated JavaScript looks a little bit like this:

window.onload = function() {
    document.getElementById('copy').style.overflow = 'hidden';

    if (parseInt(document.getElementById('copy').offsetHeight) < parseInt(document.getElementById('copy').scrollHeight)) {
        insertScroller();
    }
}

The first line defines a function to handle the onload event, which will be thrown by the browser when the page finishes loading. The second line takes care of the overflow property and then a simple if statement checks the scrollHeight and offsetHeight of the copy div to see if the custom scroller is actually needed. If it is needed, the insertScroller function is called and the scroller gets inserted into the page. How the actual insertScroller function inserts the required elements is unimportant for the purposes of this post, so I won’t get into that (feel free to ask though if you’re interested).

Once all that was finished I went on to write the functions and event handlers that would control the scrolling of the content as well as other page events (such as handling scenarios like showing or hiding the scroller when users resize their text size on the fly). After that was done I did another round of browser testing to make sure that my scrolling interface worked across our usual list of supported browsers. Everything worked like a charm… or so I thought anyways.

It wasn’t until I pushed the site to an external server that I noticed that Safari was having a bit of an issue with the scroller, one that I wasn’t expecting to see and quite frankly caught me off guard. Basically what happened is that Safari would go through the normal procedure of inserting the scroller when needed, but the actual browser scrollbars were still visible; even after explicitly setting the copy div’s overflow property to ‘hidden’ in the JavaScript. No matter what I tried, I couldn’t get those scrollbars to disappear, so there I had my custom scrolling interface, and right next to it was the browser’s default scrolling interface which (to make matters more interesting) couldn’t actually be used. A quick alert of the copy div’s overflow property told me that it was in fact set to ‘hidden.’ Odd. Very odd.

The Problem 

Like I said before, it took me quite a bit of Googling to find out that Safari can’t dynamically alter the overflow property of an element. QuirksMode specifically says that it ‘can’t dynamically change the overflow property to auto or scroll’ but after more testing and even more searching around, the general consensus that I found was that Safari just can’t change the overflow property at all. Apparently the new beta of Safari 3 can handle it, but that’s only just been released and I haven’t had a chance to take a look at it yet to confirm or deny that statement.

The most confusing thing about the whole situation is that on our internal test server, the scroller and overflow change worked perfectly in Safari. I then had someone from outside the office look at our test-server version and see the problem, which made me scratch my head even more. So, I guess it comes down to a performance issue: on a fast internal connection where the site loads in a split-second, Safari is able to handle the switch seamlessly. On a live “through the Internet” connection when the site takes longer to load in, Safari has a brain fart of sorts and can’t deal with the switch.

The Solution

Well, truth be told, the solution is really more of an admission of defeat at this point. Because Safari can’t handle the switch, I’ve used a quick JavaScript test to bypass the insertScroller function if the user is using Safari. Yep, that means Safari users will get the browser’s native scrollbars.

The only thing I was able to determine is that if the copy div starts with the overflow property set to ‘hidden,’ everything looks just fine. Unfortunately, this makes the content inaccessible to users who have JavaScript disabled but still have CSS enabled, so it’s not a viable solution. Does anyone know if there’s a good way to get around this issue? Has anyone else run into problems like this?

Update: Well, never one to totally give up on something, I took another look at it last night and was able to figure out a bit of a workaround for Safari. By repositioning the scroller div, setting its background colour (previously I wasn’t setting any background colour, just some transparent background images) and playing with the dimensions of the copy div, I was able to hide the scrollbars underneath the scroller div. So, the scrollbars are still there, but you can’t see them. While this “solution” works great in this case, if you absolutely needed a transparent scroller you may still be out of luck.

Posted in: CSS, CSS Tips, JavaScript, Web Development, Web Standards

Comments (post your’s)

Globally Recognized Avatar1. Daco - August 29, 2007, 12:29 PM

I found another, dirty trick to accomplish this. If you first remove the div by myDiv.parentNode.removeChild(myDiv), than create a new div newDiv by document.createElement(’div’), insert the innerHTML property of myDiv to newDiv, and than reinsert this newDiv with the correct position and dimensions and off course with overflow set to hidden, I found it to work.

Again, this is really dirty, but I’m going to implement it in my project.

Globally Recognized Avatar2. Scott - November 2, 2007, 1:18 AM

I am having a similar problem with Safari.
In Firefox my scrolling div works perfectly, but viewed in Safari, the entire page scrolls.
I’ve been redesigning my site and I’m trying to use a single css style sheet instead of inline CSS. Now Safari will not even scroll and it drops the table with images in my portfolio down by 10-20 pixels. I’m baffled and my very knowledgeable friends are baffled as well. I would love to hear your feedback.

Globally Recognized Avatar3. Jonathan Eckmier - November 7, 2007, 7:01 AM

Hey Scott,

First off, sorry for the delay in getting back to you. It’s been a crazy week and I’m behind on getting back to emails or comments.

Second, without seeing your actual code it’s hard for me to really provide you with too much feedback, as I really don’t know without looking at it what could be causing this issue. So, feel free to use the contact form to send me your URL, or even some html/CSS/JavaScript snippets and I should be able to take a look at it.

If you need a quick response though, you’re probably better off posting your questions to a forum as I really can’t guarantee when I’ll have a chance to actually diagnose your code. SitePoint has a great community forum that I always point people to, and usually the response time is fairly quick.

The other thing you could do, is to do both. Post your question to a forum, and send me your URL/code. Who knows, I might be faster than I think :) Either way, thanks for visiting and please let me know what you find out!

Post a Comment

Fields marked with an asterisk (*) are required. Email addresses are never published or distributed.

Some XHTML code is allowed (<strong>, <em>, <del>, <code>, <blockquote>, <a href="URI">). URIs must be fully qualified (eg: http://www.reinspire.net) and all tags must be properly closed.

Line breaks and paragraphs are automatically converted.

Please keep comments relevant. Off-topic, offensive or inappropriate comments may be edited or removed.





Comment Preview:

Globally Recognized Avatar4.

 

« June 2007 »

Sun Mon Tue Wed Thu Fri Sat
     12
3456789
10111213141516
17181920212223
24252627282930

Search this site

Latest Entries

Hot Topics