How to Make a Website

A Comprehensive Guide to Building a Website From Scratch Born Out of My Frustration Trying to Answer the Simple Question: How Do I Make a Non-Stupid Website? Includes Notes about How This Website Was Built and Source Code
by Oliver; Jan. 13, 2014
       
css
         
web
 

Introduction

This article is no longer up to date


Since just about everything in the world is getting sucked—Matrix-like—online, knowing web-design is an increasingly useful skill to have. Although you can find a zillion well-written tutorials teaching HTML, CSS, and javascript down to almost infinite granularity (e.g., W3Schools), from my perspective surveying the scene as a total beginner there seemed to be a lack of comprehensive guides showing you how to put everything together—the big picture. Given the innumerable approaches to this problem, each supported by a different faction in Google's search results, which path do you take? This article was born out of my frustration trying to answer the simple question: how do I make a non-stupid website? In the flood of information online, I had a lot of questions that I couldn't find the answer to in any one place. For example,
  • Where do you begin?
  • What are the best-practices?
  • HTML is merely a markup language, so how do you start programming your site?
  • What's a static versus a dynamic website?
  • How do you structure your site, its code, and the directories that underlie it?
  • Should you use a fancy content management system, like Drupal or Wordpress, a web framework, like Rails or Django, or can you make something just as good going it alone?
  • How can you host your website?
Before you read any further, if you just want to get a personal webpage up, the quickest way to do so is with one of the well-known blogging sites, like Google Blogger, Tumblr, or WordPress. What follows is an amateur, DIY guide to making a site from scratch, which is far more time-consuming but also gives you more freedom and—to some extent—prevents the big companies from owning and profiting from your data. It's a wonderful way to learn, too. If you don't want to follow my slog from ignorance to nirvana, the common sense conclusion I reached is that using a web framework is indeed the way to go. But note that the all-important question of which technology to use resists a one-size-fits-all answer (see the next section). In the last part of this article, I discuss how this website was built and include some of the source code.

What Technology Do I Use Again?

Technology's always on the move and hard to pin down but, surveying the scene of as 2014, I see Google Blogger, Tumblr, WordPress, Amazon Web Services, Drupal, Rails, Django, Flask, Nodejs, Angularjs, Backbonejs, Emberjs, Bootstrap, Heroku, jQuery. WTF! Appropriate reaction: crawl into a Saddam-style spider hole, belly up, and die. The items in this list are not in a single category but, still, how do you pick your battle in this overwhelming and overpopulated landscape? If you simply want a blog, as we remarked in the last section, just go with WordPress or Google Blogger and dispense with any coding. If you want to program a web application, one important consideration we'll discuss below is whether your code should run on the client-side or the server-side.

If you can get away with it, running things on the client-side—with "the lingua franca of the web" Javascript/jQuery—is very appealing because it's independent of how your backend server looks and any package dependencies or installations. The scripts are simply downloaded onto the client's computer and his web browser executes the code for you (two interesting consequences of this fact are that (1) the app will work sans internet connectivity and (2) the client receives the entire source code). However, this is not always feasible. If your page needs to, say, access a large database of articles or product descriptions or anything else, you can't download this onto the client's computer everytime he visits your webpage. In this case, a web framework like Rails or Django is what you should use, which is the storyline this article develops. These frameworks run code on the server-side, which means you, the client, are controlling programs running on a remote computer somewhere. Contrast this app, which calculates the distance between airports, with this one, which performs calculations for a particular HIV assay based on user input. Can you guess which app is all (client-side) javascript and which app is running (server-side) Django? Hint: which one needs access to a lot of data the user isn't supplying? Read more about the airport app.

Let's introduce another layer of complexity. What if you're an entrepreneur looking to make an app that will, you hope, have a large user base? An important question beyond the scope of this article is, how will your website scale? Will it handle traffic from 1,000 users just as well as it handles traffic from 100 users? I haven't used Heroku myself, but I know that many start-ups favor it for its reputedly hassle-free scaling and git-based code deployment. This is the approach explored in Coursera's excellent Startup Engineering (Stanford) by Balaji S. Srinivasan and Vijay S. Pande (I have a short post about it here).

There's no single answer to the What Technology? question, but I hope this provides a little bit of orientation in this deluge of choices—back to the basics now!

A Problem with Many Facets

Making a website is a problem that contains many distinct sub-problems. One of these hydra heads is how it comes into existence in the first place. That's something along the lines of:
Server (hardware) --> HTTP Server (software) --> Your Website
If you're going to do this 100% from scratch, you can't even think about making a site until you've gotten over the first two hurdles. In practice, a server is a computer that's always on, and thus able to serve up your website any time someone requests it. A wise choice is outsourcing this task to a company you trust can handle it, like Amazon Web Services. You can read a thorough account of how I set up mine at How to Host a Website on the Amazon Cloud (AWS). An HTTP Server is a program, such as Apache, that transforms that machine that's always on—your hardware server—into something able to host pages. You can read about one approach to this problem at Setting Up Nginx, uWSGI, and Django on Amazon's EC2. I'll assume you've already done these two things and focus on the last piece, your website.

It's useful to consider a website in terms of three independent categories:
  • The Code
  • The Graphic Design
  • The Content
The code, this article's concern, is really important to you but only indirectly important to the user in so far as he feels its effects. The graphic design—the look and feel of your pages and their layout—is an art problem. Although it's non-technical, the category lines blur a little here and some of it has to be translated into code. The most important thing, of course, is your content which (ideally) sits atop your well-engineered and aesthetically-appealing site. In so far as possible, you should keep these three components decoupled to embody the computer science principle of modularity: in the future you can freely change any one because they're not irreversibly stewed together.

HTML, CSS, JS, and the Long Ingredients List of a Website

A difficulty for new website builders is the same one we ran into last section: multifacetedness. The simplest websites use only HTML. If all you need is a glorified text file—think of a placard with words and pictures floating in cyberspace—it will suit your purposes very well. However, most basic websites use a combination of three languages which you need to learn merely to get your foot in the door:

HTML

HTML is the main actor and the other two are helpers. As we've said before, it's a relatively simple markup language. This means an HTML file is basically just a text file, with special tags around certain words to mark them up—say, make them italic or reference a web link. A supremely important point is that HTML is not a programming language. This is frustrating if you're used to basic human-rights like variables, conditional logic, loops, and functions. What would be elementary in other languages, like the principle "Thou Shalt Not Repeat Code", suddenly becomes hard in HTML. It's an accident of the web's evolution that HTML still has the central role that it does, and a lot of web programming seems to be overly complicated because it's trying to turn this simple tag language into a dancing marionette. If the web had been invented last year, it would definitely not have been entrusted to such a primitive standard-bearer. How else to explain why you need three languages for a garden-variety website? The lack of self-sufficiency demonstrates that it was not designed from first principles with efficiency in mind. For sophisticated websites, "real code" whirs away in the background and translating everything into HTML is the last step. Yet the lack of variables, logic, and loops is still so problematic that modern web designers have added these things into HTML by creating templating languages, as you can see with the Django template language or Embedded Ruby (ERB) in Rails. HTML is excellent as a pure markup language, and you can't not know it. Just be aware of exactly where it sits in the web programming ecosystem. It does not and cannot hold the whole web on its shoulders. I've included a short HTML primer below.

CSS

CSS is the language of aesthetics. You can use it to set the layout of your page as well as to set the font, line-spacing, background color, etc. of various content blocks. You can assign a unique id or a non-unique class to any HTML tag and this is CSS's entry point into the picture. CSS has a lot of quirks and is unlike most other languages. It gets tricky surprisingly fast. You can read more about CSS in the primer below.

Javascript

Javascript—or jQuery, a pre-digested, self-sufficient Javascript library—is like pixie dust. Sprinkle it on your website and magic happens: menus can pop up, text can shrink, pictures can animate, and so on. We'll talk more about dynamic websites below, but javascript is one way of making your page dynamic. Javascript is client-side scripting, as opposed to server-side scripting, which is to say your javascript runs on the user's computer, not your server's. Javascript excels at programming stuff on a given webpage—manipulating HTML tags by type, id, or class. But it's not useful for the other thing people associate with the word dynamic, site-wide structural programming. There's a very small jQuery primer below.

Only three languages, you say—that's not bad. However, to make a more advanced website you have to know still more—at least one conventional programming language, like Python, and a database language, like MySQL. That's five!

HTML Primer

If you're new to HTML, W3Schools is a good place to start, as always:

HTML tags example

Mark up is surrounding text with tags to give it additional properties. It's easy. For example, the following code:
<p>This line is within paragraph tags.</p>
<p><i>This</i> is italic.</p>
<p><b>This</b> is bold.</p>
<h1 id="myHeader">This is a header</h1>
<p><a href="http://www.nytimes.com">This is a link to The New York Times</a>.</p>
<p><a href="#myHeader">This is an <i>internal page link</i> to 
the tag with id == myHeader</a>.</p>
will produce:

This line is within paragraph tags.

This is italic.

This is bold.

This is a header

This is a link to The New York Times.

This is an internal page link to the tag with id == myHeader.

The tags we used are elementary:
  • <p>   paragraph
  • <i>   italics
  • <b>   bold
  • <h1> header 1
  • <a>   link
Note that the <a> tag can link to other webpages or to locations within your page if you give it "#someID" as a reference (more about IDs in a minute).

There are on the order of 100 other HTML tags. You can see a complete list here: New tags come in and certain old tags get deprecated as new versions of HTML are released.

Class, id, and the <div> tag

The <div> tag is particularly useful. It doesn't do much on its own (div stands for "division") and is therefore perfect to use as a wildcard to do what we like with. It really comes into its own when you give it a class or an id. What are these? Tags can be assigned to a class, which groups a bunch of distinct tags into the same category, and given an id—used to mark elements uniquely. A <div> tag might look something like this:
<div id="myid" class="myclass"></div>
Both CSS and javascript can manipulate elements by class and id, as well as by tag type. For example, some HTML in our page's body might look like this:
<div class="text1"> We can style this text one way </div>
<div class="text2"> and style this text another way </div>
<div class="text3"> because they belong to diff classes </div>
class and id are an all-important bridge from the world of simple mark-up to the world of programming.

HTML page structure

The bare-bones structure of an HTML webpage looks like the following:
<!DOCTYPE html>

<html>
	<head>
	</head>

	<body>
	</body>
</html>
Inside the <head> tag is where you set the title of your page, link javascripts and CSS stylesheets, and so on. The <body> tag is where the code for the page the world will see resides.

HTML reserved characters

HTML has a set of reserved characters you cannot use, most notably:
  • &
  • >
  • <
These are instead written as:
  • &amp;
  • &gt;
  • &lt;
respectively. There's a full list of HTML codes for special and reserved characters at:

HTML whitespace

By default, HTML doesn't see carriage returns and, if you want more than one whitespace, you have to use the special code &nbsp;. For carriage returns use the unpaired tag <br>.

Where do the HTML files which create your webpage reside on your computer?

One final point: you've written an HTML file, but who decides if this file will be rendered into a website? This is a matter for your HTTP server—e.g., Apache—to decide. In a basic setup, you'll choose a folder out of which to serve web content. This information will be in your HTTP server's configuration file. Then, by longstanding convention, when you go to your web address, it will look in this folder for a file called index.html and that's what it will serve.

CSS Introduction

You can make a stylesheet anywhere in your directory structure—say, in a folder called styles—and link to it in your <head> tag:
<link rel="stylesheet" type="text/css" href="/path/styles/mystyle.css" />
In CSS, the symbol # refers to an HTML tag's id, while the symbol . refers to its class. Referring again to our <div> tag:
<div id="myid" class="myclass"></div>
in mystyle.css we can say:
#myid
{
	/* my styles for the element of id == myid */
}

.myclass
{
	/* my styles for any element of class == myclass */
}
The unique div tag with id="myid" will be styled according to the first block of instructions. And any div tag that has class="myclass" will be styled according to the second block. To make this concrete, suppose we want three different font styles in our document. We might do something like this:
.text1
{
        /* page header style */
        font:72px bold arial,sans-serif;
        padding: 15px;
}

.text2
{
        /* left sidebar style */
        font:10px arial,sans-serif;
        padding: 5px;
        color: blue;
        border:1px solid rgb(200,200,200);
        background: yellow;
}

.text3
{
        /* main text style */
        font:12px times;
        line-height: 24px;
}
We can also style HTML tags directly, even if they don't belong to a class or have an id. For example, if we wanted to style all <p> tags:
p
{
	/* my styles for all HTML p tags */
}
It's more common to work with class and id, however, because this doesn't allow us much flexibility.

CSS supports inheritance. We can style particular HTML tags that appear in our classes, adding to the style they already get by being members of the class. For example, we could add specific style rules for all the paragraph elements (<p>) in myclass.
.myclass
{
	/* my styles */
}

.myclass p
{
	/* extra style for paragraph elts in myclass */
}
We can also nest multiple user-defined classes. The syntax is:
.myclass.myclass2
{
	/*  
	Here we've defined multiple classes.
	This style will apply to anything with
	class="myclass myclass2"
	*/
}
For a more extensive introduction, see

CSS Layout Primer

Now for the hard part: page layout. Here are some important CSS concepts governing this.

Display

Display is a property with three especially useful values:
display: inline
display: block
display: none
inline and block are roughly what they sound like: inline elements go in a line, as if you're adding words to the end of a sentence. A block element, on the other hand, will force a carriage return. Compare inline display:
a a a
to block display:
a
a
a
By default, the <div>, <p>, and <h1> tags display as blocks, while the <i>, <b>, and <span> tags display inline.

Dimensionality and the box model

Once you've created a content block, you can set its dimensions explicitly, as in:
height: 500px;
width: 200px;
In most circumstances, if you don't specify this the block will stretch around the child elements it contains, automatically sizing itself.

As you consider your content block, note the Box Model, which explains how CSS interprets properties like margin, border, and padding. This picture from W3Schools is key:

image

A point that sometimes causes confusion: as the picture shows, margin defines the space outside your element.

Normal document flow

Normal document flow is the natural state of affairs in which elements are aware of each other's existence and behave accordingly. If you type an a, for example, followed by a b, the letters will be next to each other rather than superimposed on one another. In CSS, however, giving elements certain attributes will take the elements out of normal document flow, which means other elements will behave as if they don't exist and things can overlap. For example, assigning an element the attribute position: absolute will take it out of document flow.

Position

The CSS position property can take on values like:
position: static	
position: relative
position: absolute
position: fixed
position: static is the status quo, while position: fixed fixes the position of an element relative to the browser window. The menu on the left sidebar of this webpage (with HOME, Full Sitemap, etc.) is using the fixed effect. position: relative gives the element an offset relative to where it would normally be, and position: absolute sets the offset relative to the containing element. You use these position attributes in combination with specifications about the offset:
top: 5px
bottom: 5px
left: 5px
right: 5px
I found an excellent discussion of relative and absolute positioning in an article called "Web Design 101: Positioning" in Digital Web Magazine. Since neither the magazine nor the article seems to exist anymore, I'll quote it here:
Relative Positioning

The position of an element with position:relative is, as has been mentioned, relative to itself. This may sound odd, but it can be rather useful once you grasp the concept.

This is how it works, in layman’s terms: The box generated by the element is laid out just as it is for static elements. Then the rendered box is shifted horizontally and/or vertically, according to the values of the top, right, bottom, and left properties. But here’s the tricky part—as far as the rest of the document is concerned, the box is still in its original place! It is laid out where it should be, and it will occupy that position in the document flow. It’s only the rendered box that is shifted, relative to that original position. If we move it a large distance, we will leave a hole in the document. This means that position:relative is utterly useless for things like column layout. It is normally only useful for nudging an element a few pixels or so. Does this mean we can forget about position:relative? Not at all. In fact, it has a side effect that makes it very valuable, indeed, which we will get to in a moment.

Absolute Positioning

Absolute positioning can be quite useful, even for laying out columns. It has its drawbacks, though. An element with position:absolute is removed from the document flow, which means the rest of the document acts as if the element weren’t there. It won’t affect subsequent elements. Instead, it could end up layered over other elements, unless we make sure it doesn’t. (Sometimes we want that to happen, of course, for example for pop-ups without JavaScript.)

With absolute positioning, the top, right, bottom, and left properties apply in a very different way than for relatively positioned elements. They now specify the positions of the four edges of the generated box. The values can be specified with length units, such as top:50px or left:-8.5em. They can also be specified in percents, in which case it gets slightly more complicated. A percent value for top and bottom refers to a percentage of the height of the containing block, while for right and left it refers to the width of the containing block.

What is a containing block? I’m glad you asked… It sounds like one of those boring technical details that only real nerds pay any attention to, doesn’t it? To be honest, it is a boring technical detail, but unfortunately we have to understand it. The containing block is extremely important when we use absolute positioning.

Take a look at what the CSS 2.1 specification has to say about containing blocks:

If the element has ‘position: absolute’, the containing block is established by the nearest ancestor with a ‘position’ of ‘absolute’, ‘relative’ or ‘fixed’ ... If there is no such ancestor, the containing block is the initial containing block.

OK, the containing block for an absolutely positioned element is the nearest positioned ancestor. An ancestor is a parent element or a grandparent, and so on. If none of the ancestors is positioned, the containing block is some mythical entity called “the initial containing block”, about which the specification has the following to say:

The containing block in which the root element lives is chosen by the user agent. (It could be related to the viewport.) This containing block is called the initial containing block.

Very helpful, isn’t it? The root element in any HTML or XHTML document is the html element. So the initial containing block is like the parent of the html element, whatever that is. The specification starts flapping at this point and mumbles about “chosen by the user agent” and “could be related to the viewport.” In W3C lingo, user agent is (in most cases) what we mere mortals call a browser, and viewport means browser window.

In other words, we can assume that if there is no positioned ancestor for an absolutely positioned element, the containing block is the document itself.

If we look closer at the first quotation, we will discover that interesting side effect of relative positioning I mentioned earlier: apparently, a relatively positioned element becomes the containing block for any absolutely positioned children. That is extremely useful to us, because that allows us full control over our containing blocks.

If we want to position an element absolutely, but with respect to some other element, all we have to do is make that other element (or a common ancestor) be our containing block. We can now achieve that easily by setting position:relative on it. We don’t have to specify any movement at all. The containing block doesn’t move, it just becomes a containing block. Nice and simple, eh?
Reading this discussion, you can start to appreciate why CSS is hard: it's full of subtleties and the interplay between attributes is complex.

Float and clear

CSS float is an attribute that usually takes on the values:
float: left 
float: right
Floating an element will either kick it as far left or right as it can go within its containing block. The floating attribute does not take elements out of normal document flow, which makes it very useful. About the clear attribute, W3Schools says: "Elements after the floating element will flow around it. To avoid this, use the clear property." It has a great example, which I'll copy here verbatim:
img
{
	float:left;
}

p.clear
{
	clear:both;
}
<img src="logocss.gif" width="95" height="84" />
<p>
This is some text.  This is some text.                                                                                
This is some text. This is some text.
This is some text. This is some text.
</p>
<p class="clear">
This is also some text. This is also some text.                                                                                               
This is also some text. This is also some text.                                                                                               
This is also some text. This is also some text.                                                                                               
</p>
produces:
image

Getting started - making container blocks

The first step is to block out your page. There's a nice set of templates here: which are great for modifying. As you experiment with layout, it's useful to give all of your container blocks borders so you can see how they behave. For example, on this site:

image

You can see we've made an outer container block, which circumscribes our universe: everything outside it is background and everything inside it is our page. It's:
#container
{
	margin: 2px auto 2px auto;
	width: 1000px;
	background: #fff;
}
By adding a width property, we've made our page fixed-width—that is to say, the internal content blocks won't accordion if the user changes the window size. I like fixed-width pages—nytimes.com is a good example—because you have complete control over the appearance. Remember: if we don't specify width our container will auto-size to fit its child elements. Adding the margin property (it goes in the order top, right, bottom, left) with auto on both sides means our page will always be centered in the browser window. Inside our container, you can see numerous blocks forming sub-divisions. There's a header, a left sidebar, a content container, a right sidebar, and so on.

Examples of CSS weirdness

To a beginner like me, the business of positioning in CSS often seems finicky. Let me give you two examples of random CSS problems that you might not anticipate, via Stackoverflow. The first is that if you use absolute positioning for a container block, you'll run into the issue that it won't re-size to fit the child elements you put inside it. See the discussion here: which notes:
Absolutely positioned elements do not count towards the container's contents in terms of flow and sizing. Once you position something absolutely, it will be as if it didn't exist as far as the container's concerned, so there's no way for the container to "get information" from the child through CSS. If you must allow for your scroller to have a height determined by its child elements without Javascript, your only choice may be to use relative positioning.
My solution is to never use absolute position for a container block—it's not worth the headache.

Another problem that could blindside you is that, if a container block without explicit size has child elements which all float, the container will "collapse". There's a discussion about it here: which notes:
Although elements like <div>s normally grow to fit their contents, using the float property can cause a startling problem for CSS newbies: if floated elements have non-floated parent elements, the parent will collapse.
These and other tripwires are awaiting you in CSS.

jQuery Primer

jQuery, a user-friendly incarnation of Javascript, is more like a conventional programming language than either CSS or HTML and it has a great online API. Thus, I'll keep this discussion really short. As with your CSS stylesheet, you link to your javascript in the <head> tag. To import jQuery use:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>

$(document).ready()

One of the most useful parts of the jQuery suite is the ready() function, often invoked as:
$(document).ready(function(){ })
As the manual says,
A page can't be manipulated safely until the document is "ready." jQuery detects this state of readiness for you.
It's typical to put all the functions you, the programmer, write inside ready() so the top of your webpage might look something like this:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" src="/path/myscript.js"></script>

<script> 
$(document).ready(function() {
	// these are functions defined in myscript.js
	// to be executed once the document is ready:
	function1();
	function2();
	// and so on
}); 
</script>
while your myscript.js would look like this:
function1()
{
	// my javascript
}

function2()
{
	// my javascript
}

Selecting Elements

As we've remarked, jQuery is a full-fledged language with variables, logic, functions, and all the rest, too big to cover here. I just want to state a couple other basic things you should know about it. The first is, you can select elements based on id and class. For example, this code snippet would select the element of id == someid and all the elements of class == someclass and invoke the hide() function on them:
$('#someid').hide()
$('.someclass').hide()
Thus jQuery gives you great power to manipulate the elements on your page. Be sure to check out the indispensable library of event functions at such as click(), keypress(), and mouseover(), which allow you to bind event handlers to elements that fire when the user does specific things in the browser.

Debugging

Something else you want in your bag of tricks is the ability to debug by printing the value of variables, or whatever you like, to your web browser's Error Console. To see your console in Safari, go to the menu Develop > Show Error Console:

image

Here's the jQuery to print hello to the console:
console.log("hello");

DOM

jQuery sometimes refers to the Document Object Model (W3Schools Entry), or DOM. This is a way of thinking about your page as a tree: The <html> tag is the root, and probably contains the two branches <head> and <body>, which contain other branches, and so on.

You can see a more involved example of jQuery in the source code included at the end of this article.

An Example Webpage Using HTML, CSS, and JS

Without an example to crystallize what we've just covered, this article would be impotent. If you have a Macintosh, you can mock up a web page in any folder you like. You don't even need internet connectivity—just create an .html file and drag it onto Safari to see it. I've created three sample files, test.html, test.css, and my_functions.js, and I use one 100 pixel-width image file I stole from Google Images called hellokitty.jpeg:

image

The following are from a website I tried to make a year ago and, reviewing it today, I see a lot of room for improvement, especially in the coding of the CSS layout. The point of including it here is so you can see how HTML, CSS, and JS play together. Here are the files:

test.html

(you can scroll down within the following box)
<!DOCTYPE html>
<html>

<head>
	<title>My Homepage</title>

	<!-- define character set -->
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 

	<!-- favicon -->
	<link rel="icon" type="image/ico" href="images/favicon.ico"/>
	
	<!-- my styles -->	
	<link rel="stylesheet" type="text/css" href="test.css" />
	
	<!-- jQuery -->	
	<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js" 
	charset="utf-8"></script>

	<!-- my scripts -->
	<script type="text/javascript" src="my_functions.js"></script>

        <script> 
        $(document).ready(function() {
                animateText();
        }); 
        </script>
</head>

<body id="body_background">

<!-- 	
The point of this overarching content container 
is to get the fixed width effect and get this block centered 
-->	
<div id="container_outer">

	<div id="block0">
	
		<div class="text1">My Homepage</div>

		<div id="block0-1">
			<i>About:</i>
			<br>
			<div class="text2">
				About me: I work as an astronaut ...
			</div>
		</div>
		
	</div> <!-- block0 -->
	
	<div id="block1">

		<div id="block1_column1">

			<div class="text3">Hobby 1</div>
			
			<div class="text3in">ABCD<br>EFG<br>HIJK</div>
						
			<div class="text3">Hobby 2</div>

			<div class="text3in">LMNOP<br>QRS<br>TUV</div>
			
		</div>

		<div id="block1_column2">
		
			<div class="text3">Hobby 3</div>
			
			<div class="text3in">WX<br>Y<br>Z</div>
						
			<div class="text3">Hobby 4</div>

			<div class="text3in">123<br>456<br>789</div>

		</div>

		<div id="block1_column3">
		
			<div class="text3in">
				<a href="#">work page</a>, 
				<a href="#">blog</a>, 
				<a href="#">contact</a>
			</div>
		
		</div>

		<!-- for main picture block -->
		<div id="block1-1">
			<!-- images -->
			<div id="block0-2"></div>	
		</div>

	</div> <!-- block1 -->
				
</div> <!-- container_outer -->

</body>	

</html>
This is straightforward. In the head, we're giving paths or addresses to our CSS and JS scripts, and calling one homemade jQuery function animateText() we'll see below. In the body, there are two major content blocks <div id="block0">, the header, and <div id="block1">, which contains a number of columns and a large space for a picture.

test.css

#body_background
{
	background: rgb(50,50,50);
}

#container_outer
{
	/* container for all content */
	/* to get the fixed width effect and center  block centered */

	border: 5px solid white;
	width: 900px;
	/* if you don't include height, it will not be fixed 
	and accommodate however many elts you have */
	height: 930px;
	background: white;	
	/* margin defines the space OUTSIDE the border of the elt */
	/* setting the left and right margin to auto will automatically center the elt */
	margin: 4px auto 50px auto;
}

#block0
{
	/* title bar block */

	display: block;
	border:1px solid rgb(200,200,200);
	width: 850px;
	height: 200px;
	margin-top:10px;	
	margin-right: auto;
	margin-left: auto;
	/* 
	block0-1 is position:absolute - looks to nearest positioned parent, 
	which is this block. Use position: relative but don't shift any 
	direction. The point is, it has a position. 
	*/
	position:relative;	 		
}

#block0-1
{
	/* About me block */	

	border:1px solid rgb(200,200,200);
	width: 290px;
	height: 182px;
	position:absolute;	
	top:8px;
	left:550px;
}

#block0-2
{
	width: 225px;
	height: 200px;
	
	/* absolute pos takes out of doc flow */
	position:absolute;	
	top: 70px;	
	left: 340px;	
	background-image: url(hellokitty.jpeg); 
	background-repeat:no-repeat;	
}

#block1
{
	/* main block */	

	border:1px solid rgb(200,200,200);
	width: 850px;
	height: 680px;
	position:relative;
	margin-right: auto;
	margin-left: auto; 		
	margin-top: 8px;
}

#block1_column1
{
	/* column 1 in main block */	
	
	border:1px solid rgb(200,200,200);
	width: 180px;
	height: 663px;
	position:absolute;	
	top:8px;
	left:8px;
}

#block1_column2
{
	/* column 2 in main block */	
	
	border:1px solid rgb(200,200,200);
	width: 180px;
	height: 663px;
	position:absolute;	
	top:8px;
	left:200px;
}

#block1_column3
{
	/* column 3 in main block */	
	
	width: 200px;
	height: 20px;
	position:absolute;	
	top:624px;
	left:660px;
}

#block1-1
{
	/* for large picture embedded within main block */	

	border:1px solid rgb(200,200,200);
	width: 450px;
	height: 583px;
	position:absolute;	
	top:8px;
	left:390px;
}

.text1
{
	/* a class for styling text for main heading of the web page! */

	display: block;
	margin-top: 10px;	
	margin-left: 10px;	 

	font-size: 48px;
	font-weight:500;
	letter-spacing:10px;		
	color: black;	
	font-family:"Times New Roman",Georgia,Serif;
}

.text2
{
	/* a class for styling text in the About-Me block */
	
	display: block; 
	margin: 6px;	
	
	font-size: 13px;	
	color: black;	
	font-family:"Times";		
	letter-spacing:0px;
}

.text3
{
	/* a class for styling text for topic headers */
	
	display: block; 
	margin-top: 4px; 	
	margin-left: 4px; 
	
	font-size: 14px;
	font-weight:bold;
	letter-spacing:2px;	
	color: rgb(32,62,132);	
	font-family: Verdana, Arial, Helvetica, sans-serif;
}

.text3 a {color: rgb(32,62,132); text-decoration:none;}			/* unvisited link */
.text3 a:visited {color: rgb(32,62,132);}				/* visited link */
.text3 a:hover {color: rgb(32,62,132); text-decoration:underline;}	/* mouse over link */
.text3 a:active {color: rgb(32,62,132);}				/* selected link */

.text3in
{
	/* a class for styling text for topic sub-headers */
	/* "in" stands for "indent" */
	
	display: block; 
	margin-top: 4px; 	
	margin-left: 8px; 
	line-height: 1.6;

	font-size: 10px;
	font-weight:700;
	letter-spacing:1px;	
	color: rgb(0,171,255);	
	font-family: Verdana, Arial, Helvetica, sans-serif;

}

.text3in a {color: rgb(0,171,255); text-decoration:none;}		/* unvisited link */
.text3in a:visited {color: rgb(0,171,255);}				/* visited link */
.text3in a:hover {color: rgb(0,171,255); text-decoration:underline;}	/* mouse over link */
.text3in a:active {color: rgb(0,171,255);}				/* selected link */
This stylesheet gets the job done, but it doesn't do it particularly well. Remember when we discussed CSS positioning and remarked that it's unwise to overuse absolute positioning to place container blocks? Well, that's exactly the sin I'm committing here. It's fine if I'm only including a couple of things in each column. But if I have a lot of text—say, a list of 25 hobbies—the columns won't auto-size to accommodate this because they're out of document flow. It is therefore smarter to use floats to position blocks because it keeps them in document flow. Beginner that I am, I didn't grasp this when I wrote this CSS.

my_functions.js

function animateText()
{	
	console.log("Testing ..."); 

	$("#block1_column2").click(function() 
	{
		$(".text3").css("font-size", "32px");
	});						
}
This jQuery function increases the font-size of our Hobby headers when the user clicks on the second column. It's purely pedagogical—there's no reason you would want to do such a thing.

Together, these three files produce:

image

If we click on the second column, the jQuery expands all text of class == text3 as follows:

image

If you copy these files onto your computer, they should produce the same result.

Making Your Page Non-Stupid: The DRY Principle, Server Side Scripting, and CGI

DRY

After you've drunk deep from the cups of HTML, CSS, and Javascript, you'd think you'd be ready to go. So I thought, until I got down to business and hit a monumental logjam. When you visit some website, you'll often notice simple features that are unchanging across all pages—things like headers, footers, and sidebars. If you think about making 10 pages within a given site, you will very quickly become acquainted with the DRY Principle, which stands for "Don't Repeat Yourself". This is pure common sense: if you later decide to change your header, would you rather re-code it 10 times or re-code it once? In every walk of programming, this same reasoning causes people to package re-usable swaths of code into functions or modules. So, congratulations! You've had your first crisis, all stemming from the trivial question: How can I avoid repeating my HTML header code on each page?

If you have any programming experience, this is the easiest problem in the world: just store the header in a string as some kind of site-wide global variable and spit it out on every page. However, we've seen that HTML is not a programming language, so this isn't an option. What to do then? We could solve the problem with javascript/jQuery and create a function that inserts a bunch of HTML into a specific <div> tag on each page. This works, but it's a bad solution. First, you don't really want half of your HTML to be scattered inside javascripts. Second, there's a tiny chance the visitor to your site might have javascript disabled—although such a visitor wouldn't deserve much sympathy. And third, perhaps because javascript's niche is pop-up menus, animations, etc., it just feels awkward writing this in javascript.

Server-side scripting and CGI

Let's talk about a couple of distinctions related to the problem at hand. The first is static vs dynamic websites. A static website is just a marked up text file floating inanimately in cyberspace. A dynamic website, on the other hand, is one that has been programmatically generated in some way. For example, if your website has a series of magazine articles, and you want to generate a page on the fly that has all the articles with a given search-word, there's no way to do this statically. In our case, we want some very simple programming to automate attaching the header, sidebar, and footer. If we're going to write a program, where is going to run? Will it run on the computer of the person who's visiting our page, the client, or will it run on our computer, the server? This is the distinction between client-side scripting and server-side scripting. Javascript does the former, but we can also do the later.

We all know our HTTP server can serve up boring old HTML files. But you should also appreciate an important fact: it can oversee scripts that we run on our server as well. This means we can extricate ourselves from the HTML straitjacket and return to the land of sane programming. With server-side scripting, a visitor to your website from anywhere in the world can click some button and cause a script to run on your computer. Massive bombshell!

Ponder the implications of this major boon. Instead of requesting a plain HTML file, you can have the visitor request that a script be run which programmatically creates the HTML, automating headers included. But it could lead to problems if, for example, you allow the visitor to run a program that takes some input and subsequently makes a system call, because he could remove some of your files or worse. Hence, if your computer is going to permit some random person on the internet to run a script on it, it has to be done with care. One way of doing this is putting any such executable in a designated directory, often named cgi-bin. This isn't any great security measure, but at least it will restrict the scripts you have to worry about to one place. Who decides what and where directory this is and what the specific rules are? This is the job of your HTTP server, and you'll have to tailor its configuration file accordingly. With Apache, for example, you can read about how to do it here: A CGI (Common Gateway Interface) script refers to any script that can be run by, or is under the control of, your webpage. You can write it in any language you like, and it's sometimes given the extension .cgi. If you're using a web framework, it will handle the CGI stuff for you and you shouldn't have to worry about security. If you're DIY-ing it, be careful to sanitize user inputs as this comic shows.

If you look around the web and pay attention to URLs, you can spot programs running in the cgi-bin directory all over the place. For instance, I paid someone with PayPal the other day and captured this screenshot:

image

You can also see many scripts on the web with the .cgi extension. For example, in bioinformatics Blast is a program maintained by NCBI which aligns nucleotide or protein sequences based on homology. Look at this screen shot:

image

A user can upload his own sequences and run blast on NCBI's servers via the script Blast.cgi. This would be impossible without server-side scripting.

The URL as a Path; The URL as a Function Input

As we make the jump from simple static pages to more advanced dynamic pages, we're recapitulating the history of the web itself, which started primarily with one and progressed primarily to the other. The role of the URL is a nice illustration of this transition. Let's suppose your root HTML directory (the directory your HTTP server is set to serve pages out of) is:
/path/testwebpage
and that this is linked to the address:
http://myaddress.com
Now suppose your site's directory structure looks like this:
$ tree testwebpage/
testwebpage/
├── index.html
└── pages
    ├── about.html
    ├── contact.html
    ├── people
    │   ├── janedoe.html
    │   └── johndoe.html
    └── people.html
If you want to see janedoe's page on the web, the address is:
http://myaddress.com/pages/people/janedoe.html
and if you want to find the file janedoe.html on your computer, it's at:
/path/testwebpage/pages/people/janedoe.html
What you notice is that the URL, with its telltale forward slashes, is really just a glorified unix path. When you're browsing through your computer on the command-line, you go to the path you desire. On the internet, you go to a domain plus a path, almost as if you're inside the unix file system of the whole world's computer. In simple setups, your site's structure on the web is determined by its directory structure on your server. With modern websites, this is not necessarily the case. Instead, the URL is treated as a string which is the input to some function. When you call a website, a server-side script parses this string via regular expression and conditional logic decides what to do from there. We'll see an example of this below when we look at Django's urls.py. You can lose sight of some of these nuances if you jump into a modern web framework right away without appreciating what came before.

Making Your Own Dynamic Website with Apache and 1990s Perl CGI

If you were crazy, you could try to make your own dynamic website from scratch. But it would be foolhardy to try to re-invent the wheel. There are great web frameworks that do exactly this and are better than anything you can make in a reasonable time investment. Before I knew any better, I took a crack at it with "1990s" Perl and Apache, so I'll throw it up here purely as a curiosity. You can skip this section with impunity.

Change your Apache .conf file and parse your URL with mod_rewrite

The first step is to change your Apache configuration to allow the execution of .cgi scripts, and to parse the incoming URL. Something like this:
ErrorLog /path/root_html/error_log

<Directory "/path/root_html/">

Options FollowSymLinks Indexes MultiViews Includes ExecCGI 
AllowOverride All
Order allow,deny
Allow from all

RewriteEngine on
RewriteBase /

# Require all granted
AddHandler cgi-script .cgi

# this is working! - 
# http://www.webmasterworld.com/apache/4117882.htm
RewriteCond %{REQUEST_URI} !^/~username/cgi-bin [NC]
# RewriteRule foo.html http://mysite.edu/~username/bar.html
RewriteRule ^(.*)\.html$ http://mysite.edu/~username/cgi-bin/main.cgi?$1

</Directory>
What's going on here is that I'm using Apache's mod_rewrite to remap incoming URIs from, e.g.,
http://mysite.edu/~username/test.html
to
http://mysite.edu/~username/cgi-bin/main.cgi?test
So when a visitor thinks he's going to visit the page test.html what actually happens is that this URL is remapped to run the program cgi-bin/main.cgi and we can grab what's after the ? character—test in this example—and use it in our script.

Accessing our parsed URL from a perl CGI script

Now we need a main program, main.cgi, that stitches strings together to make an HTML document based on how it parses the URL. I'll give a sketch how you might do this, without doing the whole thing:
#!/usr/bin/env perl

use strict;
use warnings;
use CGI;
use Cwd 'abs_path';
use FindBin qw($RealBin);

#############################################
#### DEFINE VARS
#### 

# path to site directory root
my $sitedir="../mysite";

# main blocks of html content
my $block0html;
my $block11html; 
my $block12html; 

#############################################
#### MAIN 
####

# Print the CGI response header, 
# required for all HTML output 
# (must have this line or it will crash!)
# Note the extra \n, to send the blank line
print "Content-type: text/html\n\n" ;

print "<!DOCTYPE html>\n";
print "<html>\n";

my $page_name = parse_uri();

if ( -e "$sitedir/pages/$page_name" )
{
	$block0html = `cat $sitedir/pages/$page_name/html/block0.html`;
	$block11html = `cat $sitedir/pages/$page_name/html/block1-1.html`;
	$block12html = `cat $sitedir/pages/$page_name/html/block1-2.html`;

	print_html($block0html, $block11html, $block12html);
}
else 
{
	print "page not found\n";
}

print "</html>\n";

exit;

#############################################
#### SUBROUTINES 
#### 

# parse URI, for URI routing
sub parse_uri
{
	# use Apache mod_rewrite to change incoming URIs like, e.g., 
	# http://mysite.edu/~username/test.html
	# to
	# http://mysite.edu/~username/cgi-bin/main.cgi?test
	# this is going to return what's after the "?"

	my $uri = $ENV{"REQUEST_URI"};
	# split on "?"
	my @tmp=split(/\?/, $uri);
	return $tmp[1];
}

# print useful CGI stuff
sub print_cgi_info
{
	my $str = "";

	$str=$str."Versions:\n";
	$str=$str."perl: $]\n";
	$str=$str."CGI: $CGI::VERSION\n";

	my $q = CGI::Vars();
	$str=$str."\nCGI Values:\n";
	foreach my $k ( sort keys %$q ) 
	{
	    $str=$str."$k [$q->{$k}]\n";
	}

	$str=$str."\nEnvironment Variables:\n";
	foreach my $k ( sort keys %ENV ) 
	{
	    $str=$str."$k [$ENV{$k}]\n";
	}

	return $str;
}
This doesn't accomplish anything great, but you can see the lay of the land. We're going to read some HTML files into Perl variables as strings and we'll stitch them together in the method print_html(), which isn't shown. What a lot of work! Since everything is done programmatically, we can solve our problem about repeating the header. However, this solution is obsolete.

The Way Forward: A CMS, like Drupal, vs. a Web Framework, like Django

Summary thus far:
  • you should use server side scripting.
  • You should not try to write a web framework by yourself.
At this point in my web building odyssey, I wanted opinions about what to do next, not facts or tutorials. Thus, I will transmit the prejudices I acquired to you. Should you use a fancy content management system, like Drupal or Wordpress? In a word: no. Learning their idiosyncratic idiom is another chore, and engaging their heavy-duty machinery is pointless if you're not trying to build something big and bulky. Worst still, they lock you into a rigid pre-packaged framework. To do anything creative outside of it, you have to go learn the fundamentals anyway, then patch some script into their machinery. So why tolerate their expensive overhead? When you learn a language, you want to invest in one that has some staying power, like Rails or Python. You can do a lot with them, but only a single thing with Drupal. When I tried Drupal, it was all about cookie-cutter sites—not an adequate pay-off for its unpleasant learning curve.

Should you use a web framework, like Rails or Django? For me, the answer was yes. They're a lot more technical than Drupal or Wordpress but that's precisely why I like them better. I chose Django for this site because it's Python-based, but mostly out of ignorance. I like it so far! It gives you great tools for parsing URLs and hooking your site up to a database. There's a small primer below.

To reemphasize the point I made in the introduction, this solution fit my needs but it might not fit yours. See What Technology Do I Use Again? Don't take my word for anything!

Django Primer

When you get down to it, many web sites can be thought of as miniature magazines. After all, the web is comprised of pages. There are exceptions—some of those pages may have little TV screens or video games embedded in them—but for the most part the magazine metaphor works, especially for the most obvious form of personal site, the blog. Django, originally designed for a Kansas news-site, fits well into this paradigm. Django is based on Python modules or packages that you create. It's meant to be used together with a database to hold your data (the default is Sqlite). Let's see how we would build an article module. In Django, there are a few standard scripts that go in every user-created package:
  • models.py - defines the representation of your data
  • urls.py - controls URL routing
  • views.py - does logic processing
A good mnemonic I picked up off the web is MTV for Models, Templates, Views which, respectively, take care of data, presentation, and logic. If the following example is too simplistic, you can look at some of the Django source code for this website below.

models.py

models.py is the script responsible for establishing the model of your data and Django will use it to create a table in your database. It's easy to understand models.py in terms of object-oriented programming: think of it as where you define what an article class is and supply any methods you want to act on article objects (i.e., instances of this class). Consider a magazine article for a moment. Aside from the text itself, there's a lot of metadata associated with it—the author's name, the date of publication, the format in which it's to be rendered, how many "likes" it has, and so on. All of this stuff goes into your article object. models.py might look like this:
from django.db import models

# https://docs.djangoproject.com/en/dev/ref/models/fields/
class Article(models.Model):
    author = models.CharField(max_length=500)
    title = models.CharField(max_length=500)
    pub_date = models.DateField('date published')
    body = models.TextField()

    # example method:
    def get_author(self):
        return self.author
As soon as we've set this up, running
$ ./manage.py syncdb 
creates a table in our database corresponding to the model. (Django comes with the script manage.py, which takes care of a lot of miscellaneous tasks.) It is now our job to populate this database with content, .e.g.:
sqlite> SELECT * FROM article_data LIMIT 1;
id|author|title|pub_date|body
1|joe|first_article|2014-01-13|my first article
For an example wrapper script to load data into an sqlite database, see Wiki: MySQL and SQLite. This is all necessary leg work, even though we haven't said anything about our actual website yet.

urls.py

The next step is to determine how we want to route a given URL to a given page in our site. Think of the URL as a string which is the input to a function. The function is going to take this string, parse it, and then send the user along to the appropriate page. This is the job of urls.py, which might look like this:
from django.conf.urls import patterns, include, url

urlpatterns = patterns('',
    url(r'^news/(?P<article_name>\w+)/$', 'article.views.my_news_article_function'),
    url(r'^blog/(?P<article_name>\w+)/$', 'article.views.my_blog_article_function'),
)
This parses the URL via regular expression (see the python regex docs if this is unfamiliar to you). Any URL that follows the pattern blog/some_article_name such as
http://www.mysite.com/blog/some_article_name/
will call the the function my_blog_article_function in views.py, passing the variable article_name to it as input. On the other hand, URLs of the pattern news/some_article_name will call a different function. So—what's views.py?

views.py

views.py is the logical brain of your operation. It takes the variables passed by urls.py, does whatever scripting it needs to do, chooses the appropriate page template, and creates your HTML. For example:
from django.shortcuts import render, render_to_response
from django.http import HttpResponse
from django.template.loader import get_template
from django.template import Context
from django.views.generic.base import TemplateView
from article.models import Article

def my_news_article_function(request, article_name):
    name = "Dear Reader"
    html = "<html><body>Hi %s</body></html>" % name
    return HttpResponse(html)

def my_blog_article_function(request, article_name):
    name = "Dear Reader"
    t = get_template('article/blog_template.html')
    html = t.render(Context({'name': name, 'article': Article.objects.get(title=article_name)}))
    return HttpResponse(html)
The function my_blog_article_function passes a Context object to the template blog_template.html, which has access to the python dict passed as an argument. We also have access to our article object—note the line:
from article.models import Article
and Django provides convenient methods on it, like the one we're using to get a specific article by title. Still, we don't know how the HTML looks until we see our template.

Templates

Django has a templating language, which is HTML augmented with simple variables, loops, and logic. This is a big subject you can read about here: The only thing I'll say about it is that variables are enclosed in double curly brackets:
{{ variable }}
Our template blog_template.html might look like this:
<html>
<body>
        Hi {{ name }}
        Welcome.
        You are reading {{ article.title }}
        by {{ article.author }} published on {{ article.pub_date }}
        <br>
        <br>
        {{ article.body }}
</body>
</html>
Thus we see how data which originated in our database makes its way, via parsing in urls.py and conditional logic in views.py, into our HTML.

More about Django

I have some more notes about Django here.

Debugging Your Website and Lifting Code from Pages You Like

Now that you're merrily in the midst of building your website, you may find yourself doing a lot of debugging. We all know how to debug an ordinary program, but how do you debug a website? If you're on a Macintosh, Safari has a nice suite of developer tools. We've already mentioned the Error Console. Another thing you want to use is the Web Inspector in the menu:
Develop > Show Web Inspector
It looks like this:

image

The web inspector lets you view your source code and get a DOM's-eye-view of your page. Crucial for debugging, you can click on an HTML tag and see what CSS styling it's getting. Most other browsers have similar capabilities—e.g., Chrome's is at:
View > Developer
(You may have heard of the world famous Command Option J).

Anytime you view a website, all of the HTML, javascript, CSS, and images are downloaded to your computer. You can see all of them with the web inspector. Do you like something from somebody else? Take it then (but give credit, as common sense demands).

Misc Topics: Favicons and robots.txt

A couple of miscellaneous topics that don't fit anywhere in particular. As you put the finishing touches on your website, you'll want to make a favicon, which is the little graphic next to the URL. Two useful sites for this are: The favicon for this site:

image

features an ape motif. To make it, I used a 16 x 16 pixel canvas in Photoshop—the actual size of a favicon—and then converted the picture into an .ico file. A word of advice: don't try to do too much with it artistically. The tiny dimensions force you to stay bold and simple.

Changing gears completely, search engine spiders (or robots) crawl over the web all the time, making page indexes. By convention, these robots should obey instructions you give them in a robots.txt file in your website's root directory. For example, an instruction might forbid preview information about your site to be displayed on Google's search results. Read more about robots.txt here:

Working with and Optimizing Images for Your Site

As emphasized in the intro, it mustn't be forgotten that content and visual comeliness are the most important aspects of any site—programming is merely the necessary mechanical part. When you build a website from scratch you're facing, first and foremost, a graphic design problem with a secondary computer science problem piggy-backing on its shoulders. Or is it the other way around? In any case, without nice graphic design everything suffers. Here are a couple of tips about the technical aspects of image manipulation.

When you work with images, knowing and adjusting the pixel dimensions is often necessary. There's a very easy way to do this on a Mac. Using Preview, go to Tools > Adjust Size in the menu. Even if you don't adjust the size, this will tell you the dimensions. Another way to do this is with the nonpareil (and free) ImageMagick toolkit. You can re-size and re-position pictures or change their formats in bulk from the command-line. Of course, Adobe Photoshop is basically indispensable, as all graphics professionals know. Buy it! Your page will be much better for it.

Because image files can be large, they have the potential to slow down your site. You should put some thought into how much burden you're willing to put on the visitor to your site who has to download them. There's a wonderful discussion about this in Chapter 10: Optimizing Images from an O'Reilly book called Even Faster Websites. The authors note:
The single most important thing you can do to improve performance is put your site on a diet—take off (and keep off) all the bytes you put on under the stress of chasing the next killer feature. Optimizing images is one way to do just that. Historically, the question of which features to include was considered a business rather than an engineering decision, so page weight has rarely been discussed in performance circles, and yet it is extremely important to overall response time.

Response time for web pages is almost exactly correlated to page weight, and images tend to account for half of the size of typical web pages (see Figure 10.1, “Images as a percentage of page weight for the Alexa top 10 global web sites”). Most importantly, images are an easy place to improve performance without removing features. Often, we can make substantial improvements in the size of an image with little to no reduction in quality.
One easy step which goes a long way: play with ImageMagick to experiment with different compression formats for your pictures. Try .gif, .jpg, and .png and use the one that produces the smallest file size (I review some basic ImageMagick commands here). The authors have other good suggestions, like stripping metadata from your images before you post them.

How I Made This Website: Example Source Code (Django + jQuery)

You could read a tome on web design, but there's no substitute for example code. Let's look at an early draft of the source code for this website. I'm using the Django web framework. It would be impractical to write out all of the code, so I'll focus on the most important bit, the article module. Instead of trying to explain every line of code below, I'll just give some helter-skelter observations following each script.

article/models.py

My article/models.py looks like this:
from django.db import models

# https://docs.djangoproject.com/en/dev/ref/models/fields/

class Article(models.Model):
    shortname = models.CharField(max_length=50)
    title = models.CharField(max_length=500)
    subtitle = models.CharField(max_length=500)
    author = models.CharField(max_length=500)
    body = models.TextField()
    pub_date = models.DateField('date published')
    likes = models.IntegerField()
    tags = models.TextField()
    abstract = models.TextField()
    category = models.CharField(max_length=200)
    format = models.IntegerField()
    polish = models.IntegerField()

    def tags_as_list(self):
        return self.tags.split(',')

    def get_id(self):
        return self.id

    def get_cat(self):
	# return the first (primary) category in the comma-delimited list
	my_category_list=self.category.split(',')
        return my_category_list[0]

    def get_full_cat(self):
	# return the full category
        return self.category
I included a lot of attributes here, probably more than I need. category and shortname are going to comprise the last two fields of the URL. For this article, category == computing and shortname == tut_web, so the URL is:
http://www.mysite.org/article/computing/tut_web/
I have a body attribute, but I ultimately decided to keep the HTML body content in a static files because it's easier to edit than having to fish in and out of a database all the time—although perhaps you couldn't get away with this for a large-scale site. So there's a directory for each article that contains a content.html file along with whatever images go along with the it. The content.html file contains the body of the article and is completely decoupled from the page layout.

Articles can be in more than one category, so the method get_cat returns the primary one, while get_full_cat gives the whole list in a comma-delimited string.

article/urls.py

My article/urls.py looks like this:
from django.conf.urls import patterns, include, url

urlpatterns = patterns('',
    url(r'^all/$', 'article.views.all_articles_better'),
    url(r'^(?P<article_category>\w+)/$', 'article.views.all_category_articles'),
    url(r'^(?P<article_category>\w+)/(?P<article_name>\w+)/$', 'article.views.one_named_article'),
)
This routes URL to the three different page types related to articles:
  • a full site page of contents, taken care of by the function all_articles_better
  • a page of contents for articles of a given category, taken care of by the function all_category_articles
  • the article itself, taken care of by the function one_named_article

article/views.py

Let's look at article/views.py:
from django.shortcuts import render, render_to_response
from django.http import HttpResponse
from django.template.loader import get_template
from django.template import Context 
from django.views.generic.base import TemplateView 
from article.models import Article 
from django.core import serializers
import os, re

CW_DIR = os.path.dirname(__file__)

# NOTE: you have to re-start uwsgi for changes in views to take effect!

#########################

def all_articles_better(request):

    d={} # dict where keys = categories, values = list of article objects of that category

    for i in Article.objects.all(): 

        myid = i.get_id(); 
	mycat_list = i.get_full_cat(); # comma-delimited list of categories

    	for mycat in mycat_list.split(','): 
	    if not (mycat in d):
	        d[mycat] = [Article.objects.get(id=myid)]
	    else:
	        d[mycat].append(Article.objects.get(id=myid))

    return render_to_response( 'article/articles_contents.html', {'my_cat_article': d} )
    
def all_category_articles(request, article_category=1):
    # use case insensitive contains: icontains
    # see https://docs.djangoproject.com/en/dev/topics/db/queries/
    # "Basic lookups keyword arguments take the form field__lookuptype=value. (Thats a double-underscore)."
    return render_to_response(
        'article/articles_category_contents.html', 
	{'myarticle': Article.objects.filter(category__icontains=article_category)} 
    )

def one_named_article(request, article_category=1, article_name=1):

    t = get_template('article/one_named_article.html')

    # get file path
    mypath = CW_DIR + "/../static_page_data/" + article_name + "/html/content.html"

    htmlcontent = ""

    with open(mypath, "r") as myfile:
        htmlcontent=myfile.read()

    html = t.render(
	Context({'myarticle': Article.objects.get(shortname=article_name), 'htmlcontent': htmlcontent})
    )

    return HttpResponse(html)
The function all_articles_better makes the table of contents for the full site. I create a dict d where each key is a category, and each value is a list of article objects of that category. This data structure gets passed to the template article/articles_contents.html, which we'll see below. Note that by design the same article can be in two different categories.

all_category_articles filters my article objects to make a category-specific table of contents, and one_named_article passes raw HTML to a template we won't discuss called one_named_article.html, which is the view you see when you read an article.

Templates

A key part of Django templating is inheritance. When a child templates extends a parent template, it looks exactly like the parent except where it explicitly overwrites it. We're going to look at the template that has the full table of contents for this site, article/articles_contents.html. But first, let's look at its parent, base.html:
{% load static from staticfiles %}
<!DOCTYPE html>
<html>
<head>
        <!-- title -->
	{% block titleblock %}
        <title>Oliver</title>
	{% endblock %}

        <!-- meta -->
	{% block metablock %}
        <meta charset="UTF-8">
        <meta name="description" content="Oliver's Homepage">
        <meta name="keywords" content="Oliver, Oliver Artwork">
        <meta name="author" content="Oliver">
	{% endblock %}

        <!-- favicon -->
	<link rel="icon" type="image/ico" href="{% static "img/favicon.ico" %}" />

        <!-- styles -->
	<link rel="stylesheet" type="text/css" href="{% static "css/default.css" %}" />
	<link rel="stylesheet" type="text/css" href="{% static "css/style0.css" %}" />
	<link rel="stylesheet" type="text/css" href="{% static "css/style1.css" %}" />
	<link rel="stylesheet" type="text/css" href="{% static "css/style2.css" %}" />
	<link rel="stylesheet" type="text/css" href="{% static "css/style3.css" %}" />
	<link rel="stylesheet" type="text/css" href="{% static "css/style4.css" %}" />
        
	<!-- scripts -->
	<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js" 
	charset="utf-8"></script>
	<script type="text/javascript" src="{% static "js/my_functions.js" %}"></script>
	<script type="text/javascript" src="{% static "js/modernizr-latest.js" %}"></script>

	<script> 
	$(document).ready(function() {
		createToc();
		unhideContainer();
		
		// add page specific jquery
		{% block jqblock %}
		{% endblock %}
	}); 
	</script>

</head>

<body> 

{% block progblock %}
{% endblock %}

<noscript> 
	<div class="text_warn">  <h3><i>Please Enable JavaScript!</i></h3> </div> 
</noscript>

<div id="container">

	<div id="section-navigation">
	{% block sidebar %}
	<div class="text2"> 
		<b><a href='/'>HOME</a></b> 
		<br>
		<br>
		<b><a href='/article/all/'>Full Sitemap</a></b>
		<br>
	</div>
	{% endblock %}
	</div>

	<div id="content-container">

		<div id="header">
		{% block header %}
		{% endblock %}
		</div>
		
		<div id="content">
		{% block content %}
		Content
		{% endblock %}
		</div>

		<div id="aside">
		{% block aside %}
		{% endblock %}
		</div>

	</div>

		<div id="footer">
		{% block footer %}
		<small>© 2014 Oliver</small>
		{% endblock %}
		</div>

</div>
</body>
</html>
In the <head>, there are the usual links to stylesheets and a few javascript functions. The rest of the page is mostly template blocks which the child templates can write into.

Here's article/articles_contents.html:
{% extends "base.html" %}

{% block titleblock %}
<title>Oliver - Full Sitemap</title> 
{% endblock %}

{% block content %}

	<div class="text3close">
	
	<h3><a href='/art/fns'>Art</a></h3>

	<!-- key is category, value is list of articles in that category -->
	<!-- loop thro categories -->
	{% for key,value in my_cat_article.items %}
		
	{% if key != "unlinked" and value|length > 1 %}

		<h3><a href='/article/{{ key }}'>{{ key|capfirst }}</a></h3>

		<!-- loop thro list of values (it shud contain article objs) -->
		{% for j in value %}

			<!-- only print articles with polish -->
			{% if j.polish > 10 %}

				<a href='/article/{{ key }}/{{ j.shortname }}'>{{ j.title }}</a> <br>

			{% endif %}

		{% endfor %}

		{% endif %}

	{% endfor %}

	</div>

{% endblock %}

{% block footer %}
<small>© 2014 Oliver</small>
<a href='/article/unlinked/art_hero'>
<div class="image1_c">
	<img src="/static/article/img/hero2_purple_w100.png" alt="image" width="100" />
</div>
</a>
{% endblock %}
The line:
{% extends "base.html" %}
tells Django this template is building off of the groundwork laid in base.html. Remember my_cat_article is the dict mapping each article category to a list of articles. In this template, we're looping over each category and then all the articles within it. The point is to make links connecting to the rest of the site. There's a little bit of conditional logic: the special category unlinked is for articles I don't want to appear in the table of contents. I also won't print a category heading if the category has one or fewer articles in it. The contents will only contain articles with a polish attribute of greater than 10. With this dial, I can work on writing an article but keep it unlisted until it's duly polished. You can see what this template produces here.

CSS

Let's leave the world of Django, and talk CSS for a minute. I have about 1000 lines of it so far. For the layout, I started with a script from maxdesign.com and modified it. Here's a tiny peek at my CSS containing the font information for the main text categories. I opted for a clean-cut and functional look using a sans-serif font, Arial:
.text1
{
        /* page header style */
        font:30px bold arial,sans-serif;
        padding: 15px;
}

.text2
{
        /* left sidebar style */
        font:10px arial,sans-serif;
        padding: 5px;
}

.text3
{
        /* main text style */
        font:16px arial,sans-serif;
        line-height: 26px;
        padding: 15px;
}
The class I'm using for the body of the text is primarily text3. Remember, if you want to view or steal more CSS, you can do it through Safari's web inspector.

jQuery

To give you some j-flavor, here's one of the jQuery functions I wrote for this site. We didn't see the article template, but each article is divided into sections with <h2> header tags. At the top of every page is a page-wide (not site-wide) table of contents. It would be a pain to write this manually for every page and have to tweak it when something changes. So I wrote a jQuery function, createToc(), that automatically generates a table of contents from the <h2> tags. It's going to write into an empty div tag I include in the article template:
<div id="toc_main"></div>
Here's createToc():
function createToc()
{ 
    /*
    This creates a table of contents automatically by looping through h2 tag elements 
    */

    var my_url_path  = window.location.pathname
    // console.log( my_url_path );

    // testing:
    /*
    $( "h2" ).each(function( index ) {
        console.log( index + ": " + $( this ).text() );
    });    
    */

    $( "#toc_main" ).append( '<i>Table of Contents</i><br>');
    $( "#toc_main" ).append( '<small>');

    // loop thro all h2 tags
    $( "h2" ).each(function( index ) {

        // Add id to header
        $( this ).attr('id', 'h_id_' + index);

        // testing: was the id added successfully?
        // var $myid = $( this ).attr('id');
        // var $myclass = $( this ).attr('class');
        // console.log($myclass + ' ' + $myid);

        var $mytext = $(this).text();
        // remove whitespace and special chars and truncate to 40 chars:
        var $mycleantext = $mytext.replace(/\s+|\W+/g, "").substring(0,40);

        // add internal page link
        var $internal_link = '<a id="' + $mycleantext + '"></a>';
        $( this ).before($internal_link);

        // testing:
        // console.log($mytext.replace(/\s+|\W+/g, ""));

        // make a bit of html which is a link, has an id (sidebar_id_index), 
	// and contains text from the h2 element
        var $onebased = index + 1;
        var $htmlstr = '<a id="sb_id_' + index + '" href="#' + $mycleantext + '">';
        $htmlstr += $onebased + '. ' + $mytext;
        $htmlstr += '</a>';
        $htmlstr += ' <small><small><small><small><a href="' + my_url_path + $onebased;
        $htmlstr += '">VIEW_AS_PAGE</a></small></small></small></small>';

        // append this html to the elt with id == #toc_main (this will be in the main body)
        $( "#toc_main" ).append( $htmlstr + '<br>');
        
        // foreach element with sidebar id == sb_id_index, scroll to element with header id = h_id_index
        // from: http://stackoverflow.com/questions/6677035/jquery-scroll-to-element
        $("#sb_id_" + index).click(function() {
            $('html, body').animate({ scrollTop: $("#h_id_" + index).offset().top }, 1000);
        });    

        // add a little TOP link to take you back to the top of the document
        $( this ).append(' <small><small><a href="#">TOP</a></small></small> ');
        $( this ).append('<small><small><small><a href="' + my_url_path + $onebased + '">VIEW_AS_PAGE</a>');
        $( this ).append('</small></small></small>');
    });

    $( "#toc_main" ).append( '</small>');
    
}
The first thing this script does is to find the ID == toc_main div tag and write "Table of Contents" into it. Then it loops through each <h2> tag and gives it a unique ID, h_id_index, based on the index of the loop. It also adds a TOP and VIEW AS PAGE link to each tag. The variable $mytext grabs the text out of the header and $mycleantext is that same text with whitespace and special characters removed. Just before each <h2> tag, the script adds an <a> tag, whose ID is mycleantext. Internal page links, which get appended to the toc_main div and have IDs of the form sb_id_index, are going to jump to the elements of ID h_id_index—the <h2> headers. They look like this:
<a id="sb_id_index" href="#mycleantext">number. mytext</a>
This is a little bit subtle: when you click these internal page links where you go is determined by the click, animate, and scroll code which supersedes where the href source would take you. However, because of the href part, the URL still becomes "pretty":
http://www.mysite.org/article/computing/tut_web/#some_section
Remember we added <a> tags of ID mycleantext just above each <h2> tag:
<a id="mycleantext"></a>
So, if we enter this URL de novo, we still get to the right place.

Conclusion

I hope this article fills a niche for beginners looking for a non-patronizing overview of the arc of website building. I'm a beginner myself and I couldn't find anything that quite brought it all together. The question, "How Do I Make A Website?" is searched for so often that the Google results become an unsortable din of ten thousand voices. A lot of those voices seemed stupid to me or at least weren't telling me what I wanted to hear. If my take on website building seems programming-heavy, you should take encouragement that none of the coding included in this article is difficult. But there are a lot of moving parts. Perhaps the hardest thing is getting 5 very different languages to work in harmony. Good luck with your website!
Advertising

image


image


image


image