CSS, JavaScript and XHTML Explained

Estelle Weyl’s Blog of quirks, random thoughts and funky finds discovered in day-to-day coding

 

Yet Another Image Replacement Method September 19, 2007

Filed under: Best Practices, CSS (including hacks), Web Development — Estelle Weyl @ 9:39 pm

Semantic CSS Image Replacement

Yes, "YAIRM" ("Yet Another Image Replacement Method") is a crappy acronym. Anyhow….

There have been several image replacement suggestions made over the past 5 years. Semantically, some just don’t make sense. Of course, the accessibility of your image replacement method and the semantic "correctness" has to do with how you code your HTML.

Pros

  • This method works for both in-line and block style elements.
  • Accessible to screen readers and non-image/non-screen media.
  • Does not add extra elements only for styling (no extra span).
  • Works cross browser

Cons

  • Using images for text does not allow for text resizing (like all IR methods).
  • Does not handle "images off/CSS on" scenario; but neither do most layouts with background images, such as the sidebar on this blog.

When I need to replace a header or some other text with an image, I simply give the element my image replacement class (<h1 class="imgreplacement">), and declare the background image, height and width I want to use either by providing an ID and defining the background image in the #id selector, or by targeting the element through specific/unique cascade. I place all of my image replacement css in a media="screen". Even though the media attribute is not heeded by all browsers, it is heeded by devices that are not screens. If your user than prints your webpage, the text that was replaced by an image in the browser will print as it semantically should.

The CSS for the Image Replacement class:

.imgreplacement {
  display:-moz-inline-box;
  display:inline-block;
  background:transparent none 0 0 no-repeat;
  text-indent:-3000px;
  font:0/0 Arial;
  overflow:hidden;
  color:rgba(255,255,255,0);
  vertical-align:bottom;
}

XHTML markup and CSS Overrides:

With my image replacement class, the image replacement method is reusable.

<h1 class="imgreplacment" title="Tool Tip Text here">Semantic Text</h1>
<a href="link.html" class="imgreplacement">Text that makes sense for this link</a>
<button class="imgreplacement" title="Close">Close Module</button>

h1.imgreplacement {
  background-image: url(path/headerimage.jpg);
  height: 60px;
  width: 540px;
	 background-position: 20px 10px;
}

a.imgreplacement {
  background-image: url(path/linkimage.jpg);
  width: 120px;
  height: 60px;
}

button {
  background-image:url(images/redx.gif);
  width: 18px;
  height: 18px;
  border: none; // overwrite default border
  cursor: pointer;
}

This is the button: . Note that is has layout, but it’s inline, and it has a tool-tip

Explanation of the Image Replacement Class:

The imgreplacement class does the following:

  • display:-moz-inline-box;
    and display:inline-block; displays the element as an inline block. inline-block is not part of the CSS specifications, but it is supported by IE and all other grade-A browsers other than Firefox. This enables the image replacement to work on inline elements by enabling them to have width and height. The first line, -moz-inline-box, is for mozilla based browsers that don’t render inline-block. The second line is for IE, Safari 3 and Opera, though IE does not render inline-block truly inline.
  • background: transparent none 0 0 no-repeat; sets a default to non-repeated background image placed at the top-left of the element block, but does not declare a background image, enabling you to overwrite the none with an image via a second, more precise, CSS declaration
  • text-indent:-3000px; Text indent only applies to block elements. text-indent, when implemented, moves the start of the first line of text to the left or right depending on whether the property is assigned a negative or positive value. The text-indent is applied to inline-block elements, but not to -moz-inline-box. Note that IE does not render text-indent correctly, so generally I override the text-indent property for IE, but in this case the disappearing text quirk is to our benefit.
  • font:0/0 Arial; Makes the font tiny or invisible for browsers. There are a few quirks: Opera doesn’t render this shorthand, and renders font-size: 0; at about 7px; IE6 and IE7 both render the font at about 1px and Safari doesn’t render font at size 0, but does intermittently underline the non-visible character at about 1px width per character.
  • overflow:hidden hides anything that might be wider than the space provided. IE6 has the bad habit of deciding to grow elements to fit the content even if the size of the element is defined.
  • color:rgba(255,255,255,0); Makes the font color transparent (opacity of 0) for those browsers that understand opacity via RGBA, which is a feature of CSS3 (Safari 3 and pre-alpha version of Firefox 3, but not IE6, IE7 or Firefox 2 for Windows).
  • vertical-align:bottom; is required for the inline elements - it places them at the same level vertically with respect to the text around it across all grade-A browsers.

Additional tidbits

  • You have to define the width, height and background image of your element.
  • If needed, you can set the background position of the replacement image. It causes fewer cross browser issues to place the background image rather than setting margins due to differences in browsers interpretations of the box-model.
  • Remember to use sematic markup. If the image is an area header, use h1-h6. If it’s a link going somewhere, use <a>. If it isn’t linking anywhere, it’s not a link!
  • You can enhance the image replacement with a title. The title will display in some browsers as a tool tip. This may enhance the accessibility for those who use tooltips regularly.
  • You can declare a different background image using the :hover pseudoclass, so when the user hovers over the element with the mouse pointer, the image changes.

While I just showed you a method of doing image replacement, I must caution against it. Using images for text is not optimum for accessibility. This method enables assistive devices to read your text with the semantic meaning defined by the encompassing element(s). This method enables users of alternative devices, such as cell phones, and text-only browsers to read your content. It also meets web standards in terms of separating content from presentation. However, when you use images to render text, your visitor is unable to control the font-size; which makes your site less than accessible. If you are required to use images instead of text to render content, and you can’t convince your client (boss, designer or contractee, or even yourself) of the stupidity (there, i said it) of using images for text, then this is the best method of making your inaccessible page accessible to the most people. Just try to make the text in your image large enough to be read by a user.

 
 

JavaScript Date Object Methods September 5, 2007

Filed under: JavaScript, Web Development — Estelle Weyl @ 11:44 pm

Methods of the JavaScript Date Object

This is the second half of a two part discussion of the javascript date object. The first half discusses creating, formatting, extending and converting the date object. This section focuses solely on the methods of the javascript Date oject. In the prior section we created a working and accurate date object. There is a great deal written on the methods of the Date object, but there were very few examples. As this is an entry about JavaScript, you will need to have javascript enabled to learn from this tutorial. There are examples. of all the methods: see below:

dt {font-family:”Courier New”, Courier, mono; font-weight:bold;padding-top: 8px; padding-left:8px;}

I will be using three sample dates for the following examples:

  • var auntsBirthday = new Date(”September 4, 1902″);
  • var currTime = new Date() // your computer’s time
  • var myTime = new Date(2003,8,21); // September 21, 2003

When we get to the setMethods, the dates will be changed as we set different values.

prototype
The prototype property is used to assign new properties and methods to instances of the Date object
See Date.prototype.customFormat(datestring) in javascript date object tutorial.
constructor
A reference to the function that created the instance of a Date object. Can be used to test if a variable is a Date.
if (myTime.constructor == Date) {}
parse(string)
The millisecond equivalent of the date specified in the correctly formatted string parameter.

UTC(year, month [, date, hours, minutes, seconds, ms])
Returns an integer — the UTC millisecond value of the date specified as parameters. The parameter values for the UTC() method must be in UTC time for the returned value to be accurate. This method does not generate a Date object. The Year and Month are required. The other parameters are optional. I have no clue why anyone would use this. Please let me know via comments. The difference between UTC and getTime(); may be the offset from GMT. I need to look more into this.
toString()
Returns a string value of the date. Different browsers return different strings, and usually the string value is returned in a format that is not suitable to return raw to the user.
toDateString()
Returns the date portion of an instance of a Date object as a string. The format is under the control of the browser, so I prefer the customFormat method.
toTimeString()
Returns the time portion of the instance of a Date object as a String. The format depends on the browser and language so I prefer the customFormat method.

toLocaleString()
Returns the local time zone value of both the date and time. The format may be localized, so this may be useful for internationalization. I prefer, again, to rely on an internationalized version of the customFormat, but I probably shouldn’t.
toLocaleDateString()
Returns the date portion of an instance of a Date object as a String. The format is based on the browser and language and differs between some browsers, so I prefer the customFormat method.

toLocaleTimeString()
Returns the time as a String, with the format controlled by the browser and language.
valueOf()
Returns the value of the instance of the date object as an integer in millisenconds from Jan. 1, 1970.
getTime()
Returns an integer — the number of milliseconds since January 1, 1970, to the date specified by the instance of the Date object. I do not know how this differs from valueOf()
getFullYear()
Returns an integer representing the actual year for the date. Use this instead of getYear()
getUTCFullYear()
Returns the year for the date of the instance of the Date object in the UTC time stored internally by the browser. My guess is that this only differs from getFullYear when it comes to December 31 and January 1.
getMonth()
Returns the integer corresponding to the month value for the date specified by the instance of the Date object. Avoid logic errors: remember that arrays start with zero, so this returns an integer 0 - 11. January is 0 and December is 11.
getUTCMonth()
Returns the integer corresponding to the month value for the date specified by the instance of the Date object. Avoid logic errors: remember that arrays start with zero, so this returns an integer 0 - 11. January is 0 and December is 11. The difference between getMonth() and getUTCMonth is that the UTC time stored internally by the browser.
getDate()
Returns the day of the month, 1 - 31, specified by the instance of the Date object.
getUTCDate()
Similar to getDate(), for the UTC time stored internally by the browser.
getDay()
Returns an integer between 0 to 6, corresponding to the day value for the date specified by the instance of the Date object. Avoid logic errors: remember that arrays start with zero: Sunday is 0, Saturday is 6.
getUTCDay()
Returns an integer between 0 to 6, corresponding to the day value for the date specified by the instance of the Date object for the UTC time stored internally by the browser. Avoid logic errors: remember that arrays start with zero: Sunday is 0, Saturday is 6.
getHours()
Returns the integer, 0 - 23, for the hour of the day specified by the instance of the Date object, using the 24-hour time system.
getUTCHours()
Returns the integer, 0 - 23, for the hour of the day specified by the instance of the Date object, using the 24-hour time system.(the UTC time stored internally by the browser).
getMinutes()
getUTCMinutes()
Returns an integer, 0 - 59, representing the minute value for the hour specified by the instance of the Date object.

getSeconds()
getUTCSeconds()
Returns an integer, 0 - 59, the seconds past the last full minute as specified by the instance of the Date object.
getMilliseconds()
Returns an integer, 0 - 999, the milliseconds past the last full second as specified by the instance of the Date object.
getUTCMilliseconds()
Same as above, for the UTC time stored internally by the browser.
getTimezoneOffset()
Returns an integer betweeing -720 and 720 corresponging to minutes between your the site visitor’s computer and GMT. If your visitor is west of GMT, getTimezoneOffset() will return a positive values; negative values for east of GMT. Note: this returns the value in minutes — beware of logic errors!.
setTime(time)
Takes as a parameter an integer of milliseconds. Sets the date instance to the number of milliseconds from January 1, 1970. A negative integer will be before 1/1/70, a positive integer will return a date later than 1/1/70. Returns the milliseconds from 1/1/1970

setMilliseconds(ms)
setUTCMilliseconds(ms)
Takes as a parameter an integer of milliseconds. Sets the milliseconds of the date instance to the number of milliseconds from the current second. If the number is greater than 999, or less than 0, the rest of the time stamp will be effected: not just the millisecond count. It returns the milliseconds not of the parameter passed, but rather the milliseconds since 1/1/1970, midnight, GMT. The first example removes one year worth of milliseconds from the millenium date instance. The second example adds 1500 milliseconds, or 1.5 seconds. Do take a look at setUTCMilliseconds for an interesting tidbit… the “from the current second” above is quoted for a reason. You’ll note from the getMilliseconds() that this is indeed “from the last second”, and not simply an addition of milliseconds. In the test value for setMilliseconds(), the last four digits of the return value is 1500 - the milliseconds that were added. In the example for setUTCMilliseconds(), the number of milliseconds subtracted is subtracted from the seconds set above, not the milliseconds, as would seem logical

setSeconds(sec [, ms])
setUTCSeconds(sec [, ms])
Takes a required seconds as integer parameter and an optional milliseconds as integer parameter. If a float is passed as a parameter, a parseInt is automatically performed prior to setting the time. Returns the number of milliseconds from 1/1/70 GMT

setMinutes(minute [, sec, ms])
setUTCMinutes(minute [, sec, ms])
Takes a required parameter of seconds as an integer (performs the equivalent of Math.floor if the parameter is a float), and optional integer parameters of seconds and milliseconds. If you are going to define milliseconds, you must pass a seconds parameter. Returns the number of milliseconds from 1/1/70 GMT.

setHours(hour [, minute, sec, ms])
setUTCHours(hour [, minute, sec, ms])
Takes a required parameter of minutes as an integer (performs the equivalent of Math.floor() if the parameter is a float.), and optional integer parameters of minutes, seconds and milliseconds. If you are going to define milliseconds, you must pass minutes and seconds parameters. Returns the number of milliseconds from 1/1/70 GMT. The third example shows what happends when your integers are logic errors. The fourth example demonstrates that if a parameter is NaN, the function sets the date to NaN, and returns NaN

setDate(dateInt)
setUTCDate(date)
Sets the date of the month. The dateInt parameter should be in the form of an integer. If there is a logic error, such as 31 for June, the Date object calculates it and will return July 1. This sets the date, so your date object is changed. It also returns the new date in milliseconds. Note that in the third example, depending on your time zone, you may get the last day of last month.

setMonth(month [, date])
setUTCMonth(month [, date])
Sets the month, and, optionally, the day in the month. The month parameter should be in the form of an integer. Remember that the month array starts at O, so currTime.setMonth(2) will set the month to the third month, which is March. If there is a logic error, and your month int is not between 0 and 11, then the year will be set too.

setFullYear(year [, month, date])
setUTCFullYear(year [, month, date])
Sets the year, and, optionally, the month and the day in the month. The year parameter should be in the form of an integer. See quirks about the month in the setMonth() explanation. Note that the method reads “setFullYear(),” which is different then the setYear method. Since the difference is important to remember, I’ll compare the two in the examples. The setYear() adds 1900 years for any year between 0 and 100, whereas setFullYear() sets the year to whatever integer is passed.

toUTCString()
Taking no parameters, this method does not alter the date object: it simply returns the UTC value of the Date instance in standard string format: the day of the week abbreviated … well, look at the example. You’ll notice currTime has not been altered, and the return value is the same value, but presented in the UTC time zone rather than the user time zone. This method is for newer browsers than the toGMTString();, so it is recommended that you use this method over the GMT method below.

toGMTString()
Taking no parameters, this method does not alter the date object: it simply returns the value of the Date instance in standard string format. I saw no difference between the toUTCString() and toGMTString() methods.


getYear()
You don’t want to use this. Instead, use getFullYear(). Why? for years between 1900 and 1999, the getYear() method will return an integer between 0 and 99. This method does not alter the date instance. It takes no parameters. It returns an integer. Don’t use this method.

setYear(year)
Sets the year. The year parameter should be in the form of an integer. If (0<=year && year<100), setYear() adds 1900 to the year passed as the parameter. It is recommended to not use setYear(). Instead, opt for the setFullYear() method. Returns the new date instance value in milliseconds since 1/1/1970.

Notes:

  • getFullYear() and getYear() are NOT the same. getFullYear() is the actual year. getYear() is years since 1900.
 
 

Favicons: why and how to create favicons September 3, 2007

Filed under: Best Practices, Cursors & Icons, SEO, Web Development — Estelle Weyl @ 9:35 pm

The "WHY" of Favicons

Favicons ARE an integral part of your website and branding.

Favicons are the single most important graphic appearing on a website. While that sounds like a strong statement, it’s true. Favicons are the least expensive and most overlooked visual branding opportunity.

Favicons are the 16 x 16 pixel images that show up in the navigation bar of your browser. They also appear in browser’s bookmark/favorites menu. You might think, "big whoop! that’s not vital." But those aren’t the only places they appear.

They also appear at the bottom of my blog: not my favicon, but the favicon for stumbleupon, digg, technorati, del.icio.us, etc. Web developers and copy editors don’t even need to use the names of those online brands: everyone recognizes these networking favicons.

They now also appear next to the page title on the tabs in tabbed browsers: if a user has 25 browser tabs, each tab may be as narrow as just the favicon: would you prefer your visitors see Internet Explorer’s blue E, Safari’s blue compass, an icon of a page (Firefox and Opera), or would you prefer that they see your logo? If they see a logo, they recognize immediately what site is opened in each tab: you want to be one of those recognized pages.

Are you looking at your open browser tabs? Can you tell which pages are which? Have you checked your bookmarks list? Are there some bookmarks that stand out more than others? Have you looked at the bottom of this blog entry? Depending on how many toolbars you have downloaded and have open, you may have a plethora of favicons there too. So, have I convinced you?

The "HOW" of Favicons: How to design & create a FavIcon:

Designing a Favicon:

  • If you have a logo that easily translates into something that looks decent at 32 x 32 or 16 x 16, use it.
  • If you can avoid using the color blue, especially the glassy shiny blue of IE, avoid using it.
  • Keep it simple. Yahoo uses a Y!, Google uses a G. Flickr uses two little circles. Delicious is a square made of 4 squares. IE is an E. These are all ones you know.
  • If your logo is very complex, try using just a part of it such as the first letter. If your first letter doesn’t represent your company well enough (like in the case of this blog), use your logo color to abstract an image.

Creating a FavIcon: Converting an image to a .ico

  • Following the suggestions above, create a 48×48 or a 32 x 32 image that you will use as your favicon. Save it.
  • If you have photoshop, you can download a Favicon extension for Photoshop. If you don’t have photoshop, or don’t want to deal with extensions, you can visit Dynamic Drive and use their tool to convert your .jpg, .png or .gif into a .ico file. The file created will be called favicon.ico. You will be directed to download it.
  • Upload the .ico file to the root directory of your website.
  • If your favicon is named favicon.ico, then you don’t need to add code. However, if you don’t have the .ico file in your top level directory, or if you saved it under a different file name, or if you have different favicons for different parts of your site (not usually a good idea, but Yahoo has different icons for some of their properties, such as Yahoo! answers), then include the following in the header:
     

    <link rel="shortcut icon" href="http://www.mysite.com/myicon.ico" type="image/x-icon" />

Uses of Favicons

Now your favicon can appear all across the web: