TextMate Rocks

August 11, 2009

If you are running Mac OS X and doing any kind of development (Ruby, Rails, HTML, CSS, Javascript, C++, whatever) I highly recommend looking into getting TextMate.  A friend of mine bought a license as a birthday present for me some number of years ago and I had only used it sporadically.  As of late though I have started using it for everything!  It is truly fantastic and worth whatever they charge you for it.

My favorite feature?  Built in CSS/HTML W3C validation.  You would be surprised how many of your CSS bugs that you are quick to blame on browser deficiencies are actually a result of your invalid CSS :/


Separating Content from Presentation with HTML and CSS

August 11, 2009

With brockbouchard.net I have tried to take separation of presentation and content to an extreme, with the CSS Zen Garden serving as a primary inspiration.  That is to say the HTML generated by my Rails views contains only the content of my pages, with minimal structural markup.  The appearance of the site (colors, layout, fonts, etc) is controlled entirely by CSS.

What are the benefits of doing this? There are many:

  1. A professional graphic designer can totally retool your site’s design in a manner limited only by his or her imagination and knowledge of CSS.  Your interaction from a programming perspective with the designer is very little if not zero!
  2. With the focus of your HTML being solely content and structure, it is easier to appreciate and focus on the semantic statement that your markup is making about your content to search engines.  For example, search engines will look for titles to be in <h1>, <h2> and <h3> header tags, and menus to be in a <ul> list.  With CSS you can then go wild as to how an <h1> or <ul> tag is displayed.  Your header for example, could have its text hidden in order to show a background image representing your site’s header.  And the <ul> containing your site’s menu can be altered to display horizontally or vertically, and without list item markers.  This is indeed how brockbouchard.net was designed.
  3. Your site will behave nicely if loaded by a primitive browser that does not support CSS.  Indeed this is a less of a concern with the ever growing use of smartphones with full-featured browsers.  However, there are still many ordinary phones with internet access that feature a limited browsing environment.  A pure-content HTML site will render nicely in this scenario without the need for a special mobile version of the site.

How do we go about doing this? Let’s look at the basic structure of brockbouchard.net as an example.  Below is the basic HTML layout of the site, minus some of the actual information I display:

<!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>
<title>My Title</title>
	<link href="styles.css" media="screen" rel="stylesheet" type="text/css" />
</head>

<body>
<div id="container">
<div id="header">
<h1><a href="/" title="My Website"><span>My Website</span></a></h1>
</div>
<div id="menu">
<ul>
	<li id="Home"><a href="/home" title="Home"><span>Home</span></a></li>
	<li id="Contact"><a href="/contact" title="Contact"><span>Contact</span></a></li>
	<li id="Projects"><a href="/projects" title="Projects"><span>Projects</span></a></li>
	<li id="Blog"><a href="/blog" title="Blog"><span>Blog</span></a></li>
	<li id="Resume"><a href="/resume" title="Resume"><span>Resume</span></a></li>
</ul>
</div>
<div id="content">
<h2 class="pageTitle">Welcome</h2>
<div id="contentForLayout">
Content goes here</div>
</div>
<div id="footer">
Pick a theme:
<a href="?theme=theme1" title="Theme 1">Theme 1</a> |
<a href="?theme=theme2" title="Theme 2">Theme 2</a></div>
</div>
</body>

</html>

Some things to notice:

  1. The placement of <div> and <span> tags, along with the ids and classes associated with them, are totally arbitrary and up to you as the programmer.  Just because I have a <div> tag named “footer” doesn’t mean that <div> has to appear at the bottom of the page.  You could use CSS to place your “footer” anywhere!
  2. Think of the use of <div> and <span> tags as “hooks” for finer grained control inside of CSS.  While you don’t want to go crazy placing <div> and <span> tags everywhere, in some cases you will find it helpful.  In my case, I used <span> tags inside of my <a> tags as I wanted my menu links to appear as images I had designed in Illustrator.  However, I found that with some browsers the only way to make the text of the link totally disappear and give way to the image was to put the text inside of a <span> tag and hide that.  Unfortunately applying “font-size: 0″ to <a> tags in my CSS was not working on all browsers and platforms!
  3. I put links at the bottom of the page illustrating how the theme could be changed.  In my case, I have my Rails Application controller check to see at the beginning of all requests if a “theme” parameter is specified.  If so, the theme name is stored in a session variable (with the session variable defaulting to the default theme name).  Then, in my view where I spit out the <link /> tag for the style sheet, I choose which style sheet to use based on the theme name.

How about the CSS? While I can’t post all of the CSS here, here are some of the highlights.  If you want to see how I did everything then feel free to go to brockbouchard.net, view the source, then follow the link to my style sheet.

#container
{
	/* this makes the page a fixed width and centers it */
	margin-left: auto;
	margin-right: auto;
	width: 980px;
}

#header
{
	margin: 0px;
	/* this corresponds to the size of the header image */
	width: 980px;
	height: 90px;
	background-image: url("/images/main/theme1/header.jpg");
	background-repeat: no-repeat;
}

#header h1
{
	padding: 0px;
	margin: 0px;
	width: 100%;
	height: 100%;
}

#header h1 a
{
	/* these rules make the link inside of the header take up the entire space of the header */
	/* thus this makes the header a clickable link */
	display: block;
	width: 100%;
	height: 100%;
	text-decoration: none;
	border-width: 0px;
	margin: 0px;
	padding: 0px;
}

#header h1 a span
{
	/* hide the text inside of the header link */
	/* doing "font-size: 0" for the <a> does not work across all browsers */
	visibility: hidden;
}

#menu
{
	margin: 0px;
	/* the menu is rendered as all one image */
	/* the size of the menu items defined below defines the clickable area for each menu item */
	background-image: url("/images/main/theme1/menu.jpg");
	background-repeat: no-repeat;
	/* this corresponds to the size of the menu image */
	width: 980px;
	height: 45px;
}

#menu ul
{
	/* this corresponds to the size of the menu image */
	width: 980px;
	height: 45px;
	margin: 0px;
	padding: 0px;
	list-style-type: none;
}

/* this is the necessary CSS to turn list items into invisible, clickable areas over the menu image */

#menu ul li
{
	position: relative;
	display: block;
	height: 40px;
	top: 0px;
}

#menu ul li a
{
	display: block;
	width: 100%;
	height: 100%;
	text-decoration: none;
	border-width: 0px;
	margin: 0px;
	padding: 0px;
}

#menu ul li a span
{
	visibility: hidden;
}

#HomeMenuItem
{
	/* something like this would be repeated for each menu item with the appropriate width filled in */
	float: left;
	width: 104px;
}

#HomeMenuItem a:hover
{
	/* change the appearance of the menu item when the user hovers over */
	/* would need to do something similar for each menu item */
	background: transparent url("/images/main/theme1/home_hover.jpg") no-repeat scroll top left;
}