Display flash object alternative content depending on media query?

A client of mine wants to keep a menu navigation that was made as a flash object by his previous webmaster a few years ago. Now I’m trying to make this thing more accessible so I figured I would use alternative content to provide a html version of the menu:

<object type="application/x-shockwave-flash" data="menu.swf" width="980" height="405" id="flashnav">
  <param name="movie" value="menu.swf" />
  
  <div id="nav">
    <ul>
      <li>
        <a href="/1.html">Link 1</a>
      </li>
      <li>
        <a href="/2.html">Link 2</a>
      </li>
      <li>
        <a href="/3.html">Link 3</a>
      </li>
      <li>
        <a href="/4.html">Link 4</a>
      </li>
    </ul>
  </div>
</object>

This seems to work well for browsers without flash and the html menu is displayed. However, the flash menu has been designed for larger screens and while I can shrink it in html/css it will become unusable on small devices like smart phones. Some smart phones can have flash installed and it would be very bad to display the flash menu shrunk to the tiny screen size - so I want to display the alternative content (html menu) for them. Is this possible with media queries or do I have to use some js trickery for that?

I couldn’t find a css way to force the display of alternative content even if flash is installed and other solutions I’ve thought of are not that elegant in html markup.

The problem is that when I set display: none on the <object> then I hide the whole thing including its alternative content.

Would it be impractical to just have two nav bars, and hide one and show the other? Also, I hate to be the kneejerk-reaction nay-sayer, but is there a reason for the Flash menu at all? Generally I’d argue that if you’re already working on the menu for this client, it’d be far easier and far more web-friendly to just replace it with a nice menu that does what you want, and does not employ Flash.

Can you post the link to the flash menu? We might be able to recreate it in HTML/CSS/Javascript which would eliminate this issue altogether.

I was thinking about this solution but then how will I display the html nav depending on flash availability? Media queries won’t detect flash and if I have these nav bars in two independent html elements then people who have flash will see both of them. I could use js to avoid that but I’m trying to avoid js as much as possible.

[quote=“jeffreylees, post:2, topic:100973, full:true”]Also, I hate to be the kneejerk-reaction nay-sayer, but is there a reason for the Flash menu at all? Generally I’d argue that if you’re already working on the menu for this client, it’d be far easier and far more web-friendly to just replace it with a nice menu that does what you want, and does not employ Flash.
[/quote]

My reaction was exactly the same but the client is firm in his requirements and I can’t change that. The flash menu is not a simple one - it’s got fancy animations with shiny reflections moving in a 3D fashion across the surface of objects in photographic sections, shiny stars appearing in certain spots, complex slide-in text effects with motion blur and non-standard acceleration movement and stopping, plus some sound effects. Really, LOTS of work for anybody trying to replicate that in js so I decided to simply use the flash and provide simple fall back menu without the effects.

The best I can think of right now is simply serve the html menu by default and use js to replace it with flash on DOM load but then I don’t know how to avoid unnecessary http requests for background images in that html menu if flash is available - browsers may start fetching them before my script replaces the whole thing with a flash object.

Surely that isn’t part of the equation for your requirement. Just display the alternative nav for smaller devices/viewports using media queries and show the flash version for larger devices/viewports using your existing set up. Just have two separate html sections for this job.

Hm, but then I will actually have 3 html sections because my current setup contains the object tag and the alternative html section within. Then I would have to duplicate the html section outside the object tag. I don’t like the idea of duplicating the html menu in the code.

Yes that’s the only drawback but it makes for a simple solution. You will find quite often that mobile navigation is kept in a hidden div and only revealed to smaller devices. Unfortunately you can’t hide the outer object element but only show the inner alternative content to mobile with css alone.

Ok, it’s simple enough I’ve tried it and it works - almost… The problem is that when media query detects small resolution and sets display: none on the <object> then the swf file is still loaded so if someone views the site on a mobile phone the browser will still load the swf even though it will not be shown. Is there a way around this or will js be unavoidable in this case?

This works well the other way round - when the flash version is displayed then images from html menu aren’t loaded because they are background images. Unfortunately, the same mechanism doesn’t work when hiding the flash object.

Unfortunately the resources in the html always get loaded even if they are display:none. In some cases even background images will be loaded even if not used by the mobile’s media query.

That’s why its better to find an html/css menu that suits all devices rather than working around the flash issue. I think your only option in this case will be to inject the object element into the page with javascript for desktop users,

Mobile usage has polarized web design a bit in that authors now need to think carefully about the resources they use and how best to present them. In a lot of cases this has resulted in cleaner, more accessible sites across the whole range of browsers.

It’s a complicated issue as clients always want the “all singing all dancing” approach whether their users like it or not.

Thanks for the article - very informative stuff on the matter!

Then I’ll have to do it this way. However, I’ll be facing a similar problem on the other end - how to prevent html menu background files from being loaded when the flash menu is to be shown? I imagine I’ll put the html menu into the page content without the object tag so it will be the default one. Then after DOM is loaded I’ll run js that will detect large resolution and if necessary it will wrap the html menu with the object tag pointing to the flash - so if flash is available it will be displayed instead of the html version. Now how do I prevent browsers from loading html background images before my js does the swapping? Back in the old days I would use document.write to output the desired html but I’m a bit hesitant to use it nowadays… but is there any good substitute for this?

You can hide background images if you use media queries that don’t overlap. In this case the desktop won’t download the smaller devices image and vice versa.

But the thing is I cannot hide background images with media queries because if I hide them then well, there will be no menu! If I hide the background images in css for the desktop size and the user has no flash then he will see nothing. I could use js to unhide them but I want users without js to also see my html menu.

I think for good accessibility I need to have the html menu normally visible in html and css by default and only hide it if I can replace it with flash. But before the replacement the browser may load the images even if not necessary.

Just for the record I have tried hiding the html nav immediately inline in js like this:

  <div id="nav">
    <ul>
      <li>
        <a href="/1.html">Link 1</a>
      </li>
      <li>
        <a href="/2.html">Link 2</a>
      </li>
      <li>
        <a href="/3.html">Link 3</a>
      </li>
      <li>
        <a href="/4.html">Link 4</a>
      </li>
    </ul>
  </div>

<script>
    var nav = document.getElementById('nav');
    if (nav) nav.style.display = 'none';
</script>

This effectively prevents any background images belonging to nav descendants from loading - tested in Firefox and Chrome. I don’t know if it will work in 100% of cases but when testing on localhost it did. On DOM load my script simply sets the display to block again so this doesn’t cause any problems. If a user has js turned off then the hiding script will not fire therefore the menu will be visible.