Options & Sideblog
-
- svgweb - Project Hosting on Google Code
- Raphaël—JavaScript Library
- Lifehacker's Complete Guide to Windows 7 - Windows - Lifehacker
- Rustic Creek Ranch | THE SHINING STAR OF NORTH TEXAS
- Usability.gov - Usability Home
- The Facebook app is dead, long live Facebook apps
- We've Got Technology Covered // OtterBox.com
- Callies Charleston Biscuits - Welcome
- Bayou City History | Blogging Houston's history with J.R. Gonzales
- Stack Overflow
-
- RSS 2.0 Feeds
- Journal
- Portfolio
- All Articles
- Atom 0.93 Feeds
- Journal
- Portfolio
- All Articles
TAMUSigmas.org: CSS and Design Notes 09.08.2005
- Article Summary
-
Before I could get started with implementing a CMS solution for TAMUSigmas.org, I had to duke it out with the Infamous Browser Bugs of CSS.
If there is anything I would have done differently with this project, it certainly would involve how I approached it from a design perspective. My unfamiliarity with CMS software and large-scale web standards implementations led me to approach this project with a reduced level of competency.
For example, I designed only a single template in Photoshop, and then improvised how this template should hold information from varying sections on-the-fly in CSS and HTML while in the midst of implementing those sections in the CMS. This method isn't conducive to an efficient workflow; I found myself trying to fit my design around the features of the CMS rather than fitting the CMS around my design. In the end, I feel this method limited the overall aesthetic of the final product.
It also didn't help that when I first started working in HTML and CSS for this site, I wasn't able to test the designs in Internet Explorer 5 or Internet Explorer 5.5 since I already had Internet Explorer 6 installed on my computer. After finally figuring out how to install multiple versions of Internet Explorer on my computer, I discovered numerous inconsistencies between how the design looked in Internet Explorer 6 and earlier Internet Explorer versions. Fortunately, all the problems were due to CSS bugs, and the strict separation of structure and presentation implemented by Xaraya was especially useful in helping me find and fix these problems; essentially, all I had to do was alter my stylesheets.
CSS has bugs?
Ha! Of course it does! Things just wouldn't be right with web design if there weren't numerous bugs for web designers to quash along their journey toward making the perfect website. Fortunately, the majority of CSS bugs are predictable in nature, and can be eliminated with a bit of pre-planning. Some of the problems I experienced weren't even bugs, some were caused by features that were not implemented in some browsers, while others were caused by unexpected consequences of valid CSS specifications.
Unexpected Consequences of Valid CSS
Non-Clickable Links
One odd situation that occurred in the early stages of this project involved a section of links that could not be clicked. In the top navigation menu for the website, there are a group of links in a list, preceded by an h2 heading for the benefit of non-visual users. My inital goal was to be able to hide this heading for visually oriented users — without resorting to the troublesome display: none method of hiding text.
The CSS for my first attempt looked something like this:
h2 {
font-size: 2.5em;
color: #6CF;
font-variant: small-caps;
position: absolute;
text-indent: 1000px; }
The reasoning behind this (disregarding the obvious text formatting) was that by absolutely positioning the h2 element, it would be taken out of the flow of the document, and then indenting it would allow for it to not be displayed on-screen. An absolutely positioned element retains its original width unless explicitly given new dimensions, and since this had not occurred, h2 was still taking up 100% width in that area of the screen. In actuality, the text did move off-screen, but it's container was still there, and since it had been absolutely positioned, the proceeding content (the navigation menu) settled in place directly underneath it, thereby becoming unreachable.
By using negative positioning and forcing the h2 element to display: block (thereby forcing the element to take up only as much space on screen as necessary), I was able to fix this problem:
h2 {
font-size: 2.5em;
color: #6CF;
font-variant: small-caps;
position: absolute;
display: block;
left: -1000px; }
I've included a short example showing a simplified version of the problem and its solution in separate HTML and CSS files.
Opera Bugs
Large Negative text-indent Values
- text-indent: -1000em;
-
Among the first CSS issues I encountered was an issue with disappearing content in Opera 7. Not just specific content, but all content. This was a particularly difficult bug to track down, because at first I had no idea what rules in my stylesheets were causing the problem to occur. After a rather long session of troubleshooting that was very much like having a head-banging contest with a ram, I went back to basics and started commenting out sections of my stylesheet to see what would happen.
- text-indent: -700em;
-
After following this method several successive times, I tracked the problem down to a negative text-indent I had been using in a rule to implement image-replacement for h1 elements. Negative indents past a certain number (-32767px + size of image) on any element result in the aforementioned bug. Using numbers above this threshold fixes the problem. Now, if you're using percentages or ems for dimensioning, the threshold will depend on your current resolution and/or default font size. In my case, I raised the text-indent from -1000em to -700em, and this fixed the problem.
Internet Explorer Bugs
Most web designers would probably consider this an oxymoron, as Internet Explorer is in many ways one huge bug all on its own. Nonetheless, over 90% of the web still uses this family of browsers, so Internet Explorer's shortcomings must be overcome. Fortunately, IE has several bugs that allow us to fix other bugs. Most of these are well known (the infamous Box Model Hack being key among these), but others are not. Here I'll be discussing some of the lesser-publicized bugs that I encountered while creating TAMUSigmas.org.
Doubled Float-Margins
- doubled float-margin
-
- regular float-margin
-
Internet Explorer (all current versions) experiences this bug whenever a floated element is placed within a container, and the floated element is given a margin in the same direction as the float. The result, as displayed in the image above, is a doubled margin. Here's the CSS responsible for causing this bug:
div#topmenu ul {
margin-left: 32px;
float: left; }
There are several solutions for this bug. In one solution, the margin-left setting can be changed to padding-left. In another, display: inline can be added to the rule. I chose the former solution:
div#topmenu ul {
padding-left: 32px;
float: left; }
The latter solution is also effective, and has the added benefit of being usable in those instances where it's not possible to use padding in place of a margin. For a more detailed explanation of these solutions and the bug itself, take a look at this article from Position is Everything.
Lack of Support for PNG Images
This one really isn't a bug; it's actually just a case of Internet Explorer not having default support for a useful feature. As some of you may already know, PNG images provide a way to implement alpha-transparency effects on web pages. In the case of TAMUSigmas.org, the header is actually a PNG image overlaying a background JPG. If you resize the browser window, you'll notice that the human figure slides underneath the masthead, and you can see parts of the figure as it slides underneath the semi-transparent shadow of the masthead.
- header in PNG-capable browser
-
- header in Internet Explorer
-
This effect works as intended in Mozilla and Opera browsers, but Internet Explorer shows us something much different. Instead of a semi-transparent masthead, the image is completely opaque, and the underlying iamge can not be seen from underneath it.
A List Apart has an article that explains the intricacies of approaching a solution to this problem. Their solution involves the use of a little known propietary visual filter available in Internet Explorer 5.5 and later — the AlphaImageLoader filter:
div#header h1 {
background: transparent none no-repeat left top;
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader (src='http://www.tamusigmas.org/themes/TAMUSigma_Classic/images/header-logo.png');
}
As is the way with most propietary code, the use of this filter in a stylesheet or web page will result in code that will not validate. The solution at A List Apart attempts to avoid this situation by using Javascript browser-sniffing to send the filter only to Internet Explorer. I had difficulty implementing this solution; it caused the masthead to disappear in Opera.
A simpler solution for me was to use Internet Explorer's conditional comments to allow for stylesheets to be filtered directly to Internet Explorer while being completely ignored by all other browsers. In the head element of all pages on TAMUSigmas.org, I've inserted this snippet of code:
<!--[if gte IE 5.5]>
<style type="text/css">
@import "themes/TAMUSigma_Classic/style/header_png_ie55plus.css";
</style>
<![endif]-->
<!--[if lt IE 5.5]>
<style type="text/css">
@import "themes/TAMUSigma_Classic/style/header_png_ie50.css";
</style>
<![endif]-->
These statements will be read and interpreted by Internet Explorer, but are completely ignored by all other browsers (and validators too!) The "hidden" imported stylesheets each contain a single rule.
For Internet Explorer 5.0 (by way of headerpngie50.css), the AlphaImageLoader filter is not available, so I've created a transparent GIF that omits the semi-transparent shadow:
div#header h1 {
background-image: url(../images/header-logo.gif)
}
For Internet Explorer 5.5 and Internet Explorer 6 (by way of headerpngie55plus.css), I used the AlphaImageLoader filter mentioned above.
Not a Bug, But I'll Mention it Here
To conclude this entry, I'd like to talk about a neat trick I discovered to fade out images encased in links that have already been visited.
The Problem
In the Events section of TAMUSigmas.org, a small thumbnail of a flyer is displayed alongside each event. Clicking on either the thumbnail, the event title, or the "details" link at the end of the event summary will lead to a detailed description of the event. However, when you return to the events page, the text links are grayed out while the thumbnail is still bright as ever. Quickly browsing the list of events to see which ones I'd already visited became distracting because the bright image next to the low contrast text of the visited links seemed to send mixed messages as to whether or not the event had been viewed.
Synopsis of a Solution
If you click on an event, and then return to the Events front page, you'll notice that the flyer alongside the event that has been clicked is greyed out (that is, if you're viewing the site in Internet Explorer 5+ or a Mozilla-based browser).
This was accomplished by using Javascript to implement an opacity filter for the flyers corresponding to events that have already been visited by the visitor.
Catch Fish With Hooks
The first step I took in solving this problem was to find a way to differentiate between images that should be affected by this solution and images that shouldn't be affected by this solution. This was accomplished by setting class="img_opaque" inside of all img elements that would serve as flyer thumbnails. Note that you could very well use class="img_gyeah" or class="img_doesntmatter" — all that matters is that the name is unique and descriptive enough to differentiate it from all other elements.
<html>
<body>
<img src="me.jpg" class="img_opaque" />
</body>
</html>
Now place the image in an anchor element and give it a place to go:
<html>
<body>
<a href="http://www.rawkus.com"><img src="me.jpg" class="img_opaque" /></a>
</body>
</html>
Place a text link leading to the same URL as in the anchor element from above. In this step I added some extra markup to provide better documentation for what's going on:
<body>
<h1>Using JavaScript to Change Image Transparency in a Web Page</h1>
<h2><a href="http://www.rawkus.com/">Link</a></h2>
<h3>This image will fade when the link is clicked.</h3>
<p>
<a href="http://www.rawkus.com/" class="img_opaque"><img src="me.jpg" class="img_opaque" /></a>
</p>
</body>
Set up some default styles for the a and img elements.
h3 {
clear: both; }
a {
padding: 3px;
border: 1px solid #AAF; }
a.flyer {
float: left }
a:link {
background-color: #CCC; }
a:visited, a:active {
border: 1px solid #CCF;
background-color: #EEE; }
a:link:hover {
border: 1px solid #DDF;
background-color: #EEE; }
a:visited:hover {
border: 1px solid #DDF;
background-color: #EEE; }
a img {
margin: 0;
padding: 0;
border: 2px solid #FFF; }
In the first rule, we're making sure that there are no floated elements alongside any h3 elements, which is necessary since we need to left float the anchor elements containing our images in order for the anchor's box to completely encompass the image. If we didn't left float the anchor, the top of the image would end up sticking out above the anchor.
In the second rule, we give each anchor some padding and a border, purely for visual flair. The float: left in the third rule is explained in the above paragraph. The rest of the rules are there for visual purposes, but it should be noted that the background-color for the a:visited selector is significant. This value will be used later on for a special purpose, so make sure that you take note of this value (in this case, the value is #EEE.
Now, we can link the stylesheet into the page, and add a head element to the document. Also, we'll add a reference to the JavaScript document (opacity.js) we'll need to do the magic of fading our image.
<head>
<title>Using JavaScript to Change Image Transparency in a Web Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<link href="default.css" rel="stylesheet" type="text/css" />
<script src="opacity.js" type="text/javascript"></script>
</head>
Bone 'em, Skin 'em, Put 'em in the Deep Fryer
Our opacity.js file contains three utility functions. The first function that we encounter is named findImgOpaqueClass().
function findOpaqueImgClass(classname) {
var alltags = document.all ? document.all : document.getElementsByTagName("img");
for (i=0; i<alltags.length; i++) {
if (alltags[i].className == classname) {
//alert(getCurrentStyle(alltags[i].parentNode, 'background-color'));
if ((getCurrentStyle(alltags[i].parentNode, 'background-color') == "#eee")
|| (getCurrentStyle(alltags[i].parentNode, 'background-color') == 'rgb(238, 238, 238)')) {
setOpacity(alltags[i], 30)
}
}
}
}
The goal of this function is to find all image elements with a class property set to the value of the parameter (classname) that has been passed into the function. Then, once all those elements are located, determine what the background color of their parents are. The getCurrentStyle function takes care of this:
function getCurrentStyle(obj, prop) {
if (document.defaultView && document.defaultView.getComputedStyle && document.body) {
var computedStyle = document.defaultView.getComputedStyle(obj, null);
return computedStyle.getPropertyValue(prop);
}
else if (obj && obj.currentStyle) {
return obj.currentStyle.backgroundColor;
}
}
The first if statement is for Mozilla, Firefox, and Safari, while the else if statement is for Internet Explorer.
Once the background color of the parent element is discovered, the next step is to determine whether this value is set to either "#eee" or the equivalent RGB value of R=238, G=238, B=238. What's so significant about this particular color? Well, since the immediate parent of all the selected images should be an anchor tag, we're essentially looking for all anchors whose direct descendant is an img element with a class property set to "imgopaque" ("imgopaque" being the value that is be sent to the function via the classname parameter). In addition, we'll only be selecting those anchors with "#eee" as a background color, and as noted above the only anchors set to this background color are those anchors that represent visited links (and active links too, but that's a bit of minutia that is irrelevant in this case). If the current img in the loop matches all the aforementioned criteria, it gets sent to a function named setOpacity for further processing.
function setOpacity(obj, opacity) {
opacity = (opacity == 100) ? 99.999 : opacity;
// IE/Win
obj.style.filter = "alpha(opacity:"+opacity+")";
// Safari<1.2, Konqueror
obj.style.KHTMLOpacity = opacity/100;
// Older Mozilla and Firefox
obj.style.MozOpacity = opacity/100;
// Safari 1.2, newer Firefox and Mozilla, CSS3
obj.style.opacity = opacity/100;
}
This is the function that fades the images. It works by lowering the opacity of the image so that it blends into its background, thereby causing it to lower its contrast and "fade" out. Notice the comments — this function will only work correctly for Internet Explorer for Windows, Safari, Konqueror, Mozilla, and Firefox (and any future browsers that understand the obj.style.opacity property). All other browsers will skip through this and not apply any opacity change, which is fine since it allows the entire thing to fail gracefully for those browsers that don't support opacity changes through JavaScript (i.e. Opera).
Well, everything should be fine and dandy right? Not exactly. We still haven't designated a way for our functions to be called from within our HTML document. This can quickly be remedied by setting the onload property of the body element:
<body onload="findOpaqueImgClass('img_opaque')">
Notice that we've called the first javascript function I talked about, and we're sending "img_opaque" as a parameter as discussed previously.
You can see this in action, and if you're so inclined you can also download the accompanying HTML, CSS, and JavaScript files. For more information, take a look at this excellent article about image fading over at Clagnut.
posted in Web Design at 04:12PM on September 08, 2005.