"I regularly read Internet user groups filled with messages from people trying to solve software incompatibility problems that, in terms of complexity, make the U.S. Tax Code look like Dr. Seuss." — Dave Barry
Fancy Directory Listing (Using htaccess)
Fancy Directory Listing (Using htaccess)
In this tutorial I cover the basics of htaccess, how to create a custom Apache directory listing using .htaccess. If you look at the default Apache directory listing you’ll see a plain, boring, dull, hard to read design. Our objective for the course of this tutorial is to spice up that design, and learn some htaccess in the process!
For those that would just like to see the finished results, you can see the before and afters here.
http://www.thewebsqueeze.com/samples/directory-listing/
The Rules
Before we get started I want to cover the SUPER basics of htaccess. This will help those who aren’t familiar with how Apache and htaccess work understand what we are doing as we go along. (These are generic rules, and may differ from server to server, depending on the configuration. Ask your server administrator if you receive any errors.)
- All htaccess code should be placed in a text document named ‘.htaccess’.
- htaccess works on a recursive basis. So any command you type will work for the current directory, and all sub-directories under that, unless otherwise specified.
- You can have any number of htaccess files on your domain. The root of your domain can have a master htaccess file, and then you can override the master htaccess file within sub-directories off the root of the domain.
- In htaccess, any line prefixed with a “#” symbol is considered to be a comment. You should comment your code so you can refer to that comment 3-4 months down the road when you are trying to figure out why you coded it in that way.
- If ever in doubt you can read the Apache documentation. (http://httpd.apache.org/docs/2.2/) Or, you could ask the kind hearted folks at The Web Squeeze in our forum! (http://www.thewebsqueeze.com/forum/)
Let’s get started!
Here’s the default directory listing for Apache! Now, you might not see this by default, in fact you may see a Forbidden page, however, we’ll fix that with this next bit of code!

I always start my htaccess documents with what I call “General Rewrites”, those are the rewrites that I tend to duplicate throughout all my htaccess documents.
# START :: General Rules
RewriteEngine On
RewriteBase /
In htaccess any line prefixed with a “#” symbol is considered to be a comment. So, for organizational purposes I have commented the start and end of sections. We are then turning on the RewriteEngine and setting the base for the engine, if it’s not already set.
Options +Indexes
First, as you may already know htaccess has countless options to allow you to control how your domain works and loads without editing server configuration files. The “Options” directive controls which server features are available in a particular directory. You can view all the available options on Apache’s website.
http://httpd.apache.org/docs/2.0/mod/core.html#options
So, we’re saying find the “Indexes” option within the “Options” directive, and turn that on. By adding that “+” sign in-front of “Indexes” you are effectively turning on Apache’s directory index for not only that directory, but all sub-directories below that location.
This means that if a URL which points to a directory is requested, and there isn’t a DirectoryIndex (e.g. index.html) then mod_autoindex will return a formatted listing of the directory.
You could also turn off Apache directory listing by replacing the “+” with a “-”, effectively telling Apache, not to list the contents of that directory and all directories below that.
Options +FollowSymLinks
# END :: General Rules
FollowSymLinks tells Apache to follow symbolic links. Wikipedia defines a symbolic link as…
A symbolic link (also symlink or soft link) is a special type of file that contains a reference to another file or directory in the form of an absolute or relative path and that affects pathname resolution.
# START :: Error Documents
ErrorDocument 400 default
ErrorDocument 401 default
ErrorDocument 403 default
ErrorDocument 404 default
ErrorDocument 500 default
# END :: Error Documents
Here, I’m setting all ErrorDocuments to the server default. You could replace ‘default’ with an absolute or relative path to the location of your error documents. You can read more about that here.
http://httpd.apache.org/docs/1.3/mod/core.html#errordocument
# START :: URL Rewrites
RewriteCond %{HTTP_HOST} !^clients.samples\.thewebsqueeze\.com$ [NC]
RewriteRule ^(.*)$ http://clients.samples.thewebsqueeze.com/$1 [R=301,L]
# END :: URL Rewrites
Here, I’m setting a rewrite condition. You can think of it like an “if” statement in PHP. If the URL doesn’t equal ‘clients.samples.thewebsqueeze.com’, with anything on the end, then do whatever the rewrite rule is. In this case, then, redirect them to ‘http://clients.samples.thewebsqueeze.com/’. You’ll want to either delete these lines, or change them to match the location of your fancy directory! You could also alter this to remove or add the ‘www’ for your domain. See below example.
# START :: URL Rewrites
RewriteCond %{HTTP_HOST} !^www\.thewebsqueeze\.com$ [NC]
RewriteRule ^(.*)$ http://www.thewebsqueeze.com/$1 [R=301,L]
# END :: URL Rewrites
Now, this last bit of code is a method of securing our directory’s htaccess file against attacks. Protecting your site’s htaccess file is critical to maintaining a secure environment.
# START :: Strong .htaccess Protection
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
</files>
# END :: Strong .htaccess Protection
You can read more about the above method at Perishable Press.
Now, let’s recap all the code thus far!
# START :: General Rules
RewriteEngine On
RewriteBase /
Options +Indexes
Options +FollowSymLinks
# END :: General Rules
# START :: Error Documents
ErrorDocument 400 default
ErrorDocument 401 default
ErrorDocument 403 default
ErrorDocument 404 default
ErrorDocument 500 default
# END :: Error Documents
# START :: URL Rewrites
RewriteCond %{HTTP_HOST} !^clients.samples\.thewebsqueeze\.com$ [NC]
RewriteRule ^(.*)$ http://clients.samples.thewebsqueeze.com/$1 [R=301,L]
# END :: URL Rewrites
# START :: Strong .htaccess Protection
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
</files>
# END :: Strong .htaccess Protection
So, now we’ve defined some basic rules, and your directory listing should look like mine!

Next, we’re going to get started customizing the htaccess listing! So, what are you waiting for? Let’s go!
Pretty Directory Listing (htaccess)
# START :: Directory Customization
<ifmodule mod_autoindex.c>
Here we are creating an if module which says, if the Apache Module ‘mod_autoindex.c’ is available and installed, then do whatever is inside. You would end that IfModule like so…
</ifmodule>
# END :: Directory Customization
But, let’s not end it just yet. This is going to be the core of our directory listing. So, in-between the starting and ending ‘IfModule’, add the following.
# Set Index Options
IndexOptions IgnoreCase FancyIndexing FoldersFirst NameWidth=* DescriptionWidth=* XHTML HTMLtable SuppressHTMLPreamble SuppressRules SuppressDescription SuppressLastModified SuppressSize IconHeight=16 IconWidth=16 IconsAreLinks
Here we’re setting our directory index options. That’s a lot to undertake, so I’ll go over it piece by piece.
IndexOptions
The IndexOptions directive specifies how Apache handles the directory indexing. You can see all the ‘IndexOptions’ available to you by seeing the Apache documentation.
http://httpd.apache.org/docs/2.0/mod/mod_autoindex.html#indexoptions
IndexOptions IgnoreCase FancyIndexing FoldersFirst
After ‘IndexOptions’ we are setting all the different options for that directory. We are choosing to ignore case for the directory listing. Next, we are applying ‘FancyIndexing’, and setting folders to display before files using the ‘FoldersFirst’ declaration.
NameWidth=* DescriptionWidth=* XHTML HTMLtable
We continue by setting the width of the name and description to ‘*’ which essentially means that it will grow the column to the necessary width in bytes. This means that no line wrapping will happen for longer file/directory names. We then turn on ‘XHTML’, you can leave this out if you are coding an HTML document. After that, we apply an HTML table around the directory listing using ‘HTMLtable’. This allows us to style the table without messing up the columns.
SuppressHTMLPreamble SuppressRules SuppressDescription SuppressLastModified SuppressSize IconHeight=16 IconWidth=16 IconsAreLinks
‘SuppressHTMLPreamble’ removes the starting , and tags allowing you to code that in your header and footer documents below. ‘SuppressRules’ removes the horizontal rule lines (
). We then remove the description (SuppressDescription), last modified date (SupressLastModified), and size columns (SuppressSize). After which, we set the ‘IconHeight’ and ‘IconWidth’ to 16px, and make the icons links. (IconsAreLinks) Continuing on….
# Set Display Order
IndexOrderDefault Ascending Name
Here we set the index order to ascending by the file/folder name. So this means it’s in alphabetical order!
# Specify Header File
HeaderName /i/header.shtml
# Specify Footer File
ReadmeName /i/footer.shtml
This is one of the keys! Here we are setting the location of the header and footer documents. These documents contain the structure of the directory listing. We’re using .shtml so that we can do some server side scripting later on. (Make sure you change the location/name of those documents to where they will be stored on your server.)
# Ignore These Files/Folders
IndexIgnore header.shtml footer.shtml i images cgi-bin favicon.ico .htaccess .ftpquota .DS_Store icons *.log *,v *,t .??* *~ *#
Here we are telling Apache not to display any of the files or folders that follow ‘IndexIgnore’, this is great as it allows you to hide your images directory…etc.
# END :: Directory Customization
Finally, we end the ‘IfModule’. Quickly recapping the above code….
# START :: Directory Customization
<ifmodule mod_autoindex.c>
# Set Index Options
IndexOptions IgnoreCase FancyIndexing FoldersFirst NameWidth=* DescriptionWidth=* XHTML HTMLtable SuppressHTMLPreamble SuppressRules SuppressDescription SuppressLastModified SuppressSize IconHeight=16 IconWidth=16 IconsAreLinks
# Set Display Order
IndexOrderDefault Ascending Name
# Specify Header File
HeaderName /i/header.shtml
# Specify Footer File
ReadmeName /i/footer.shtml
# Ignore These Files/Folders
IndexIgnore header.shtml footer.shtml i _htaccess-code clients.zip images cgi-bin favicon.ico .htaccess .ftpquota .DS_Store icons *.log *,v *,t .??* *~ *#
</ifmodule>
# END :: Directory Customization
Now, we need to add the SHTML documents to the mix. You’ll notice I use some server side scripting, however, I won’t go into detail on that as it’s not the objective of this tutorial.
HEADER.SHTML
< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<!--#if expr="$Request_URI == '/'"-->
<title>TWS Clients :: Choose A Client</title>
<!--#elif expr="$Request_URI == /AOL\/?/"-->
<title>America Online, LLC.</title>
<!--#elif expr="$Request_URI == /Apple\/?/"-->
<title>Apple Inc.</title>
<!--#elif expr="$Request_URI == /Cisco\/?/"-->
<title>Cisco Systems, Inc.</title>
<!--#elif expr="$Request_URI == /Dell\/?/"-->
<title>Dell, Inc.</title>
<!--#elif expr="$Request_URI == /EA\/?/"-->
<title>Electronic Arts, Inc.</title>
<!--#elif expr="$Request_URI == /Google\/?/"-->
<title>Google, Inc.</title>
<!--#elif expr="$Request_URI == /IBM\/?/"-->
<title>IBM, Inc.</title>
<!--#elif expr="$Request_URI == /Logitech\/?/"-->
<title>Logitech, Inc.</title>
<!--#elif expr="$Request_URI == /Microsoft\/?/"-->
<title>Microsoft, Inc.</title>
<!--#else -->
<title><!--#echo var="Request_URI" --></title>
<!--#endif -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" type="text/css" href="/i/style.css" />
<link rel="shortcut icon" href="/i/images/favicon.ico" />
</head>
<body>
<div id="wrap">
<div id="main">
<!--#if expr="$Request_URI == '/'"-->
<h1>TWS Clients</h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#elif expr="$Request_URI == /AOL\/?/"-->
<h1>America Online, LLC.</h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#elif expr="$Request_URI == /Apple\/?/"-->
<h1>Apple Inc.</h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#elif expr="$Request_URI == /Cisco\/?/"-->
<h1>Cisco Systems, Inc.</h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#elif expr="$Request_URI == /Dell\/?/"-->
<h1>Dell, Inc.</h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#elif expr="$Request_URI == /EA\/?/"-->
<h1>Electronic Arts, Inc.</h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#elif expr="$Request_URI == /Google\/?/"-->
<h1>Google, Inc.</h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#elif expr="$Request_URI == /IBM\/?/"-->
<h1>IBM, Inc.</h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#elif expr="$Request_URI == /Logitech\/?/"-->
<h1>Logitech, Inc.</h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#elif expr="$Request_URI == /Microsoft\/?/"-->
<h1>Microsoft, Inc.</h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#else -->
<h1><!--#echo var="Request_URI" --></h1>
<h3 class="location">Location: <!--#echo var="Request_URI" --></h3>
<!--#endif -->
FOOTER.SHTML
<p>Icons By: <a href="http://www.famfamfam.com/lab/icons/silk/">FAMFAMFAM</a></p>
<p>© Copyright 2009 <a href="http://www.thewebsqueeze.com/">The Web Squeeze, LLC.</a><br />All Rights Reserved.</p>
</div>
</div>
</body>
</html>
STYLE.CSS
html, body, div, span, applet, object, iframe,
header, footer, nav, section, article, aside,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, font, img, ins, kbd, q, s, samp,
small, strike, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin:0;
padding:0;
border:0;
outline:0;
font-weight:inherit;
font-style:inherit;
font-size:100%;
font-family:inherit;
vertical-align:baseline;
}
body {
background:#469bfc;
color:#333;
font-family:Tahoma, Geneva, sans-serif;
width:100%;
float:left;
padding:0 0 30px;
}
#wrap {
width:360px;
margin:30px auto 0;
}
#main {
width:300px;
float:left;
padding:30px;
background:#fafafa;
border:6px solid #007ede;
}
h1 {
font: 2.0em Georgia, serif;
text-align:center;
color:#78D316;
}
h3.location {
font-size:13px;
font-weight: bold;
margin:12px 0 30px;
text-align:center;
color:#4D7EC7;
}
a:link, a:visited {
text-decoration: none;
color: #024591;
}
a:hover, a:active {
text-decoration: underline;
color: #006be6;
}
table {
width:100%;
padding:0;
margin:0;
border:0;
}
tr {
width:100%;
padding:0;
margin:0;
border:0;
}
tr:nth-child(even) {
background:#def2ff;
}
th {
display:none;
}
td {
height:20px;
padding:10px;
margin:0;
}
td:nth-child(1){
width:16px;
}
hr {
display:none;
}
p {
margin:20px 0 0;
font-size:14px;
text-align:center;
}
Your directory listing should look like mine now!
![]()
But, what about the icons? Well, continue on to the next part!
Adding Custom Icons
Almost all of the icons used for directory symbols were downloaded from FAMFAMFAM. You can download the Silk Icon set below.
http://www.famfamfam.com/lab/icons/silk/
Once you’ve downloaded the icons, your ready to start! Find the following section of code.
# END :: Directory Customization
Above the end ‘’ add the following lines of code.
# START :: DEFINE FILE & FOLDER ICONS
# Default Icon
DefaultIcon /i/images/icons/resultset_next.png
# Folder/Directory Icon
AddIcon /i/images/icons/folder.png ^^DIRECTORY^^
# Up a directory
AddIcon /i/images/icons/arrow_undo.png ..
Again, I heavily commented each line, thereby making it easier to update later. Basically, I’m defining a default icon for files, and a default icon for directories. After which we define the icon used to “Go Back”, or up a directory.
# Directory Icons
AddIcon /i/images/client-icons/aol.png AOL
AddIcon /i/images/client-icons/apple.png Apple
AddIcon /i/images/client-icons/cisco.png Cisco
AddIcon /i/images/client-icons/dell.png Dell
AddIcon /i/images/client-icons/ea.png EA
AddIcon /i/images/client-icons/google.png Google
AddIcon /i/images/client-icons/ibm.png IBM
AddIcon /i/images/client-icons/logitech.png Logitech
AddIcon /i/images/client-icons/microsoft.png Microsoft
Now I’m setting custom icons for my main directory listing. You set a custom icon in the following format….
AddIcon /location/to/graphic.png FILE-NAME
So, you see how I assigned icons to certain folders, but what about file formats? You don’t want to have to assign an icon to every mp3 file using the above method. Here’s a method to assign an icon to file formats.
# START :: DEFINE FILE FORMAT ICONS
# PDF Documents
AddIcon /i/images/icons/book_open.png .pdf
# Word Documents
AddIcon /i/images/icons/page_white_word.png .txt .doc .rtf .log .asc
# Pictures
AddIcon /i/images/icons/picture.png .jpg .jpeg .jpe .png .gif .mpg .ico .psd
# Music
AddIcon /i/images/icons/music.png .mp3 .wav .vox .wma .ra .ram .ogg .vqf .aac
# Video/Movies
AddIcon /i/images/icons/film.png .mov .avi .wmv .mpeg
# HTML
AddIcon /i/images/icons/html.png .html .htm .shtm .shtml
# XHTML
AddIcon /i/images/icons/xhtml.png .xhtml
# CSS
AddIcon /i/images/icons/css.png .css
# PHP
AddIcon /i/images/icons/script.png .php
# ASP / JavaScript
AddIcon /i/images/icons/script.png .asp .js .xml
# Flash
AddIcon /i/images/icons/page_white_actionscript.png .swf .fla .as
# Compressed Documents
AddIcon /i/images/icons/page_white_zip.png .zip .rar .gz .bz2
# Disk Image
AddIcon /i/images/icons/drive_web.png .iso .rpm
# Torrent Files
AddIcon /i/images/icons/application_lightning.png .torrent
# END :: DEFINE FILE FORMAT ICONS
This basically works the same way.
AddIcon /location/to/graphic.png .FILE-TYPE
Again, all the icons are from the Silk Icon set by FAMFAMFAM. You can download them and view them here.
http://www.famfamfam.com/lab/icons/silk/
http://www.famfamfam.com/lab/icons/silk/previews/index_abc.png
You can also add file and folder descriptions using this format.
# START :: File Type Descriptions
AddDescription "<span class='description'>Music/Sound File</span>" .mp3
AddDescription "<span class='description'>GZIP compressed TAR archive</span>" .tgz .tar.gz
AddDescription "<span class='description'>GZIP compressed archive</span>" .Z .z .gz .zip
......etc.....
# END :: File Type Descriptions
That adds a description for certain file types, with a span class around the description. You can also target certain directories or files.
# START :: Folder Descriptions
AddDescription "[<span class='description'>Go Back..</span>]" ..
AddDescription "[<span class='description'>American Online, LLC.</span>]" AOL
AddDescription "[<span class='description'>Apple Inc.</span>]" Apple
AddDescription "[<span class='description'>Cisco Systems, Inc.</span>]" Cisco
AddDescription "[<span class='description'>Dell Inc.</span>]" Dell
AddDescription "[<span class='description'>Electronic Arts, Inc.</span>]" EA
AddDescription "[<span class='description'>Google, Inc.</span>]" Google
AddDescription "[<span class='description'>IBM, Inc.</span>]" IBM
AddDescription "[<span class='description'>Logitech, Inc.</span>]" Logitech
AddDescription "[<span class='description'>Microsoft, Inc.</span>]" Microsoft
# END :: Folder Descriptions
You can also add a default description for other “unknown” file types/folders by using a wildcard.
# Default Description
AddDescription "<span class='description'></span>" *
Apache Directory Listing Gallery
I didn’t have time to cover all of the possible options you can use when styling your custom Apache directory listing, however, I hope the samples I designed will help you!
http://samples.thewebsqueeze.com/directory-listing/
Clients Listing
Media Listing
Linux Mirror
You can view all the designs, and download the code here.
http://www.thewebsqueeze.com/samples/directory-listing/
If you have any questions, ask them below. Now, go out a design your own fancy directory listings and post them in the comments section below!





