Omnibus

Accessible HTML Tables: Element Attributes

The , we covered some lesser-used child elements. Between that and the first article on tables, we’re set on table elements. But what about table-specific attributes? There are quite a few, some which you may not even be familiar with. These can help non-visual user agents as well as semantics. Read on to learn more.

A good table should generally be visually designed such that a visitor can look at it and use visual cues to understand the most important data, if any, or be guided visually toward whatever data are the focus of the table. Non-visual visitors do not receive those visual cues, however. The majority of these attributes focus on non-visual user agents. They give additional information or auditory cues to allow the table to be better understood.

Please note that when I reference “the attributes of an element” in this article, I’m referring to the element/table-specific attributes. Like most elements, these can have classes, ids, and other common attributes. No need to cover those here. Additionally, I’m from the school of separate content from presentation, as you should be, and so any attributes that are visual—and thus can be set using CSS—will also be ignored for the purposes of this article. Leave a comment if you want me to cover styling tables with CSS in the future.

table element attributes

Despite this series of articles focusing on tables, we haven’t really talked about the table element, have we? It’s pretty straight forward; you put all the important bits inside the <table> tag, maybe add a class or id, and don’t think about the actual table element again. However, for good table design, we should be putting a little more thought into that. There is at least one table element-specific attribute that is smart to use.

summary
The summary attribute allows you to provide a summary of the table for non-visual user agents. Visual users may be able to look at a table and understand instantly that such and such lines total a specific amount, thanks to visual design cues, but what about non-visual visitors? By providing that sort of information in the summary attribute, you allow them to quickly gain the understanding that visual visitors have. Example:

<table summary="The data show that sales are increasing steadily, rising almost $1000 per quarter, with a year end total of $12,000 this year as opposed to $8,000 at the end of last year.">
cellspacing
This attribute controls the space in between cells—not just padding on the cells, but actual spacing between the cells, borders and all. Modern Web development generally calls for a separation of content and presentation. As such, most display attributes for table are either deprecated or better set though CSS. cellspacing is the one remaining attribute that can’t be set through CSS reliably. Truthfully, I’ve never found need for it—I always want a cell spacing of 0, which is easily accomplished through CSS by specifying border-collapse: collapse; on the table. However if you do need spacing between your cells, the closest CSS comes is a border-spacing property that is ignored by IE. cellspacing is not deprecated, so go ahead and throw it in if you really need it. Its sister attribute cellpadding is not neccessary; you can add padding to any or all cells.

Cell attributes (th and td)

In How to Use the Table Element Correctly, we explored the difference between the two cell elements, th and td. While their use in semantic tables may differ, they share many attributes.

colspan, rowspan
The two spanning attributes allow you to create a cell that spans multiple columns or rows. For instance, <td colspan="5"> would span the entire width of a 5-column table. Likewise, <th rowspan="2"> would create a heading cell that spans two rows.

It is important to note that using these two attributes requires that you leave out cells that would overlap. Here is an example:

<tr>
    <th rowspan="2">Cells</th>
    <td>data</td>
    <td>spanning, headers, axis, abbr</td>
    <td>id, class, etc</td>
</tr>
<tr>
    <td>header</td>
    <td colspan="2">Same as above</td>
</tr>

Note that there are only two cells in the second row. The first cell is not declared, as it is spanned from the row above. And the last cell is also left undeclared, because the third (second defined) spans over the final cell.

The value of these two attributes is numeric. A value of “0” is perfectly valid; this value tells the user agent to span from the current location to the end of the row group (thead, tbody, tfoot), if rowspan, or end of the current colgroup, if colspan.

axis
The axis attribute is an interesting creature. It allows for categorization of data, which enables user agents to calculate answers to queries. For instance, in a table of expenses, if you label a cell with axis="entertainment", a user can query the user agent with something like “What did I spend on entertainment”. The user agent can ascertain which data are categorized as entertainment and then calculate an answer.

Cell attributes that are mainly useful for th

There are a few attributes that are perfectly legal to use on td elements, but if used properly, they really make more sense being restricted to th elements. They are immensely helpful to non-visual user agents, especially when the contents of the table are being read out loud.

scope
Used primarily on th elements, the scope attribute designates which cells the header refers to. Allowed values are:

  • row
  • col
  • rowgroup
  • colgroup

Adding the scope attribute to the first td in a row will cause it to act like a header with non-visual user agents. But since we’re being semantic, we’d never do that, right?

abbr
This attribute is immensely useful for non-visual agents, especially auditory ones. It allows you to specify an abbreviation of the cell contents for use when reading multiple times. It mostly pertains to th elements, which are repeated before data, however it can be used for td as well. Example usage:

<th abbr="Density">Population Density (1-100)</th>

For non-visual users, the full header would be read on the first encounter, but any repetition would use the abbreviation.

Cell attributes that are mainly useful for td

The headers attribute is the sibling of scope. Whereas scope defines which data a header pertains to, headers allows for explicit indication of which headers pertain to a given data cell. Its value is a space-separated list of ids, so you must make sure to use the id attribute on any headers referenced in this way. An example:

<tr>
    <th colspan="0" id="h1">Shared Attributes</th>
</tr>
<tr>
    <th rowspan="2">Cells</th>
    <td>data cell</td>
    <td>spanning, headers, axis, abbr</td>
    <td>id, class, etc</td>
</tr>
<tr>
    <td>header cell</td>
    <td colspan="2" headers="h1">Same as above</td>
</tr>

In the above example, we see that the cell with contents “Same as above” is marked as being headed by the “Shared Attributes” header. According to the W3C, this attribute is to be used by non-visual agents, but can also be useful to visual agents through the use of CSS styling.

Other table element attributes

The attributes for other elements, such as rows, rowgroups and columns have either been covered in or are merely design aids. The latter should be done through CSS rather than HTML attributes. If you want to learn more about those or any of the attributes discussed here, the W3C Recommendation on Tables is a great place to learn virtually everything about them. It includes plenty of examples as well.

And thus concludes the series on tables. Do you have any questions, or care to expand on what I’ve said here?

Converting From Named to Numbered Entities

The Web is ever changing, and this article is relatively ancient having been published 10 years ago. It is likely out of date or even blatantly incorrect in relation to modern better practices, so proceed at your own risk.

I’ve been having some feed issues lately, thanks to my propensity for using proper(ish) typography, such as real quotes (“=&ldquo;,”=&rdquo;,‘=&lsquo;’=&rsquo;) in my content and headlines. The problem was that XML doesn’t behave very well with some of the named HTML entities. My feed-generation code had some conversion set up using html_decode_entities() and a declared charset of UTF-8 for the document and decoded entities, which can handle them all, but for whatever reason no luck; It was still generating invalid RSS feeds. Matt Robinson’s code for conversion to numbered entities fixed it all up nice and clean-like. Thanks, man.

Advanced HTML Tables: Columns

Last week, we discussed table basics for the year 2010 (as opposed to 1995). We set up a simple semantic table with a caption, header and footer. Today, we’re going to go over two lesser-known elements: the colgroup and col elements. I had grand plans of going into some little-known attributes for other table elements, but we’ll leave that to next week.

So, my columns feel left out

In the last article, you saw how thead, tfoot and tbody allowed for groupings of rows in a table. But often times, it’s useful to group columns as well. A couple uses I can think of include highlighting a totals column or perhaps a sales option that you want to promote. Other uses include the ability to set explicit widths for individual columns without much extra markup.

So, where do these elements go? When using column and column-group elements, you place the tags after the caption but before any row-groups or rows in the table. Modern user agents will then determine which cells belong to the appropriate column or column-group.

<table>
    <caption>Elements To Use in Proper Tables</caption>
    <colgroup span="2" width="100px">
        <col width="90px" />
        <col class="attribs" />
    </colgroup>
    <colgroup span="1" width="0*"></colgroup>
    <thead>
    ... 

colgroup: grouping columns

As you may have guessed by the “group” part of the element name, colgroup designates a structural grouping of columns. Semantically, you’re saying that the columns are related somehow.

col: sharing attributes without structural grouping

Unlike colgroup, col does not specify structure, it merely allows you to share attributes across multiple columns. In fact, for purists, one might argue that col is purely layout-driven. I’ll let you judge of that on your own.

Only two attributes?

The use of colgroup and col in HTML is limited to two attributes: span and width.

Span specifies the number of columns the group encompasses for colgroup or the attribute should apply to in the case of col. When using these two elements, make sure that the number of elements and their span attributes don’t equal more than the number of cells you have per row.

Width allows you to set the width of a column or columns in a column-group. When used in colgroup elements, remember that it specifies width of each column in the group not the total width of the grouping. If a child col also has width set it will override the parent colgroup setting. General width values are accepted, but there’s also a strange format available: the zero-asterisk (0*) value, which sets each column to be the minimum width needed to display the full cell content. You can also use an asterisk with a numerical value to designate proportional widths. For instance, if you want three columns to be set up proportionally, you could designate them as such:

<colgroup span="2" width="100px"></colgroup>
    <colgroup span="3">
        <colgroup width="1*" />
        <colgroup width="4*" />
        <colgroup width="2*" />
    </colgroup>
    <thead>
    ... 

That structure would take the total remaining width after assigning 100px to the first two columns, divide it into seven portions (1+4+2 = 7), and then apply the correct width based on portion width multiplied by number of designated portions.

Beyond these two attributes, you can use most common attributes such as id, class, align, etc.

Tell me about styling.

Here’s the drawback: colgroup and col have limited styling. You can only use four CSS attributes, and even they are limited:

  • background: you can set a background, but it is only honored if both the row and cell backgrounds are transparent.
  • border: borders work if the table has borders set to collapse (border-collapse: collapse;), at which point the borders appear based on the border conflict algorithm. If the table is set to have separated borders, no dice.
  • width: works as expected, no explicit limitations.
  • visibility: will only work with the collapse value.

But despite the limitations, these two elements can come in handy for informative tables. Let’s put it together with our table code from last time:

<table id="elements-for-tables">
    <caption>Elements To Use in Proper Tables</caption>
    <colgroup span="2" width="100px">
        <col width="90px" />
        <col class="attribs" />
    </colgroup>
    <colgroup span="1"></colgroup>
    <thead>
         <tr>
             <th>Tag </th>     <th>Attributes</th>     <th>Description</th>
         </tr>
     </thead>
     <tfoot>
         <tr>
             <td colspan="3">* denotes optional child elements</td>
         </tr>
     </tfoot>
     <tbody>
         <tr>
            <th>caption*</th>
            <td>common attributes</td>
            <td>A succinct description or title for the table.</td>
         </tr>
         ...
     </tbody>
</table>

table {
    margin: 1em auto;
    border-collapse: collapse;  /* note that this is required for using border on columns */
    }
caption { font-size: 1.2em; }
th, td {
    padding: .25em;
    border: 1px solid #000;
    font-family: sans-serif;
    }
caption, th {
    color: #004900;
    font-weight: bold;
    text-align: left;
    }
thead tr, tfoot tr { background-color: #aaa; }
thead th {
    border-bottom: 3px double #000;
    background-color: #ccc;
    text-align: center;
    }
tfoot td {
    border-top: 3px double #000;
    color: #333;
    font-style: italic;
    font-size: .8em;
    text-align: right;
    }
tbody th { color: #000; }
col.attribs {
    background-color: #B6FFBD;
    border: 2px dotted #004900;
}

The result:

Elements To Use in Proper Tables
Tag Attributes‡ Description
* denotes optional child elements
† denotes tags to be discussed in part two, next week.
‡ only tag-specific attributes are included. In general common attributes are also allowed. See the W3C HTML 4.01 Attribute Table for a complete list.
caption* A succinct description or title for the table.
colgroup* span, width A way to group columns for semantic accessibility, progressive enhancement and styling.
col* span, width A child element of colgroup, used to share attributes amongst multiple columns.
thead* A group of rows comprising a header for the table.
tfoot* A group of rows comprising a footer for the table.
tbody* A group of rows comprising the body of the table. There can be multiple tbody elements.
tr A table row. If thead, tfoot, and tbody are not used, this will be a child element of the table, otherwise it is a child element of the rowgrouping elements.
th* †abbr, axis, colspan, headers, rowspan, scope A table heading. A child element of tr. Most commonly used to signify column headings when used in a thead element, but can be used as a row heading as well.
td †abbr, axis, colspan, headers, rowspan, scope, Table data. A child element of tr. The most numerous element in a table, it contains data.

Notice the funky border collapsing in the footer and that the heading background color overrides the column background color. But don’t let that limit you: be creative, and you can accomplish great feats.

Just think of how that could be useful in extremely large data sets, accounting tables, or product tables. The possibilities are endless. Next week, we’ll discuss attributes galore for semantic, accessible table creation.

Great Time to Start an IRA

“You’re in your early 20s. That’s too early to start thinking about retirement.” Wrong. So completely wrong. Now is the best time to think about retirement. Sure, it’s a long way off, but even a small percent of your salary can mean a nice bit of savings in the long run thanks to the power of compounding interest.

Start an IRA

I was inspired to write this post because ING/Sharebuilder is offering FREE automatic investments for the year when you start a new IRA with them before 15 Apr 2010. I already have a Roth IRA with them, but I decided to start another one. Those normal $4 commissions really add up and put a dent in returns, especially when saving as little as I am, and if I can get all of those transfers for free for a year, well, I’m gosh darn gonna try! The promotion applies to both Roth and Traditional IRAs as well as Rollover Roths.

If you’re not interested but are considering opening up a non-IRA account with them, leave a comment to that affect and I’ll pass along a referral that nets me five free investment trades and you $25 to invest.

Why?

As I said, compounding interest is amazing for growing money. I started my Roth IRA just a few months before my 23rd birthday. There’s not a lot of money in there, because I only put in $50/month right now while I pay off debt. At $4/trade, that’s a lot of fees in relation to the investment, so I started doing the investment every other month at $100 for now, until I can bump up my monthly contribution. But let’s run some numbers about what I’m gaining by even my paltry investment.

In my calculations I’m considering a really low return: 5%. Historically, smartly invested funds will net about 10% in the market over the time we’re talking about before retirement. At 5%, we should barely beat inflation. But, this requires investing in the market or things like bonds, not letting it sit in your local bank savings account or CD.

Effect of Compound Interest
Starting age Monthly investment Money invested Interest earned Total value at age 65 Monthly to match age 23 Increased investment Interest earned
I’m rounding. Numbers aren’t precise, but close.
23 $50.00 $25,200 $60,724 $85,500
33 $50.00 $19,200 $28,236 $47,436 $ 90.00 $34,560 $50,940
43 $50.00 $13,200 $10,867 $24,067 $178.00 $46,992 $38,508
53 $50.00 $ 7,200 $ 2,679 $ 9,879 $433.00 $62,352 $23,148

I’m using simple math here. Compounding annually, ignoring inflation, conservative return, ignoring commissions.

What does this show us? By saving $50 a month in an investment vehicle that is only returning 5%, starting at age 23, you get over $60,000 interest on top of your principal. If you wait 10 years, starting at age 33, that free money shrinks to only a little over $28k. Meanwhile, if you plan to have $85,500 in the bank at 65 like you would had you started at 23, you’ll have to bump up your monthly contribution to $90, and you’re still losing out on $10k in interest. And that return shrinks exponentially the longer you wait.

If you don’t believe me, play around with this calculator. It’s simple, but simplicity at it’s best: it’s very clear about the differences between starting now and starting later, with nothing fancy to confuse the fact.

N.B. The savings I’m talking about here is on top of any employer-based retirement plan if one with matching is available. If you’re not already contributing enough to get the employer match if you have one, you’re doing things wrong. Obviously, saving $50/month for retirement isn’t going to secure you a nest egg. Even my full retirement savings, currently around 7.6% of my income including a 3% employer match won’t set me up for retirement. I know I have to step it up once I pay down debt. But based on these numbers, the money I’m saving now is miles beyond better than saving nothing, don’t you think? So, why not start now?

But, I’m in debt!

I argue that even being in debt is no excuse not to start saving. With a caveat: If you’re so in debt that you’re paying minimum balances, pause retirement savings. You need to set up a budget, forgo some luxuries and pay off debt so that you can start saving. But I’m not a financial adviser. If you really are struggling that much, you need to go see one.

How to Use the Table Element Correctly

First, how not to use the table element: as a layout tool. Repeat after me: “Tables are for tabular data. Tables are for tabular data. I will not use tables for laying out a Web page. Tables are for tabular data.” So, now that we’ve gotten that bit out the way, let’s talk about what comprises a semantic, valid table. This is basic table creation 101. Next week, we’ll talk about advanced table features.

Forget the old paradigm

Remember back in the day when this was a complete table? Perhaps one you used as a layout tool? Or one you’ve seen recently in live code and then cried a little inside?

<table>
     <tr>
        <td>
            Hi! I’m some table content. In poorly-developed sites, this might actually be where all of the site content is!
        </td>
    </tr>
</table>

Great. Enough nostalgia. That is not an OK table for 2010.

The new paradigm: semantic, accessible, complete

What was that mantra? “Tables are for tabular data.” When presenting tabular data, we need some more information about that data. Modern HTML tags help us out there. First, let’s talk about what information we need for a good data table.

Distinction between headings (<th>) and data (<td>)

When you’re looking at a table, some cells are heading information. They don’t describe actual data, they describe what the data is. Those cells are table headings (th).

Of course, the bulk of the table cells are table data (td).

You should use the correct cell element for the right type of information.

A title (<caption>)

Your users need to be able to look at the table and know what it’s about. A descriptive, succinct title helps with that.

Important notes:

  • <caption> must be the first child element of the table.
  • There can only be one <caption> element inside of a table.
<table>
    <caption>Elements To Use in Proper Tables</caption>
    ...

Headings (<thead>)

We talked about using <th> element above, now let’s talk about where to use them. Short answer: mostly in the <thead> element.

The <thead> element is one of three rowgroup elements (the others are <tfoot> and <tbody>—more on them later). It gives semantic meaning to a grouping of rows, saying “these rows are the heading of the table.” Combining it with <th> elements allows you to create a semantic section to describe columns.

Important notes:

  • The <thead> element isn’t required, however any data that deserves to be in a table deserves to have headings, right? So semantically, you should use it. And again, don’t forget about its use in selectors for progressive enhancement and CSS.
  • An empty <thead> is invalid. It must contain a <tr> and the same number of header or data cells as the body of the table.
  • You can use <td> elements in it, but again, remember the distinction between those and <th>. Chances are, you’re definining a heading in the <thead>.
<table>
    <caption>Elements To Use in Proper Tables</caption>
     <thead>
         <tr>
             <th>Tag </th>     <th>Attributes</th>     <th>Description</th>
         </tr>
     </thead>
    ... 

Table Footer (<tfoot>)

The second of three rowgroup elements, the <tfoot> element designates a group of table row elements as the footer. I can’t harp on about how you should use the <tfoot> element in every. Single. Table. Because, I admit, you don’t always need a footer for data. Semantically, it can have a few different uses. I use it for things like a total line, footnotes for data, etc. Like <thead>, it’s not a required child element.

Important notes:

  • An empty <tfoot> is invalid. It must contain a <tr> and the same number of header or data cells as the body of the table.
  • It must come before the <tbody> element(s). Straight from the W3C:

    <tfoot> must appear before <tbody> within a <table> definition so that user agents can render the foot before receiving all of the (potentially numerous) rows of data.

    In other words, if you have a lot of data, the <tfoot> should be rendered before all of the data.

  • The <tfoot> should be displayed after all <tbody> elements, despite the fact that it appears before them in the code. However, this is sadly untrue for some older user agents and most HTML as PDF rendering vehicles. It sucks, but those older clients’ use is decreasing, at least.
<table>
    <caption>Elements To Use in Proper Tables</caption>
     <thead>
         <tr>
             <th>Tag </th>     <th>Attributes</th>     <th>Description</th>
         </tr>
     </thead>
     <tfoot>
         <tr>
             <td colspan="3">* denotes optional child elements</td>
         </tr>
     </tfoot>
    ...  

Table Body (<tbody>)

The final rowgroup element, <tbody> defines the body of your table—the section that contains all of your data. There can be multiple <tbody> elements in the table, if such a grouping makes sense for your data.

Important notes:

  • In any table that uses <thead> and <tfoot> elements, <tbody> is required. Otherwise, it is implicit. You should include it anyway.
  • For the most part, <tbody> will contain a bunch of <td> elements nested inside of <tr> elements. <th> elements are also appropriate if you want to add a heading for that row.
  • Using multiple <tbody> elements is not appropriate for zebra-striping. That should be a progressive enhancement with Javascript.

So, to wrap it up, code for a complete simple, semantic table will look something like this:

<table id="elements-for-tables">
    <caption>Elements To Use in Proper Tables</caption>
     <thead>
         <tr>
             <th>Tag </th>     <th>Attributes</th>     <th>Description</th>
         </tr>
     </thead>
     <tfoot>
         <tr>
             <td colspan="3">* denotes optional child elements</td>
         </tr>
     </tfoot>
     <tbody>
         <tr>
            <th>caption*</th>
            <td>common attributes</td>
            <td>A succinct description or title for the table.</td>
         </tr>
         ...
     </tbody>
</table>

Using Progressive Enhancement and Styling

The best argument for using complete semantic tables is for progressive enhancement and styling selectors. In the old paradigm, you’d need to add classes everywhere to style things; a class for the headings, a class for the footer, a class for row groups, etc. Instead, view this simple example of styling without any classes using only the elements:


table {
    margin: 1em auto;
    border-collapse: collapse;
    }
caption { font-size: 1.2em; }
th, td {
    padding: .25em;
    border: 1px solid #000;
    font-family: sans-serif;
    }
caption, th {
    color: #004900;
    font-weight: bold;
    text-align: left;
    }
thead tr, tfoot tr { background-color: #aaa; }
thead th {
    border-bottom: 3px double #000;
    background-color: #ccc;
    text-align: center;
    }
tfoot td {
    border-top: 3px double #000;
    color: #333;
    font-style: italic;
    font-size: .8em;
    text-align: right;
    }
tbody th { color: #000; }
Elements To Use in Proper Tables
Tag Attributes‡ Description
* denotes optional child elements
† denotes tags to be discussed in part two, next week.
‡ only tag-specific attributes are included. In general common attributes are also allowed. See the W3C HTML 4.01 Attribute Table for a complete list.
caption* A succinct description or title for the table.
colgroup*† span, width A way to group columns for semantic accessibility, progressive enhancement and styling.
col*† span, width A child element of colgroup, used to share attributes amongst multiple columns.
thead* A group of rows comprising a header for the table.
tfoot* A group of rows comprising a footer for the table.
tbody* A group of rows comprising the body of the table. There can be multiple tbody elements.
tr A table row. If thead, tfoot, and tbody are not used, this will be a child element of the table, otherwise it is a child element of the rowgrouping elements.
th* †abbr, axis, colspan, headers, rowspan, scope A table heading. A child element of tr. Most commonly used to signify column headings when used in a thead element, but can be used as a row heading as well.
td †abbr, axis, colspan, headers, rowspan, scope, Table data. A child element of tr. The most numerous element in a table, it contains data.

Hey, we have some different stuff going on, and not a single styling class to be found! Now, that, my dear readers, is good, modern (X)HTML.

As for progressive enhancement, I’m not going to cover anything here, but things like zebra striping, column sorting, scrolling, etc. are possible with the addition of semantic elements. In fact, in the W3C documentation on HTML tables, they give the following reasons for having <thead> and <tfoot> elements:

This division enables user agents to support scrolling of table bodies independently of the table head and foot. When long tables are printed, the table head and foot information may be repeated on each page that contains table data.

Sounds like a good reason to use semantic tables to me!

Why?

Because it’s good development.

More importantly, having a solid semantic framework for your table makes it better for accessibility, progressive enhancement and styling. It’s the same argument for any semantic, valid code. It’s better. It makes your life easier in the long run. It’s the right thing to do.

Stay tuned for next week, when I expand on the topics we discussed today and show you how to use little-known attributes and a few more elements to really make your tables “pop.” Okay, they won’t pop, per se, but they’ll provide very important instructions for non-visual browser clients and provide a few more hooks for progressive enhancement and CSS styling.

Why printf Isn’t Working: PHP String Handling

At one point in time, I spent hours troubleshooting why my argument swapping/repeated placeholders in sprintf/printf statements weren’t working properly. I referred to the PHP docs, the internet, cursed the fact that I was doing back-end coding again, etc., and finally gave up and just repeated my variables using normal, un-numbered conversion specifications. Not once did I see anything that answered my question: “Why am I getting a ‘Too few arguments’ warning when using numbered placeholders?”

So, why am I getting a ‘Too few arguments’ warning when using numbered placeholders?

I (and probably you) was/were/are using a double-quoted string.

The issue here is with how PHP handles the String type. PHP is pretty forgiving about a lot of things, and in many cases single-quoted strings and double-quoted strings work just as well as the other. But there are some very important differences, especially when it comes to special characters, conversion specifications and variables.

If you’re having this same problem, change to using single quotes. Voilà, your problem is probably fixed, as long as you didn’t forget to escape any single quotes within your string.

A little more information on strings

The number one thing to remember when working with single-quoted strings in PHP: the only parsed character is the escaped single quote [\'].

Double-quoted strings will parse many escape sequences, and most importantly will expand variables.

If you’re a visual learner, refer to this example:

print '\nHello $username';
print "\nHello $username";

The above code will produce the following (assuming $username has been set to “World”):

\nHello $username
Hello World

So why is this an issue with printf?

I haven’t actually found a source to explain this or verify my postulate. But, I’d bet money on it, and I’m not a betting woman.

Double-quoted strings expand the conversion specification as a variable before printf even gets a chance to evaluate the code. Visually speaking:

$s = "shoes";
$numchucks = "a";
$noun = "wood";
$verb = "chuck";
printf("How much %1$s would %2$s %1$s-%3$s %3$s...",$noun,$numchucks,$verb);

The above code results in a “Too few variables” warning, and nothing prints because printf is actually getting a string that looks like: “How much %1shoes would %2shoes %1shoes-%3shoes %3shoes... In other words, you’re passing it five valid conversion specifications but only four arguments. If you added in the proper number of arguments, like this:

printf("How much %1$s would %2$s %1$s-%3$s %3$s...",$noun,$numchucks,$verb,$noun,$verb);

The resulting output would be:

How much woodhoes would    ahoes chuckhoes-woodhoes chuckoes…

For those readers who are familiar with only the most basic of conversion specs, %2s is perfectly valid. It reads like: “format as a string [s] at least two characters long [2], using the default padding character [a space] and default alignment [left].” So, as you see with ‘a’, it pads the left of the value with a space (exaggerated in above example with three spaces).

In the above examples, we end up with a (somewhat) sensibly formatted string because our interpreted variable $s started with the letter ‘s’, a valid conversion specification character. You will end up with even weirder results if $s begins with an invalid conversion spec character. Take $s="random"; for example. printf tries to use ‘r’ but as it’s not a valid spec character it just leaves out the conversion specifications

How much andom would andom andom-andom andom…

Even more descriptive is if $s doesn’t exist:

How much would…

So, for future reference, if you want to use numbered conversion specifications, here’s the proper way:

printf('How much %1$s would %2$s %1$s-%3$s %3$s...',$noun,$numchucks,$verb);

And you know, I’ve really always wondered—

How much wood would a wood-chuck chuck…

…if a wood-chuck could chuck wood.

Semantic, Accessible (Good) Forms: the Label Element

One of the most common issues I see with forms is the improper (or lack of) use of label elements. Admittedly, I too am guilty of misuse, but even after becoming aware of them, I was very confused about how to do radio and checkbox elements. Why? I learned incorrectly that the for attribute of the label referred to the name attribute of the input. Wipe that from your memory this instant. The label’s for attribute is a reference to the input’s id.

Wait, back up. What is the label element?

The label element in HTML provides a way to give semantic meaning to the text describing or labeling form control elements. Using the element not only gives you an element to style around your labels, but also provides accessibility and functional advantages.

By using a properly constructed label element along with your input, textarea, or select element, you give

  • screen readers information on which form control the label belongs to,
  • manually maladroit visitors an increased click area (clicking on the label focuses on the element), and
  • yourself a semantic element to target with CSS and Javascript to use in design and enhancement.

Add this element and its use to your list of best practices for forms.

How do I use the label element?

The label element is simple to use and shouldn’t cause any additional headaches while setting up forms. Its usage is simple:

<label for="visitor-email">E-mail address</label>
      <input type="text" name="email" id="visitor-email" size="32" />

It can go either before or after your element. In a real form, you would most likely have the entire line wrapped in a list item or paragraph element, but I left those off for purposes of demonstration.

For checkboxes and radio buttons, the usage is very similar. You provide a label for each individual element, keyed to that element’s id attribute:

<label for="contact-by-email">e-mail</label>
      <input type="radio" name="contact-how" id="contact-by-email"  checked="checked" />
<label for="contact-by-phone">phone</label>
      <input type="radio" name="contact-how" id="contact-by-phone"  />

Incorrect use, a demonstration

The following are improper uses of the label element:

<label>E-mail address</label> <input type="text" name="email" id="visitor-email" size="32" />
In this example, the label does not have a for attribute declared, so its semantic value and aid in accessibility is lost.
<label for="contact-how">Contact by</label>
       phone <input type="radio" name="contact-how" id="contact-by-phone"  checked="checked" />
       e-mail <input type="radio" name="contact-how" id="contact-by-email"  />
Here, the for attribute is referring to the name attribute of the inputs. This is incorrect. The for attribute is a reference to the id attribute of the input.
<label>Phone <input type="radio" name="contact-how" id="contact-by-phone" checked="checked" /></label>
While technically correct according to W3C recommendations, this method should not be used. The reason being, certain browsers, particularly mobile browsers, handle this code incorrectly and will often cause the element to be un-clickable. You are better off using the method of labeling checkboxes/radio buttons I described above.

For detailed information on the label element and other form information, check out the W3C Recommendations on Forms.

Don’t Let TurboTax Free Edition Fool You—You Probably Want FREEDOM Edition

TurboTax touts their Free Edition’s free-ness. Free to use, free to file. Free for Federal, that is (1040EZ only). Then, they try to up-sell you on filing State for $27.95. What they probably don’t want you to notice is that the Free Edition has nothing to do with the Free File program offered by the IRS, which TurboTax does participate in. But I noticed. Especially one year in while in college when I had to file in three different states, all of which allowed Free E-Filing.

Some of the numbers have changed. View the 2010 update.

Do You Meet One These Criteria?

  • AGI of 31k or less, or
  • Active Military with AGI of 57k or less, or
  • you qualify for the Earned Income Credit

Congratulations, you should probably use Freedom edition if you are planning on using TurboTax.

The IRS Free File program has its limits, as does TurboTax Freedom edition. For the former, you’re only eligible if you had an AGI of $57k or less in 2009. For TurboTax, it’s even more stringent: $31k AGI (for single filers). Additionally, if you own a house, own a business, have a lot of investments/capital gains/losses or donate a lot to charity and you don’t pay attn. to tax laws on your own or don’t care to, neither of TurboTax’s free editions are right for you. There are other companies that offer robust solutions through the Free File program that don’t have the same income limits (Freedom) or restrictions to 1040EZ (Free).

Why should I care?

I don’t know about you, but I don’t want to pay $30 to file my state taxes. Freedom edition allows you to do it for free in states that allow for free e-filing.

Additionally, while 1040EZ will suffice for some people, many others have more difficult tax needs and thus need access to the 1040, which is provided by the Freedom edition, but not Free edition.

But, I don’t see that option on TurboTax’s Web Site!

Yes, they’re rather sneaky like that. In order to access the Freedom edition, you have to go through the IRS Free File Portal. The IRS provides a nice tool to help you choose a preparer, but you can also choose to go to TurboTax directly. The link to TurboTax will allow you to use the Freedom Edition, where things really are free.

I can’t speak with any amount of authority, but I believe the same process is true for some of the other tax companies as well. So, if you do have an AGI under $57k, it’d be smart to head over to the IRS Free-File page and access the online tax applications from there. They provide a list of participating companies, the limitations of each, and a link to the correct free edition.

My Opinion of 1st Financial Bank, USA: Steer Clear

In honor of paying off my oldest/highest-interest credit card balance (woohoo, halfway through my CC debt!), I thought I’d share some thoughts on the card issuer—1st Financial Bank, USA. Particularly, why I think it is an exceptionally shady lender that preys on financially-uneducated students. Sure, most credit card lenders are shady, but few target students to the extent of 1FB.

Is there any good?

Before I bash them, I will admit to a couple of good things: they allowed me to found a credit history at age 18 and raised my limit like clockwork every 6 months, allowing me to maintain a decent debt/credit ratio. Except, maybe that latter bit wasn’t that “good.” I mean, do they really expect a college student to have the means to pay back ~12k? No, definitely not, but 1FB can make a decent chunk of fees if one were to charge up that amount. For the record, I never hit anywhere near that limit.

The Bad

They make it hard to pay and hard to know when to pay by providing jumping due dates, outdated Web access, no option for e-statements, no financial education tools, and limited telephone customer service hours. Maybe some research firm told them that it was good business sense for Generation Y to have access to account information via text message, but to lack a robust online portal, who knows, but if they did, they were told wrong. Regardless of my critique of their technological presence, the real issue is that they exhibited about every bad practice outlawed by the recently-passed CARD act, and are retaliating with painful rate increases and feature removal.

Preemptive CARD Act Changes

Two words: 24.99% APR. Yes, in anticipation of the CARD act coming into effect, they raised my interest rate by 10%! in October. 14.99% wasn’t great to begin with, but 25% is usury in most states (but not SD, where 1FB is based). Also, in addition to the general overdraft/late fee raising that most banks are doing, they also removed the one “reward” type feature of the card: 0% on balances below $250 (or $500 for other cards of theirs).

A good thing? They did remove double-cycle billing. Of course, it wasn’t out of the kindness of their blackened hearts; ceasing double-cycle billing is one of the major dictates of the CARD act.

When Is My Bill Due?

On the nth of the month, give or take a week. My due date constantly bounces around. It is generally somewhere early in the month, but has ranged from the 5th to the 16th. It’s a great way to trap the inattentive (or busy!) student into a late fee.

And a newer development: The online FAQ provides the following about information available online:

1FBUSA Online Services provides easy access to the following information about your credit card account: your credit limit, current account balance, amount of your last payment, date last payment received, your available credit, last statement balance and date, minimum payment due, payment due date, next billing statement date, and next billing statement payment due date. Transactions posted since the date of your last statement are also available, …

[Emphasis Mine]

However, after recent site updates, they no longer provide either a next billing statement date or the next due date. It may seem like unimportant information, but I would like to know the exact date I can see the final finance charges due on my account. Not to mention I prefer to pay the account as close as possible to the statement date, rather than the due date.

How do I pay my bill?

Oh, sorry, we’re still in the 20th century. Mail us a check with your statement stub, please. Your bank does online payments? Well, that’s some newfangled thing they’ve never heard of (ok, a little exagerated, they do provide an ACH program you can enroll in), but the bank can send them a paper check instead of an electronic payment. That’s what ING Direct does for me. The downside there is that despite it being free for me (one of the great ING features), it takes about a week to post, depending on the date 1FB receives it, since it doesn’t have the remittance stub with it, just the acct # on the check..

What about paying online or by phone, like most any decent credit card? Sure, for a $9 charge. I guess it’s the lesser of two evils: forget to send your payment and tomorrow is the due date? No problem, just pay $9 to make a payment on their Web site. Think that’s ridiculous? NP, you can just pay the higher late fee.

Want some human compassion/courtesy? Fuggetaboutit.

Don’t get me wrong, I don’t think it’s the bank’s responsibility to forgive fees right and left or for every sob story, but pretty much anywhere will give you one late payment fee pass, especially if you pay on time consistently. Does that include 1FB? Not in my experience, and I didn’t even hit the dreaded 30-day past, report to the Credit Bureaus point, just 15 days or so.

A few years ago, my grandmother passed away during December finals, right before the payment due date. The following two weeks were a mess—flying home for the funeral, flying back to school to finish my finals, driving home for the month break between semesters (and you had to be out, out, out! of the dorms within 24 hrs. of your last final). True, it’s my responsibility to pay my bill, but obviously, I was a little distracted. I forgot to send in payments for both of my cards. Two weeks go by and I realize my mistake, and send in the payments, then make the dreaded call to request forgiveness of the late fee with my story. Chase: “Sorry for your loss, miss. I see you’ve paid on time in the past. We’ll remove that fee right away as a one-time courtesy. Thank you for calling.” 1FB: “Errr, you paid late. That means a fee. You need to pay it. Yeah, you’ve always paid on time before, but it doesn’t matter. Have a nice day.”

Maybe they decided to take the tough-love approach to creating dependable borrowers. Sure.

What Can You Do About It?

If you have a 1FB card, get it paid off (consider transferring the balance to a new company’s card), find a different card to use every day, and consider closing your account. But don’t close it if it is your oldest account—that will likely hurt your credit score. If you don’t already have a 1FB card, don’t get one!

Update: closing the account might not hurt your score as much as they try to make you think it will. Read about how (not) bad it hurt my credit score to close this account in June 2010.

If you’re a just-entering-college student, verse yourself in financial literacy. Don’t use the card except for small things that you pay off monthly. And that advice applies to any card, not just 1FB-issued ones.

If you’re a parent of a young-adult, please educate them on how to handle their finances, and if possible find a way to get them a card with a company that has some sort of conscience, no matter how small it is. Any other bank seems a little better than 1FB USA.

Of course, in a dream world, we wouldn’t need to worry about getting a credit card at 18, but unfortunately, credit history is important once you graduate and enter the real world, and that’s about the only place to start.

Server Ignoring PHP 301 Header: IIS Known Bug

The Web is ever changing, and this article is relatively ancient having been published 10 years ago. It is likely out of date or even blatantly incorrect in relation to modern better practices, so proceed at your own risk.

This is a little more back-end/server-side than front-end, but I happened upon an absolutely aggravating bug found with IIS/the FastCGI module when moving a client over to a new site structure. Like any good development company, we wanted to make sure the old site structure URLs redirected permanently (301 Redirect) to the correct new URLs so that off-site links continued to work. Unfortunately, I ran into some roadblocks setting it up.

The Problem and Roadblocks

This is a large site; something on the order of 2500 pages needed redirects for the new structure. Or at least, 2500 URLs. Many of the pages were dynamically generated from a CMS with redirects already set up to resolve SEO-friendly URLs to the server-based variable-laden ones. The fastest and most convenient—not to mention maintainable and scaleable—method of doing this seemed to be writing a quick PHP script (as it is the scripting language used by the site and CMS) to map the old URLs to the new. We’d simply redirect all requests to that script and then let it handle the mapings with a header statement:

header("Location: ".$newURL,true,301);

Trivial, quick, workable. At least on Apache. I traced my headers though, and IIS was sending a 302 (Temporary) redirect despite the explicit 301 call. I threw out some very naughty words at that point.

Roadblock #1: Using a Microsoft Server

Ok, so, maybe I’m being a little flippant. I suppose there’s nothing wrong with IIS. It’s just that I, personally, prefer LAMP development if I have to do back-end/server-based stuff.

But facetiousness aside, IIS really is the cause of our problems in this case. Ultimately, two issues were affecting what should have been a simple issue. Specifically, a bug in the IIS FastCGI module and a size limit on web.config files.

Roadblock #1.1: IIS/FastCGI and PHP 301 Redirects

Two dirty words: “Known Bug.” Essentially, IIS/FastCGI module somehow lose track of the fact that you said “I want a 301 redirect” and handles it as a 302. Every. Single. Time.

So, our quick, easy, maintainable, scalable script idea goes out the window.

Roadblock #2: web.config filesize limit

Evidently there is a max size for your web.config filesizes. Don’t ask me what it is though: I can’t figure that out. My Google-fu isn’t strong enough to find anything about it, evidently.

I found this out when moving to Redirect Mapping Plan B: Spit Out web.config Redirects for Every URL Mapping In One File. That, my friends, spit out a wonderful 500: Internal Server Error error when I uploaded my new web.config file.

Guess it was time for a Plan C.

Our Workaround

Yuck.

I don’t even want to mention it. It’s depressing. Hopefully if you run into this, you can do something better.

We wrote a script that generated the URLs we needed and the mapping to the new URLs. Then, we formatted them for web.config redirects (everything to this point was actually part of Plan B. Moving on:) and made individual web.config files for each. Individual. Folder. under the old structure. This meant leaving old, useless folders online with nothing by web.config files in them. Like I said. Yuck.

Why not use another language, like ASP to get around the bug?,” you ask. In theory, that would work. But it would also take more time. See, we needed to interface with the CMS to get the correct URLs, so not only would we have to author the quick mapping script, but we’d have to write a more involved script to actually retrieve the correct URLs from the PHP-based CMS, and that was determined to be a non-option. (Hey, it all comes down to business: time==money && faster_workaround == less_time == more_money_per_time.)

Will This Ever Be Fixed?

According to user ruslany (Microsoft employee?) on the IIS forums:

This is a bug in IIS FastCGI module. It will be fixed in Windows 7 RTM. We are also looking into possible ways for making this fix available for IIS 7.

So, short answer, no, not really, unless you upgrade. Maybe they’ll get around to fixing it in IIS 7 with a patch. Maybe. They’re looking. He says. Here’s the full thread.

As for the max web.config file size, it actually makes a lot of sense, so I can’t imagine them fixing changing it. It was just frustrating to hit that unknown amount after the other bug. If anyone reading this happens to know that mysterious byte size cap, though, please let me know. It’d be useful info in the future, I suppose, and I am too lazy to experiment to determine the answer.