Blog
Common HTML Markup
Everyone that writes content on the web should know a little HTML. This is my cheat sheet for the most common used HTML elements I've seen that are supported in multiple browsers, tools, and CMS software.
Text Structure
blockquote, br, h1, h2, h3, h4, h5, h6, p
Example:
A pessimist is one who makes difficulties of his opportunities and an optimist is one who makes opportunities of his difficulties.
Harry S. Truman
<blockquote cite="http://www.brainyquote.com/quotes/authors/h/harry_s_truman.html">
<p>A pessimist is one who makes difficulties of his opportunities
and an optimist is one who makes opportunities of his difficulties.</p>
<p>Harry S. Truman</p>
</blockquote>
HTML Elements
a, abbr, acronym, code, del, em, ins, img, pre, sub, sup, strike, strong
Notes:
- The image element (img) should include an alt="" attribute that is a description of the image.
- Declining in use; b (use strong), i (use em).
- The element strike could be used for formatting, but if used to denote editing, del should be used instead.
Example:
HTML or HTML 4.01 is an abbreviation, whereas, GUI is an acronym. I added text then removed it.
<p>
<abbr title="Hyper Text Markup Language">HTML</abbr> or <a title="HTML 4.01 Specification"
href="http://www.w3.org/TR/html4/">HTML 4.01</a> is an abbreviation,
whereas, <acronym title="Graphical User Interface">GUI</title> is an acronym.
I <ins>added</ins> text then <del>removed</del> it. </acronym>
</p>
Lists
Example:
- apples
- peaches
- pears
<ul>
<li>apples</li>
<li>peaches</li>
<li>pears</li>
</ul>
Tables
Example:
Column One | Column Two |
---|---|
cell one | cell two |
cell three | cell four |
<table>
<tr>
<th>Column One</th>
<th>Column Two</th>
</tr>
<tr>
<td>cell one</td>
<td>cell two</td>
</tr>
<tr>
<td>cell three</td>
<td>cell four</td>
</tr>
<caption>Table caption</caption>
</table>
Content Formatting
Elements To Avoid
Style Preferences
Personally, I don't like br tags. If more space is needed between paragraphs, then the CSS should be modified, not the content. I prefer div elements for block sections and span elements for inline.
Example:
I went on a snowmobile tour in Keystone Colorado.
<div class="floatleft">
<img alt="Snowmobiles at Keystone Colorado"
src="http://tim-stanley.com/Snowmobile1_thumb.jpg">
</div>
<p>I went on a snowmobile tour in Keystone Colorado.</p>
<div class="clearer></div>
Head Elements
link, meta, script, style, title
The meta description is used to display by search engines. If a description isn't present, the search engine will pick their won. Most search engines use a combination of the description and content to display preview information of the page.
Version information on style sheets and JavaScript files are used and updated when the content changes to force browsers to re-load their cached versions (particularly if a far expiration date is set on the content).
Example:
<head profile="http://gmpg.org/xfn/11">
<link rel="stylesheet" href="/themes/style.css&v=1.4.5.1" type="text/css" />
<meta name="keywords" content="photography,photoshop" />
<meta name="description" content="Mister Retro has a great set of Photoshop plug-in's that
will save a significant amount of time and effort when manipulating files in Photoshop for
those textured and stunning artistic effects." />
<link rel="last" title="Using Cache And Compression For Performance"
href="/post/Using-Cache-And-Compression-For-Performance.aspx" />
<link rel="first" title="How To Enable HTM Server Side Include Parsing in IIS"
href="/post/How-To-Enable-HTM-Server-Side-Include-Parsing-in-IIS.aspx" />
<link rel="next" title="Images Part 1 - Snagit" href="/post/Images-Part-1-Snagit.aspx" />
<link rel="prev" title="Font Tools" href="/post/Font-Tools.aspx" />
<link rel="contents" title="Archive" href="/archive.aspx" />
<link rel="start" title="Tim-Stanley.com" href="/" />
<link type="application/rdf+xml" rel="meta" title="SIOC" href="http://tim-stanley.com/sioc.axd" />
<link type="application/apml+xml" rel="meta" title="APML" href="http://tim-stanley.com/apml.axd" />
<link type="application/rdf+xml" rel="meta" title="FOAF" href="http://tim-stanley.com/foaf.axd" />
<link type="application/rss+xml" rel="alternate" title="Tim-Stanley.com (RSS)"
href="http://tim-stanley.com/syndication.axd?format=rss" />
<link type="application/atom+xml" rel="alternate" title="Tim-Stanley.com (ATOM)"
href="http://tim-stanley.com/syndication.axd?format=atom" />
<link type="application/rsd+xml" rel="edituri" title="RSD" href="http://tim-stanley.com/rsd.axd" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link type="application/opensearchdescription+xml" rel="search" title="Tim-Stanley.com"
href="http://tim-stanley.com/opensearch.axd" />
<script type="text/javascript" src="/blog.js&v=1.4.5.1"></script>
<title>Machine Wash Effect - Tim-Stanley.com </title>
</head>
DocType
The DOCTYPE is the most controversial. XHTML or HTML, transitional, or strict? The main reason the DOCTYPE is controversial is because it can cause browsers to display in standard or quirks mode depending on the DOCTYPE. XHTML 1.0 Transitional is my preference.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
References
Related Items
Using Cache And Compression For Performance
Most browsers and servers have default values that provide fairly good performance with a minimum caching of static file content. A little bit of coaxing can result in better performance with less traffic and less bandwidth.
There are two types of caching I discuss: static content (*.JPG, *.JPEG, *.png, *.gif, *.ico) rarely updated and semi-static content (*.js, *.css) updated very infrequently. The decision to cache page output (*.aspx, *.html, *.htm) long term is too dependent on application functionality decisions to discuss generically.
Summary
If you are short on time, the quick summary is summarized below.
Setting a future expiration date let's the browser be smarter about how it requests content only when absolutely necessary. Compressing / Deflating the content for css, js, aspx and html content minimizes the amount of bandwidth used. If you pay for bandwidth by the byte, compression is going to save money.
Windows Servers:
- If you have access to the IIS Admin console, set an expiration date. This is cheap and quick. You get caching via future expiration dates without compression and with no code changes.
- If you want to control individual files for compression and/or caching, but do not have IIS Admin access, you can configure a verb to process *.css.axd, *.jpg.axd, *.js.axd files and then change your references to the content.
- If you want to control individual files for compression and/or caching, install an httpHandler and configure the verb to process *.css, *.jpg, *.js or other files. This also requires access to the IIS Admin console to set the Application Extension Mapping, or if the project is installed via MSI, the mappings can be done at installation.
Apache Servers:
- Use Apache mod_expires to set the expiration date in the future.
- Modify .htaccess and set Header unset ETag and FileETag None
- Use a compression module on like mod_gzip or something similar.
Expiration Dates:
- Images should be anywhere from 30 days to 5 years or more.
- CSS and JavaScript may need to be updated more frequently and should be anywhere from 1 day to 5 days.
One Page, Many Contents
When loading a web page, it typically isn't a single request. It's just the tip of the iceberg. The page loads, then the browser may need to load more content from that (like a CSS file that references images). The browser may also attempt to load the favicon.ico file even if the page doesn't ask to load it.
Here's an example of a single page that has 27 requests for various different content needed to support loading 1 page.
200's and 304's
Browsers have a conversation with the server to request content for a [url] that starts off something like this.
First time requests:
- Browser: Can I have the content for [URL]?
- Server: HTTP/1.0 200 OK -> here it is.
- Browser: I also need the content for [URL]
- Server: HTTP/1.0 200 OK -> here it is.
- Browser: I also need the content for [URL]
- Server: HTTP/1.0 200 OK -> here it is.
That happens over and over for every piece of content needed for the page to be displayed for the first time. The second time the request is made, if the browser has enough information to make a decision, it gets a bit smarter.
Second + N requests:
- Browser: If the server sent an expiration time for the content, the browser may just use the last copy of the content (No request sent to the server)
- Browser: If the server didn't send an expiration time, request the content (depends on browser settings).
- Server: If it was updated or no eTag match: HTTP/1.0 200 OK -> here it is.
- Server: If it's the same: HTTP/1.1 304 Not Modified -> Use what you have, it's hasn't changed.
The difference between loading the same page shown above is 1.78 seconds for the first time and 0.108 seconds the second time. The time savings is due to the fact that all but one piece of content is cached in the browser for the second request.
Browser Settings
Although you can't force users to do it, browser settings can affect how they ask servers for the information.
A unique query parameter on a URL will cause IE 7 to believe it's a "different" URL and IE will be more inclined to request data even though it already has it. For example traces I've seen with timestamp's as part of the query parameter will cause IE to request JPG files and receive 304 responses. If the query parameter is not part of the URL, IE will not request the content again until a refresh is requested.
The following value controls how IE uses it's cache for HTTP content (not just pages).
Firefox 3 has both the Private Data (cache) setting and the options that control how it utilizes the cache.
Entity Tags
Entity Tags (ETags) are used to provide additional detail for checking caching. Yahoo Rules for high performance web sites and YSlow recommend setting the ETag values to improve performance.
By default, Apache and IIS use ETags. If you are running a web farm, remove ETags or ensure the ETags are syncronized across the farm (refer to the Microsoft support article to remove etags in IIS).
In Apache to remove ETags, modify the .htaccess or httpd.conf file:
Header unset ETag
FileETag None
If ETags are used, the request from the browser will contain something like the following:
If-Modified-Since: Tue, 08 Jul 2008 05:52:56 GMT
If-None-Match: "0ac6adebee0c81:893"
In ASP.Net code, this is set with a statement like:
Response.Cache.SetETagFromFileDependencies();
Refer to the Microsoft support article to remove etags in IIS or to set ETags, refer to Enabling Client-Side Caching of Generated Content in ASP.NET for a more detailed explanation.
Save Requests, Use A Cache
If you have a large number of users, the 304 responses add additional HTTP requests and traffic. These can be eliminated or reduced in IIS and ASP.Net in three ways: IIS Content Expiration, ASP.Net *.css httpHandlers, or with an ASP.Net *.axd httpHandler.
IIS Content Expiration
If you have access to IIS administration set the IIS expiration cache to an appropriate value. Unlike Apache, I haven't figured out how to set different expiration dates for images versus CSS and JavaScript files.
ASP.Net httpHandler *.css.ashx *.css.axd
Sample content references:
<link rel="stylesheet" type="text/css" href="csshandler.axd?path=style.css" mce_href="csshandler.axd?path=style.css" />
<link rel="stylesheet" type="text/css" href="style.css.axd" mce_href="style.css.axd" />
Adding an httpHandler in the web.config.
<httpHandlers>
<add path="*.css.axd" verb="*" type="Utils.SFHandler" validate="false"/>
</httpHandlers>
The article at Caching in ASP.NET explains in more detail how to use this approach. This approach does not require IIS administration permissions, but it does leave the CSS or other source references tied to unusual file extensions for css, js, and images.
Caution: You must take measures to ensure that only specific types of files desired are output. If this is not done properly in code, using the path=abc.css approach, could allow someone to load a normally secure file (like the web.config) using this technique.
Once you have the handler in place, it's simple:
Response.Cache.SetExpires ( DateTime.Now.AddMinutes ( 86400 ) )
Response.Cache.SetCacheability ( HttpCacheability.Public )
Refer to the code example for the BlogEngine.Net CSS handler for more detail.
ASP.Net httpHandler *.css
Sample content reference:
<link rel="stylesheet" type="text/css" href="style.css" mce_href="style.css" />
Adding an httpHandler in the web.config.
<httpHandlers>
<add path="*.css" verb="*" type="Utils.SFHandler" validate="false"/>
</httpHandlers>
The approach is exactly the same as in Caching in ASP.NET, but this time some more configuration work is required. However, with this approach an additional application IIS Extension Mapping is required. If you have access to the IIS administration console, this is easy for the site. If you are in a commercial hosting environment, it's much more difficult.
In IIS, this is set on the Home or Virtual Directory, Configuration, Mappings, Add
Executable = C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
Extension = .css
Limit To = GET,HEAD,POST,DEBUG
Apache mod_expires
In Apache, an future expiration date can be set with with Apache mod_expires.
ExpiresActive On
ExpiresByType image/gif A2592000
ExpiresByType image/png A2592000
ExpiresByType image/jpg A2592000
ExpiresByType image/jpeg A2592000
Save Bandwidth, Use Compression
Compression can reduce the size of a css, js or the output of php or aspx files by 60-80%. Yahoo performance research notes:
40-60% of Yahoo!’s users have an empty cache experience and ~20% of all page views are done with an empty cache.
Even though these files can be cached, by enabling compression for these files, you reduce both the bandwidth and the load time required for the file. If you pay for bandwidth by the byte, this will save money.
All this bandwidth savings comes at a cost of CPU. If the results for static content are cached, the result is minimal. If you have a large number of users accessing a site and they are accessing it over the WAN, not LAN, then compression is in my opinion a better option over the CPU cost. If your on a LAN or have a low number of users, compression isn't going to benefit compared to the CPU cost.
Mads Kristensen talks about stripping white spaces in the article Reduce the weight of stylesheets by 35% at runtime but his article on HTTP compression in ASP.NET 2.0 covers how to make compression work for the ASPX output and this can be applied to css and js files as well.
Warning: Using compression can break some javascripts, if used on the Webresources.axd, and can break some third party components, so use this with caution.
For information on Webresource compression, refer to Miron Abramson's New & Shiny WebResource.axd compression Module.
BlogEngine.Net
BlogEngine.Net is a wonderful blogging platform (it's used for this site) and it has a lot of example code for these techniques listed here. For more information, refer to the BlogEngine.core modules image.axd, css.axd, and js.axd.
Sample code from BlogEngine.Net CSS Handler
private static void SetHeaders(int hash, HttpContext context)
{
context.Response.ContentType = "text/css";
context.Response.Cache.VaryByHeaders["Accept-Encoding"] = true;
context.Response.Cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(7));
context.Response.Cache.SetMaxAge(new TimeSpan(7, 0, 0, 0));
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
string etag = "\"" + hash.ToString() + "\"";
string incomingEtag = context.Request.Headers["If-None-Match"];
context.Response.Cache.SetETag(etag);
if (String.Compare(incomingEtag, etag) == 0)
{
context.Response.Clear();
context.Response.StatusCode = (int)System.Net.HttpStatusCode.NotModified;
context.Response.SuppressContent = true;
}
}
Recommendations
- Minimize the number of HTTP requests by minimizing the unique content that must be loaded on a page.
- Set an expiration time to enable the cache to eliminate HTTP requests that would involve 304 responses. 30+ days for images, 1+ days for CSS and JavaScript files.
- Use Compression for page output, CSS and JS.
- Do not use compression for images (the algorithms for JPG, PNG already compress data for the image).
Search Terms
- ASP.net enable content expiration
- ASP.net expires header
- ASP.net 304 set expires time images
- ASP.net httphandler verb css
- HttpCacheability.Public
References
I've listed the articles that I found appropriate in my research on this topic.
- W3C Http 1.1 Status Code Definitions
- Caching in ASP.NET
- Reduce the weight of stylesheets by 35% at runtime - Mads Kristensen
- How to cache in ASP.NET
- How To Add Good Expires Headers to Images in Apache 1.3
- Stop Image Flickr With Cache Control Extensions (IE Only)
- How to Keep your CSS Visible (replace CSS images ~/ path)
- Add variables to standard CSS stylesheets in ASP.NET - Mads Kristensen
- Combine multiple stylesheets at runtime - Mads Kristensen
- Yahoo Rules for high performance web sites
- Performance Research, Part 2: Browser Cache Usage - Exposed!
- IIS7 Deployments calls for ETag Usage Review
- Internet Explorer 6 tweak guide
- Serving JavaScript Fast
- Enabling Client-Side Caching of Generated Content in ASP.NET
- Cache your site for faster loading and bandwidth saving
- Microsoft support article to remove etags in IIS
- Remove ETag Headers to Speed up Apache
- Apache mod_expires
- How Web Caches Work
- HTTP Compression Module
- Compression and performance - GZip vs. Deflate
- BlogEngine.Net
- Firebug
- Fiddler
- YSlow
Related Items
Images Part 3 - Windows Live Writer
Windows Live Writer provides a handful of helpful image enhancement features. It's not Photoshop by any means, but it's quick.
Drop Shadow
Photo Paper
Watermark
Polaroid Picture
The Windows Live Writer Polaroid Picture extension provides the ability to add a drop shadow, tilt pictures and add captions and change the text flow.
Related Items
Images Part 2 - Word
Word in Microsoft Office2007 provides the ability to post entries to websites and has outstanding image manipulation features. I love image manipulation in Word the drop shadow and reflection effects are simple, and quick.
Word does make the images fuzzy and grainy.
Shadow
Double Frame, Black
Rounded and Reflection
Bevel Rectangle
Perspective Shadow
Related Items
Images Part 1 - Snagit
A picture may be worth a thousand words, but it me takes about the same time or longer to edit images as it does to type. Snagit by TechSmith helps me a great deal.
Snagit is not a full photo editor by any means, but it does help provide some useful embellishments to images or screen shots without requiring a lot of work.
I love Snagit for three reasons.
- To capture scrolling windows (for web designs)
- To add annotation, drawing, and markup on the image
- The quick drop shadow effect
Key features I use:
- Edges- Drop shadow, fade, torn, wave, saw, shark tooth, beveled
- Watermark, resize, flip
- Image types: jpg, png, gif
Drop Shadow
Fade
Watermark
Shear
Related Items
Machine Wash Effect
Mister Retro has a great set of Photoshop plug-in's that will save a significant amount of time and effort when manipulating files in Photoshop for creating those textured and stunning artistic effects. Prices start at $49.95.
Machine wash CD 3 - Abusive Filter:
Machine Wash CD 4 - Brutality Filter:
Related Items
Font Tools
What The Font and Type Chart provide some useful interesting font tools.
What The Font does an image analysis and comes up with a list of potential fonts that are used in the image.
Type Chart provides a view of what the fonts will look like in Windows, on the Macintosh, and provides the CSS used for the examples.