CSS margins study

CSS coding delivers more “WTF moments” than any other work activity I engage in these days.  I need to understand it better, specifically CSS margins and floats. Made some time today to study up.

I read and re-read the articles below. They are aging but speak to a time when the evil IE6 was even more prominent than it is years later in 2009.

General insights include:

  • Kill IE’s double margin bug with display:inline on a floated items.
  • When 2 adjacent elements’ margins meet, only the bigger margin is used.
  • If an item’s 2 opposite margins meet, they both go away (self-collapse)
  • Nested items without padding or border will cause the top and bottom margins of all to collapse. Left and right margins remain. Adding padding or border makes the margin come back.
  • Set overflow:hidden on columns to prevent object blow out in IE.
  • To make columns, float:left on one and float:right on the other.
  • Self clear an object (always clear floats) with the :after filter.  (Example below.)
  • Center an item by setting auto on left and right margins.  margin:0 auto.
  • In addition to auto margins, to center an item in IE, also use text-align:center on parent, then reset text-align in child, usually text-align:left.

Self clear example

.columns:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}

Convert a list into a horizontal menu

Using background images instead of text.  Fixed width, left margins, using negative margin on UL to cancel first margin.

<ul class="menu">
<li><a href="#somewhere1" id="link1"><em>link 1</em></a></li>
<li><a href="#somewhere2" id="link2"><em>link 2</em></a></li>
<li><a href="#somewhere3" id="link3"><em>link 3</em></a></li>
</ul>

ul.menu {
margin:0 0 0 -20px;
float:left;
width:100%;
}
ul.menu li {
list-style-type:none;
display:inline;
float:left;
margin:0 0 0 20px;
}
ul.menu li a {
display:block;
height:50px;
background-color: #0f0;
}
ul.menu li a em {
display:none;
}
ul.menu li a#link1 {
width:100px;
background-image: url(link1.png);
}
ul.menu li a#link1:hover {
background-image: url(link1-over.png);
}
ul.menu li a#link2 {
width:110px;
background-image: url(link2.png);
}
ul.menu li a#link2:hover {
background-image: url(link2-over.png);
}
ul.menu li a#link3 {
width:120px;
background-image: url(link3.png);
}
ul.menu li a#link3:hover {
background-image: url(link3-over.png);
}

Cartooned myself

I used to draw a lot.  Unfortunately it’s all too rare these days.   When I do, it’s exciting, but always a little like starting over again.

Today I put Wacom pen to tablet again.  I thought the results were sharable.  It is a cartoon of myself as my alter ego for his website.

I didn’t bother removing the beer belly; I think it adds character.

Included a couple of the early stages as well.  That way, if you think the end product is bad, at least you know at some point it was even worse.

Twitter is good for something

Good news. I don’t obsess over my 353 feeds anymore.

Bad news.  Now I just skim them to get material for my latest obsession, Twitter.

As of now, 2,398 wonderful people follow me.  Each day I look for more people to follow.  Each day I unfollow unfollowers.

Why are so many people following me?

  1. They want me to follow them.
  2. I contribute often and try to not be annoying.
  3. I follow lots of new people every day.

Read more

PHP filter_var, where have you been all my life?

Stumbled on something handy that I can’t believe I’m just now finding.  Gotta love PHP convenience, including this built-in way to validate form input.

PHP filter_var

Thanks again, NETTUTS (tutorial here).

if (isset($_POST['email'])) {
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo "$email is a valid email address.";
} else {
echo "$email is NOT a valid email address.";
}
}
// also FILTER_SANITIZE_URL, FILTER_VALIDATE_URL

Coding email templates

I’ve written a couple email engines in my day – one in PHP and one in ASP – to integrate and automate businesses with email marketing.  Work to be proud of, indeed. Invariably after the engine part is done – or maybe you’re using an established service* for the engine part – there needs to be some content, some email design.

*Examples of consumer email marketing services (“engines”) using email templates and data merging:

Templates are for branding

HTML templates need to be made so the emails that are received are branded – at least with a logo and company colors.  This is not possible with a plain text email of course.

Merging process

The engine will take the templates and merge in some variables like “first name”, “email to”, “email from”, etc – a basic find-and-replace loop.  The HTML template will contain placeholders for each variable – strings like “{#EMAIL_TO#}” – and the loop will replace those with values from the database, then send the post-merged email to that person in the mailing list.

Email formats

There are many ways an email can be formatted such as “quoted-printable”, “text/plain”, and embedded images, but my focus is on “text/html” with linked images.  Here is a handy site that can convert static HTML into quoted-printable format, and back.

Images

The images will be stored on a server and referenced like any other web page would reference images.

Privacy and missing images

Some email viewers like Gmail tend to hide images that link back to a server, and the user has to click a “display images” link to see the email as it was intended.  This is a privacy feature because images that link back to the server provide the sender with a method for tracking who opens the email.  The log can be parsed to see who requested the image when the email was viewed.

We need to make the design look good even if all the images are missing.

alt attribute

For this reason, be sure to fill your image tags with good descriptive “alt” values so those users still know what they’re not seeing.  Putting “please display images”  in the “alt” attribute is a consideration, but might also be a flag to the program that the message is spam.

Tables

Today web designers use style sheets instead of tables for positioning content.  CSS-heavy, un-tabled code may be a good idea for modern web sites, but not for HTML email templates.  Email templates rely primarily on tables for positioning content, making columns, aligning text, etc.  This is simply because the email could be viewed in any number of applications, with a high likelihood of poor CSS support, even in modern email clients such as Outlook 2007 (whose rendering engine is Word, of all things).  Tables are “old school” web design, and so are email templates.  Being a CSS guy, I just have to suck up that reality.

Put CSS in style attribute

This isn’t to say that one should abandon CSS in email templating altogether.  In fact, feel free to use the “style” attribute – just back it up with the non-CSS way too, as insurance.

If the cell needs a background, use “style=background:url(some image path)” in addition to “background=(some image path)”.  If the font needs a color, use “style=color:red” in addition to “<font color=#ff0000>”.

Go attribute-crazy

The more attributes each table cell has, the better.  Don’t forget attributes such as “height”, “width”, “background”, “bgcolor”, “align”, “valign” and even CSS’s “style”.  You’ll thank yourself when testing in even the latest browsers and email clients.

Always use the “align” attribute in cells with text.  I can’t tell you the numbers of times I’ve seen Internet Explorer “center” text that “left-aligns” in Firefox. Setting “<td align=left..” fixes this.

Stay aware of the design affects of merging in variable data that could reflow text and images.  When columns are growing and shrinking with variable content, and you want the content to “top-align,” use “<td valign=top..”.  Otherwise there tends to be rarely-desirable vertical centering.

Variable images

If your variable images are variable sizes, heaven help you.  If necessary resample all the variable images – perhaps with ImageMagick – to give them the same widths or heights – whichever dimension flows best in your design.  Whatever table cell is containing your image should still have the height and width set.

spacer.gif

A spacer.gif is a 1×1 transparent GIF that can be resized to enforce the size of an empty table cell.

Remember those?  You’ll wanna pull those out from the back of the toolbox to help pad your tables.  Tables + spacer.gif is the “old way” but it’s the “right way” when it comes to making email templates.

If I have an email with 2 columns and padding in between, I will use a 3 column table with all cells’ widths, aligns, valigns set, and put a spacer.gif in the center “padding cell” that is the same width as the padding should be.  The height of the spacer.gif can remain 1px.

Spanning

If you find yourself using “colspan” or “rowspan”, don’t.  Instead, nest tables.  It’s sounds like such a naughty thing to say, but that’s the most dependable way to go.  Go nested-table crazy! We can’t give the cell dimensions any leeway.  Spanning cells tends to produce more random cell dimensions than the predictibility of nested tables.

Table setup example

Here’s a good set up for a centered, 650px-wide table.

<table cellspacing=”0″ cellpadding=”0″ border=”0″ align=”center” width=”650″>

“cellspacing”, “cellpadding” and “border” need to be set. Assume nothing about any dimension.  Be explicit everywhere.

Testing

Don’t forget to test in multiple browsers, and multiple email clients. This is where we see how necessary all the excessive table markup was.

Here’s a few email clients to consider:

  • Outlook 2007
  • Older Outlooks
  • Gmail
  • Yahoo Mail
  • Apple Mail
  • Hotmail

Just because the email client is web-based doesn’t mean it is just as CSS-compatible as a you’d expect.  Sometimes the CSS is rewritten to prevent style conflicts with the web page it is presented in.  We would hope that the rewriting will not be harmful to your CSS, but I wouldn’t bet on it.  Best to take the hybrid route so we won’t have to worry about it.

Conclusion

Email template design is an aging art with the advent of Web 2.0 social marketing tools, but it still reaches the most people wherever they may be online.  Deploying age old web design techniques is still the best way to code an email template so that it looks the same in most people’s email clients.

Ranking, Blog Code, Custom Search, Firefox Add Ons

Improving your site’s Alexa Rank and Google PageRank, showing code in your blog posts with syntax highlighting and line numbers, creating a custom Google search box for your website, surviving and thriving in Google Reader using PostRank, and exploring Firefox addons for web developers including GreaseMonkey and Web Developer.

Source code in blog posts:

Ranking:

Google Custom Search

Toolbars:

Firefox Add Ons:

jQuery Experimenting:

New for August 2008

Designed a little blue gray theme and unified the tutorial pages.

dvvcom 200808

Javascript Keyword or Tag List Delimiter Changer

Ever have a long list of tags or keywords for your story, and each social bookmarking site you submit to needs different delimiters for your tags or keywords? Here you go.

Keyword or Tag List Delimiter Changer

Drawing: Birdball

Sketch and final of a bird-man creature in action with a basketball.

Passing Data with AJAX, Sessions, Cookies, and GET and POST Requests

Demo
http://www.davidvanvickle.com/examples/ep8/index.htm

Download
http://www.davidvanvickle.com/examples/ep8/ep8.zip

Web pages can be highly dynamic. We can log in to a site and get relevant data like a bank balance or see our social network friends – information specific to us. That means our page requests to the server are identified as being ours and the server can compile something with our data in it.

The internet’s way of communicating (“hypertext transfer protocol” or HTTP) is stateless. That means, on it’s own, it doesn’t remember the visitor from one page to the next. It just sends anonymous requests to the server, and the server sends back that static page. Fortunately there are a few mechanisms for distinguishing one request from another, which allows us to make web pages more personalized.

One mechanism is the cookie. Cookies are strings of text stored by the browser. A cookie allows the browser to remember things between pages. A common use of cookies is with sessions. When you visit a web site, you are in a session with that web site. Cookies are sent from the site and contain data specific to that session, such as a session ID. The browser receives and stores the cookie, then sends it back to the web site every time a new page is requested. So now the server, on some level, knows who is asking for what. The server can respond differently depending on the cookie value sent from the browser.

Use Javascript to access cookies on the client-side.

alert(document.cookie);

Here is a Javascript object for reading, writing and deleting cookies.

http://www.davidvanvickle.com/examples/ep8/index.htm
http://www.davidvanvickle.com/examples/ep8/ep8.zip

CookieHandler Example

var C = new CookieHandler();
C.set(‘mykey’, ‘myvalue’);
alert(C.get(‘mykey’));
C.del(‘mykey’);

The problem with using cookies is that the user can always disable them, so you have to make sure your client side app doesn’t break when that happens. Either that or you tell users up front that javascript and cookies must be enabled to use your application.

From the server side perspective, when cookies are not available, the server has to come up with another way to track session id’s. Without cookies, the session ID must be embedded in a different part of the page request. There are a couple methods to request information from a server. One is called a GET and the other is called a POST.

GET

Using a GET request means that data is attached to the URL after the question mark. This looks like “page.php?session=mysessionid”. Multiple bits of data can get strung together after the question mark with ampersands like “page.php?key1=value1&key2=value2”.

Usually this data is read on the server side, but Javascript on the client side can parse these GET query strings as well.

The following Javascript code can read the data sent with the GET method.

http://www.davidvanvickle.com/examples/ep8/index.htm
http://www.davidvanvickle.com/examples/ep8/ep8.zip

QueryStringReader Example

var qsr = new QueryStringReader();
var key1 = qsr.get("key1");
var key2 = qsr.get("key2");
if (key1) alert(key1);
if (key2) alert(key2);

POST

Using a POST request puts data in another part of the request packet and is generally preferred when more than a few pieces of data need to go back to the server. When a user uses a search field, often a GET is used as there are only a couple fields of data to transfer. But when a larger order form is used, it will tend to POST since there is more data to pass. When files such as images need to be sent from the client to the server, the POST method is always used. Javascript does not have access to POST data, only to GET data.

AJAX

Requests aren’t restricted to when the user goes between pages. Javascript can send it’s own requests behind the scenes within a single page. This is how AJAX works. Javascript does a GET or POST request from inside the page and gets an XML response from the server. The Javascript receives the XML, parses it, and changes the page layout somehow, all without the page having to reload. That’s AJAX. There is a great AJAX quick start tutorial on Mozilla’s developer wiki. A link to it is available in the show transcript at Podturtle.com.

http://www.davidvanvickle.com/examples/ep8/index.htm
http://www.davidvanvickle.com/examples/ep8/ep8.zip

var httpRequest;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
httpRequest.onreadystatechange = function() { alert(httpRequest.responseText); };
httpRequest.open('GET', ‘data.xml’, true);
httpRequest.send('');

Sessions

The most reliable and easy way to deal with sessions is to use the built in session handling of modern server side scripting languages such as PHP and ASP. There will be an object dedicated to keeping track of the session for us. And we get to store whatever we want in that temporary session data. A server side programmer can trust the server to maintain that session for the user however it needs to, via cookies or via GET requests. It’s automatic.

PHP

session_start();
$_SESSION[‘mykey’] = ‘myvalue’;
echo $_SESSION[‘mykey’];

ASP

Session(“mykey”) = “myvalue”
Response.write(Session(“mykey”))

Similarly, methods for getting GET and POST data from requests are also handled very easily with server side scripting languages.

PHP

echo $_GET[‘mykey’]; // GET
echo $_POST[‘mykey’]; // POST

ASP

Response.write(request.querystring(“mykey”)) ‘ GET
Response.write(request.form(“mykey”)) ‘ POST

Whether you plan to program on the client side or the server side, learning how to pass data between pages is the first step to making your web apps interactive and personalized.

Return top