Alternating column colors with jQuery

By Tim Priebe on January 4, 2010 at 7:04 pm in Design, Technical, css, html

jquery-tablesWe recently had one of our designers create a table design for a client with alternating column colors. Instead of laughing at her and not coding it, we instead decided to use a little jQuery goodness to get it taken care of.

We included the following code in our document’s head, using the Google jQuery implementation:

<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("jquery", "1.3.2");

google.setOnLoadCallback(function() {
$("table tr td:nth-child(even)").addClass("even-column");
$("table tr th:nth-child(even)").addClass("even-column");
});
</script>

So that’s the code that gives every other table cell, including header cells, the class of even-column. Now we can style those cells however we’d like.

In our case, a little CSS transformed the table pictured below on the left into the table on the right.

screen-shot-2010-01-04-at-64457-pm screen-shot-2010-01-04-at-64510-pm

Of course, putting the following in our google.setOnLoadCallback function will do something similar for rows.

$("table tr:nth-child(even) td").addClass("even-column");

This would result in the following:

screen-shot-2010-01-04-at-64554-pm

While this could have been solved by actually hard-coding the table’s cells with the even-column class, we are using Wordpress on this site. This means the client could add their own table on down the line, having no idea what a class is, much less to add a specific one to every other cell in every row of the table. Plus, that would be a lot of work.

Firebug in IE

By Sean Sanders on October 20, 2009 at 6:50 am in Development, Technical, css, html

firebug-logoI’m Sean Sanders, one of the relatively new programmers here at T&S. Our former programmer Nick Little blogged previously about tools to help with web development, and one of those tools I find incredibly useful is the Firebug plugin for Firefox. There are some situations when having the ability to look at the CSS in other browsers the way you can in Firefox is helpful.  This is especially true with IE. Because of the way IE chooses to (not) display CSS rules, we often have to create style sheets just for IE to make it display our sites properly. A few days ago I found myself in a situation where I was trying to debug a site in IE7 and wanted to figure out exactly which rules were being applied. I looked into seeing if there was a way to use Firebug in IE.

What I found was a short bit of Javascript the people behind Firebug had written to be able use some of Firebug’s functionality in other browsers. They call it Firebug Lite.  This isn’t the full addon for Firefox, so you can’t change CSS on the fly the way you can in Firefox, but it’s still useful for being able to see how the rules you’ve created are getting applied. The following is the script for adding it to your website:

<script type=”text/javascript”
src=”http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js”></script>

Also, for ease of use I wrote a bit of PHP to quickly turn the Firebug Lite script on and off.

<? if ($_GET['firebug']=="1") { ?>
<script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script>
<? } ?>

Now all you have to do is view the webpage normally when you don’t want to see the Firebug information, and add the parameter ?firebug=1 to the end of the url if you want to turn on Firebug. (Or, if there are already URL parameters, &firebug=1) I mentioned IE earlier, but if you are having trouble with your website in other browsers, such as Safari or Opera, it works equally well.

Manipulating Wordpress strings that print directly

By Tim Priebe on July 13, 2009 at 9:00 am in Development, How-To, Technical, html

Disclosure: This post is for tech-inclined Wordpress users, who like to code, or even do it out of necessity. If that doesn’t interest you at all, or you have no idea what I’m talking about, feel free to ignore this post.

We’re big fans of Wordpress around here. Unfortunately, many of Wordpress’s functions directly print out text and HTML instead of returning a string that can be manipulated directly.

Fortunately, there is a way around that limitation, ob_start. You can feel free to read the  documentation of ob_start, but the short version is that it buffers your output temporarily so you can save it as a string and manipulate it before outputting it.

Let’s look at an example. We’ve added some meta data to a post to display some dates and locations on a page. (Click to enlarge)

Wordpress meta data

Now let’s look at the code.

<?php the_meta(); ?>

The above code outputs the following HTML:

<ul class='post-meta'>

<li><span class='post-meta-key'>July 14, 2009:</span> Marketing Rxpo</li>

<li><span class='post-meta-key'>July 7, 2009:</span> Client Mixer</li>

</ul>

We want two changes. First, we don’t want the colon (:) after the date. Second, we want the spans to have a class of Date instead of post-meta-key. With the code as is, Wordpress just displays the info, with no way to change it. So let’s use ob_start instead:

<?php
ob_start();
the_meta();
$out = ob_get_clean();
$out =  str_replace(':</span>', '</span>', $out);
$out =  str_replace('post-meta-key', 'Date', $out);
echo $out;
?>

Here’s the output we get now:

<ul class='post-meta'>
<li><span class='Date'>July 14, 2009</span> Marketing Rxpo</li>
<li><span class='Date'>July 7, 2009</span> Client Mixer</li>
</ul>

Naturally, any string manipulation that can be done in PHP can be performed, this is just a simple example.

Should links open in a new window?

By Tim Priebe on December 2, 2008 at 6:30 am in Development, html

No.

Let me elaborate.

Years ago, website were all about controling the user’s experience. Some sites went so far as to set up their site with a series of “Next Page” buttons instead of actual, usable navigation. Thanksfully, the web design industry has come a long way.

In more modern times, we have come to realize that the best way to keep a website visitor on your website is to let them navigate it however they want to. In fact, with all the freedom that’s out there now, people tend to get irritated when websites try to control the experience. With links to other sites specifically, you just need to provide good content and information on your website, and they’ll come back.

Although I’m probably not an average website user, I tend to leave sites that open links in new windows. I have heard the argument that most website visitors are less sophisiticated than myself. That may very well be true.

However, I’ve stood next to a client and watched as they followed a link from one website to another, then discovered they didn’t know how to get back to the previous site. (The back button in the browser is not universally understood, which shouldn’t be a surprise to web professionals.) However, as this person had doubtlessly encoutered this situation before, she simply closed that browser window, opened a new one and went back to the website.

So a lack of skill or web-savvy will not hinder anyone when links do not open in a new window. If they do any amount of web surfing at all, they’ve already learned to work around it.

Easy Guide To CSS Drop Down Menus

By Nick Little on November 4, 2008 at 2:31 pm in css, html

Drop down menus are one of the most useful tools in a website. They can make a big site very easy to navigate through. However, for the web developer they can seem like such a daunting task. This short tutorial can help anyone get started with a simple drop down. The drop down will work in all current browsers (Opera, Safari, Firefox, Chrome, and Internet Explorer 6+) if done correctly. IE will need a little bit of help using javascript.

The first thing to do when creating a CSS drop down is to write the corresponding HTML or XHTML. I have seen many people use DIV tags to code drop down menus. However, I would argue that the best menu, including drop down menus, is always a list. Here is how we should start our list:

<ul id="mainmenu">
  <li><a href="#">First Link</a></li>
  <li><a href="#">Second Link</a>
    <ul>
      <li><a href="#">Drop Down One</a>
      <li><a href="#">Drop Down Two</a>
    </ul></li>
  <li><a href="#">Third Link</a></li>
</ul>

Next, we need to add a little bit of javascript to the head tag to make sure that IE7 and below will work correctly. Note that since we are adding javascript for the drop down and the CSS for the drop down may not work in all older browsers, it is highly recommended that you still include all the subitem links on the item page. (ie. Include links to “Drop Down One” and “Drop Down Two” on the “Second Link” page.) The javascript tells IE and below to add “hover” to class attribute when mouse hovers over a list item, since it doesn’t support the :hover modifier for list items inherently.

<!--[if lte IE 7]>
<script language="javascript" type="text/javascript">
function makeDropDownMenu(ul) {
  var lis = ul.getElementsByTagName('li');

  for (var i = lis.length - 1; i >= 0; i--) {
    lis[i].onmouseover = function() { this.className += ' hover'; };
    lis[i].onmouseout = function() { this.className = this.className.replace(new RegExp('\\bhover\\b'), ''); };
  }
}

function loadIEHover() { makeDropDownMenu(document.getElementById('mainmenu')); }
window.attachEvent("onload", loadIEHover);
</script>
<![endif]-->

And now for the fun part! Styling the drop down with CSS can be a tricky process at first. Here are a few basic suggestions for troubleshooting your CSS if it does not work:

  • Know the cascading rules for cascading style sheets and make sure that one of your previous rules for the drop down is not overriding the rule that is not working.
  • Make sure that everything is positioned absolutely and that overflow is set to visible.
  • Make sure that you have overridden any default browser styles and/or styles used by the rest of the site (especially margin and padding).

If your drop down is not working the way you think then one of the above suggestions will probably be the answer. At least those were the issues that I regularly ran into the first few times I designed drop down menus. Below is some sample CSS that can at least help get you started. Note that many times IE6 and sometimes IE7 will need different styles than more standards compliant browsers.

<style type="text/css">
body { background: #A9DEEF; }
#mainmenu { margin: 0px; padding: 0px; overflow: visible; position: relative; }
#mainmenu li { background-image: none; display: inline-block; min-height: 15px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; }
#mainmenu li a { color: #444; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; font-weight: bold; text-decoration: none; text-transform: uppercase; }
#mainmenu li a:hover { color: #000; }

#mainmenu ul { background: #000; left: -9999px; margin: 0px 0px 0px -63px; opacity: 0.8; padding: 0px; position: absolute; top: 15px; width: 127px; z-index: 1; }
#mainmenu ul li { border-top: 1px solid #FFF; display: block; margin: 0px; padding: 0px; }
#mainmenu ul li.First, #mainmenu ul li:first-child { border-top: none; }
#mainmenu ul li a { color: #CCC; display: block; font-size: 10px; font-weight: normal; padding: 5px 15px; text-decoration: none; text-transform: none; }
#mainmenu ul li a:hover { color: #FFF; text-decoration: underline; }
#mainmenu li:hover ul, #mainmenu li.hover ul { left: 50%; }
</style>
<!--[if lte IE 7]>
<style type="text/css">
#mainmenu li { display: inline; }
#mainmenu ul { filter: alpha(opacity=80); }
#mainmenu ul li a { display: block; }
</style>
<![endif]-->

Putting it all together, we have:

<html>
<head>
<title>Drop Downs are Awesome!</title>
<style type="text/css">
body { background: #A9DEEF; }
#mainmenu { margin: 0px; padding: 0px; overflow: visible; position: relative; }
#mainmenu li { background-image: none; display: inline-block; min-height: 15px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; }
#mainmenu li a { color: #444; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; font-weight: bold; text-decoration: none; text-transform: uppercase; }
#mainmenu li a:hover { color: #000; }

#mainmenu ul { background: #000; left: -9999px; margin: 0px 0px 0px -63px; opacity: 0.8; padding: 0px; position: absolute; top: 15px; width: 127px; z-index: 1; }
#mainmenu ul li { border-top: 1px solid #FFF; display: block; margin: 0px; padding: 0px; }
#mainmenu ul li.First, #mainmenu ul li:first-child { border-top: none; }
#mainmenu ul li a { color: #CCC; display: block; font-size: 10px; font-weight: normal; padding: 5px 15px; text-decoration: none; text-transform: none; }
#mainmenu ul li a:hover { color: #FFF; text-decoration: underline; }
#mainmenu li:hover ul, #mainmenu li.hover ul { left: 50%; }
</style>
<!--[if lte IE 7]>
<script language="javascript" type="text/javascript">
function makeDropDownMenu(ul) {
  var lis = ul.getElementsByTagName('li');

  for (var i = lis.length - 1; i >= 0; i--) {
    lis[i].onmouseover = function() { this.className += ' hover'; };
    lis[i].onmouseout = function() { this.className = this.className.replace(new RegExp('\\bhover\\b'), ''); };
  }
}

function loadIEHover() { makeDropDownMenu(document.getElementById('mainmenu')); }
window.attachEvent("onload", loadIEHover);
</script>
<style type="text/css">
#mainmenu li { display: inline; }
#mainmenu ul { filter: alpha(opacity=80); }
#mainmenu ul li a { display: block; }
</style>
<![endif]-->
</head>
<body>
<ul id="mainmenu">
  <li><a href="#">First Link</a></li>
  <li><a href="#">Second Link</a>
    <ul>
      <li><a href="#">Drop Down One</a>
      <li><a href="#">Drop Down Two</a>
    </ul></li>
  <li><a href="#">Third Link</a></li>
</ul>
<p>This is a test paragraph below the menu.</p>
<p> </p>
</body>
</html>

Each drop down is different, but the underlying principles and most of the base code is the same. As you deesign more and more drop downs you will come across more and more oddities in browsers that do not work the way you think. Thankfully, with more experience also comes the ability to troubleshoot the problems a lot quicker.

Rounded Corners with Alpha Transparency, Dynamic Height, & Dynamic Width

By Nick Little on August 15, 2008 at 6:30 am in General, css, html

Have you ever wanted to create rounded corners with alpha transparency, but didn’t think you could get it to work in IE6? Believe it or not, it can be done. It requires quite a bit of HTML, but this is a sacrifice that must be made in order for the alpha transparency to work.

First, we must separate the box into three sections: top, middle, and bottom. The top and bottom must be separate from the middle if you plan on having a full background behind all the content in the box. This way the transparency on the corners will not show the background from the middle section. I divided this into three separate DIVs:

<div class="ContentTop"></div>
<div class="ContentMiddle"></div>
<div class="ContentBottom"></div>

Next, we need to add several DIVs inside the top and bottom sections that will act as the corners and center section(s). (We may need more than one center section if there is a repeating background with a shadow as shown in the image on the right.) We also need to apply styles to these corners and sections. For starters, we know that the left and right corners must be the same size as the background images, since this is the only way to get IE6 to properly display alpha transparency. We will use absolutely positioned DIVs to achieve this. Listed below is the code for all browsers except IE6. The code for IE6 will be shown last. However, we still need to consider the shortcomings of IE6 when designing the rounded corners.

<div class="ContentTop"><div class="ContentTopLeft"></div><div class="ContentTopRight"></div><div class="ContentTopCenter"></div></div>
<div class="ContentMiddle"></div>
<div class="ContentBottom"><div class="ContentBottomLeft"></div><div class="ContentBottomRight"></div><div class="ContentBottomCenter1"></div><div class="ContentBottomCenter2"></div></div>

<style>
  .ContentTop, .ContentTopLeft, .ContentTopRight, .ContentTopCenter { height: 47px; }
  .ContentTop { position: relative; padding: 0px 42px 0px 38px; }
  .ContentTopLeft { background: url(images/contenttopleft.png) bottom left no-repeat; left: 0px; position: absolute; top: 0px; width: 38px; }
  .ContentTopRight { background: url(images/contenttopright.png) bottom right no-repeat; position: absolute; right: 0px; top: 0px; width: 42px; }
  .ContentTopCenter { background: url(images/contenttop.png) bottom left repeat-x; }
  .ContentBottom, .ContentBottomLeft, .ContentBottomRight, { height: 52px; }
  .ContentBottom { position: relative; padding: 0px 42px 0px 38px; }
  .ContentBottomLeft { background: url(images/contentbottomleft.png) top left no-repeat; left: 0px; position: absolute; top: 0px; width: 38px; }
  .ContentBottomRight { background: url(images/contentbottomright.png) top right no-repeat; position: absolute; right: 0px; top: 0px; width: 42px; }
  .ContentBottomCenter1 { background: url(images/contentbottom.png) top left repeat-x; height: 47px; }
  .ContentBottomCenter2 { background: url(images/contentshadow.png) top left repeat-x; height: 5px; }
</style>

Optionally, there may be a shadow on the right or left of the content. This can be pretty tricky, especially when trying to get it to work in IE6. In fact, it won’t work completely in IE6 when javascript is disabled. I used a shadow on the right. Here is the code:

<div class="ContentMiddle">
  <div class="Content"><!-- Content Goes Here --></div>
  <div class="ContentRight"></div>
</div>

<style>
  .ContentMiddle { height: 1%; overflow: auto; position: relative; padding-right: 5px; }
  .Content { background: url(images/contentbg.jpg) top center no-repeat; padding: 30px; }
  .ContentRight { background: url(images/contentright.png) top right repeat-y; height: 100%; position: absolute; right: 0px; top: 0px; width: 6px; }
</style>

Now, to add in all the IE6 code. We basically replace all the transparent background images with the filter property. We also add in some javascript code to make the right shadow the full height of its container.

<!--[if lt IE 7]>
<style>
  .ContentTopLeft { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contenttopleft.png', sizingMethod='scale'); }
  .ContentTopRight { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contenttopright.png', sizingMethod='scale'); }
  .ContentRight { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contentright.png', sizingMethod='scale'); height: expression(this.parentNode.clientHeight + 'px'); }
  .ContentBottomLeft { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contentbottomleft.png', sizingMethod='scale'); }
  .ContentBottomRight { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contentbottomright.png', sizingMethod='scale'); }
  .ContentBottomCenter2 { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contentshadow.png', sizingMethod='scale'); overflow: hidden; }
</style>
<![endif]-->

Finally, putting it all together we have:

<div class="ContentTop"><div class="ContentTopLeft"></div><div class="ContentTopRight"></div><div class="ContentTopCenter"></div></div>
<div class="ContentMiddle">
  <div class="Content"><!-- Content Goes Here --></div>
  <div class="ContentRight"></div>
</div>
<div class="ContentBottom"><div class="ContentBottomLeft"></div><div class="ContentBottomRight"></div><div class="ContentBottomCenter1"></div><div class="ContentBottomCenter2"></div></div>

<style>
  .ContentTop, .ContentTopLeft, .ContentTopRight, .ContentTopCenter { height: 47px; }
  .ContentTop { position: relative; padding: 0px 42px 0px 38px; }
  .ContentTopLeft { background: url(images/contenttopleft.png) bottom left no-repeat; left: 0px; position: absolute; top: 0px; width: 38px; }
  .ContentTopRight { background: url(images/contenttopright.png) bottom right no-repeat; position: absolute; right: 0px; top: 0px; width: 42px; }
  .ContentTopCenter { background: url(images/contenttop.png) bottom left repeat-x; }
  .ContentMiddle { height: 1%; overflow: auto; position: relative; padding-right: 4px; }
  .Content { background: url(images/contentbg.jpg) top center no-repeat; padding: 30px; }
  .ContentRight { background: url(images/contentright.png) top right repeat-y; height: 100%; position: absolute; right: 0px; top: 0px; width: 4px; }
  .ContentBottom, .ContentBottomLeft, .ContentBottomRight, { height: 52px; }
  .ContentBottom { position: relative; padding: 0px 42px 0px 38px; }
  .ContentBottomLeft { background: url(images/contentbottomleft.png) top left no-repeat; left: 0px; position: absolute; top: 0px; width: 38px; }
  .ContentBottomRight { background: url(images/contentbottomright.png) top right no-repeat; position: absolute; right: 0px; top: 0px; width: 42px; }
  .ContentBottomCenter1 { background: url(images/contentbottom.png) top left repeat-x; height: 47px; }
  .ContentBottomCenter2 { background: url(images/contentshadow.png) top left repeat-x; height: 5px; }
</style>

<!--[if lt IE 7]>
<style>
  .ContentTopLeft { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contenttopleft.png', sizingMethod='scale'); }
  .ContentTopRight { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contenttopright.png', sizingMethod='scale'); }
  .ContentRight { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contentright.png', sizingMethod='scale'); height: expression(this.parentNode.clientHeight + 'px'); }
  .ContentBottomLeft { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contentbottomleft.png', sizingMethod='scale'); }
  .ContentBottomRight { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contentbottomright.png', sizingMethod='scale'); }
  .ContentBottomCenter2 { background-image: none; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='images/contentshadow.png', sizingMethod='scale'); overflow: hidden; }
</style>
<![endif]-->

Happy Coding!