<?xml version="1.0" encoding="iso-8859-1" ?>
<rss version="2.0">
<channel>
<title>NealGrosskopf.com - Geek Speak</title>
<link>https://www.nealgrosskopf.com/tech/</link>
<description>a NG Designs Website...</description>
<language>en-us</language>
<copyright>Copyright .#169; 2008 NealGrosskopf.com</copyright>
<lastBuildDate>Sat, 04 Apr 2026 12:51:02 -0500</lastBuildDate>
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>NealGrosskopf.com RSS Generator</generator>
<managingEditor>Neal Grosskopf</managingEditor>
<webMaster>Neal Grosskopf</webMaster>
<image>
<title>NealGrosskopf.com</title>
<url>https://www.nealgrosskopf.com/files/ico/favicon.ico</url>
<link>https://www.nealgrosskopf.com</link>
</image>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2012-05-22 07:40:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=81</link>
<description>
<![CDATA[
<figure class="image-caption">
    <a href="http://www.nealgrosskopf.com/tech/resources/81/"><img src="http://www.nealgrosskopf.com/tech/resources/81/example.png" alt="Font Weight Bug: IE9 vs Firefox"></a>
    <figcaption>
        <h3>IE9 vs Firefox</h3>	
        <p>Above is a comparision of IE9 and Firefox. As you can see, IE9 was bolding the font much larger than Firefox and other browsers and causing it to misrender on the page. <a href="http://www.nealgrosskopf.com/tech/resources/81/">View a demo of this effect &gt;&gt;</a></p>
        <p class="b i">Note: Remember to view demo in IE9.</p>
    </figcaption>
</figure>

<h4>Re-Education</h4>

<p>Before jumping to the solution, we should first re-review the <samp>font-weight</samp> CSS property. Historically speaking, we've used <samp>font-weight: bold;</samp> and occasionally <samp>font-weight: normal;</samp> to reset an element's font-weight. Eventually numeric values were added that allow us to pick font-weights ranging from <b>100 to 900</b>.</p>

<p>Numeric font-weights definition from <a href="https://developer.mozilla.org/en/CSS/font-weight">Mozilla's development network</a> is as follow:</p>

<blockquote>
    <p>Numeric font weights for fonts that provide more than just normal and bold. If the exact weight given is unavailable, then 600-900 use the closest available darker weight (or, if there is none, the closest available lighter weight), and 100-500 use the closest available lighter weight (or, if there is none, the closest available darker weight). This means that for fonts that provide only normal and bold, 100-500 are normal, and 600-900 are bold.</p>
</blockquote>

<h4>Font-Weight Keyword Values</h4>

<p>Like other property values in CSS, there are also keywords that can be used for font-weight. Historically, we've all been using bold as the de-facto font-weight, but each keyword behind the scenes maps to a numeric value.</p>

<h4>font-weight: lighter</h4>
<blockquote>
    <p>One font weight lighter than the parent element (among the available weights of the font).</p>
</blockquote>

<h4>font-weight: normal</h4>
<p>The <samp>normal</samp> keyword corresponds to the numeric value of <b>400</b></p>

<h4>font-weight: bold</h4>
<p>The <samp>bold</samp> keyword corresponds to the numeric value of <b>700</b></p>

<h4>font-weight: bolder</h4>
<blockquote>
    <p>One font weight darker than the parent element (among the available weights of the font).</p>
</blockquote>


<h4>The Solution: Reseting Element's Default Font Weight</h4>

<p>Historically, there have been a handful of elements in HTML that are rendered as bold by default. In IE9, if you happen to nest any of these elements within another bold element, the double-bold font effect occurs.</p>

<p>Below we have a <samp>TH</samp> element with a <samp>H3</samp> nested inside of it. This will trigger the double bold effect in IE9:</p>

<code>
&lt;table&gt;
	&lt;tr&gt;
		&lt;th&gt;&lt;h3&gt;Table Column Heading&lt;/h3&gt;&lt;/th&gt;
	&lt;/tr&gt;
&lt;/table&gt;
</code>

<p><a class="button" href="http://www.nealgrosskopf.com/tech/resources/81/">View Example of This In IE9 &raquo;</a></p>

<p>What appears to be happening in IE9 when nesting bold elements, is it's changing their font-weight from bold/700 to bolder/900.</p>

<p>To overcome this undesired effect, simply reset all of the standard bold elements back to <samp>font-weight: bold</samp>:</p>

<code>
th,
b, strong,
h1, h2, h3, h4, h5, h6
{
font-weight: bold;
}
</code>

<p>Voila! Problem solved! </p>

<h4>Further Reading</h4>

<ul>
    <li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=589365">Bugzilla - strong and b are cumulative with Arial</a></li>
    <li><a href="http://lists.w3.org/Archives/Public/public-html/2011Feb/0373.html">W3C - New: b and strong should be font-weight: bolder, not font-weight: bold. IE9 RC, Firefox 4b11, and WebKit all agree, with only Opera differing.</a></li>
    <li><a href="https://developer.mozilla.org/en/CSS/font-weight">Mozilla Developer Network - font-weight</a></li>
</ul><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=81">View Comments [8]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=81</guid>
<author>Neal Grosskopf</author>

</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2011-11-01 07:32:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=80</link>
<description>
<![CDATA[
<p>I'm not going to lie, using nth-child has always made my brain hurt when using it in CSS. Maybe it's the fact that math is involved and for the most part, I can avoid math in most other areas of CSS except this. I'm certainly not the <a href="http://reference.sitepoint.com/css/understandingnthchildexpressions#understandingnthchildexpressions__para_resultsettableintro">first</a> <a href="http://css-tricks.com/5452-how-nth-child-works/">person</a> to take a crack at explaining it but I thought I'd give it a try.</p>

<p><img src="http://www.nealgrosskopf.com/tech/resources/80/article-image.png" class="article-teaser" alt=""></p>
<p class="center"><a href="http://www.nealgrosskopf.com/tech/resources/80/" class="button">View the Nth-Child Visual Calculator &raquo;</a></p>

<h4>Simply Algebra</h4>

<p>Using nth-anything in CSS takes many of us back to our 9th grade Algebra class. The reason for this is the formula used for nth-child uses "variables". These are represented as <samp>n</samp>. The example below is an example:</p>

<code>
ol li:nth-child(2n+1)
{
...
}
</code>

<h4>Nth-Child Iteration Table</h4>

<p>Below is a table illustrating how our formula above works. It will loop until there are no more elements to loop through using the base selector <samp>ol li</samp></p>

<table class="data">
<caption>Nth-Child Iteration Table</caption>
<tr>
    <th>N</th>
    <th>Nth-Selector</th>
    <th>Math Formula</th>
    <th>Result</th>
</tr>
<tr>
    <td>0</td>
    <td>2n+1</td>
    <td>2 * <b>0</b> + 1</td>
    <td>1 (first element)</td>
</tr>
<tr>
	<td>1</td>
    <td>2n+1</td>
    <td>2 * <b>1</b> + 1</td>
    <td>3 (third element)</td>
</tr>
<tr>
	<td>2</td>
    <td>2n+1</td>
    <td>2 * <b>2</b> + 1</td>
    <td>5 (fifth element)</td>
</tr>
<tr>
	<td>3</td>
    <td>2n+1</td>
    <td>2 * <b>3</b> + 1</td>
    <td>7 (seventh element)</td>
</tr>
<tr>
	<td>4</td>
    <td>2n+1</td>
    <td>2 * <b>4</b> + 1</td>
    <td>9 (ninth element)</td>
</tr>
</table>

<p>The selector <samp>ol li:nth-child(2n+1)</samp> will therefore select every <b>odd</b> element in the ordered list.</p>

<h4>Keywords</h4>

<p>CSS also has some keyword values that can be used for nth-child to make writing the formulas easier for common nth-child selectors:</p>

<code>
ol li:nth-child(even)
{
...
}

ol li:nth-child(odd)
{
...
}
</code>

<h4>Common Nth-Child Selectors</h4>

<p>A quick shortcut to remember if you want to select every "x" element is to take the number you're looking for and multiply it times <samp>n</samp>.</p>

<table class="data">
<caption>Common Nth-Child Selectors</caption>
<tr>
    <th>Child</th>
    <th>Selector</th>
</tr>
<tr>
    <td>Every Second Element</td>
    <td>ol li:nth-child(2n)</td>
</tr>
<tr>
    <td>Every Third Element</td>
    <td>ol li:nth-child(3n)</td>
</tr>
<tr>
    <td>Every Fourth Element</td>
    <td>ol li:nth-child(4n)</td>
</tr>
<tr>
    <td>Every Fifth Element</td>
    <td>ol li:nth-child(5n)</td>
</tr>
</table>

<h4>Other Nth-Child Selectors</h4>

<p>Nth-Child also accepts negative numbers and subtraction as well as single numbers to select a specific element by its index.</p>

<table class="data">
<caption>Other Nth-Child Selectors</caption>
<tr>
    <th>Child</th>
    <th>Selector</th>
</tr>
<tr>
    <td>Only the First Element</td>
    <td>ol li:nth-child(1)</td>
</tr>
<tr>
    <td>Only the Third Element</td>
    <td>ol li:nth-child(3)</td>
</tr>
<tr>
    <td>Only the First Three Elements</td>
    <td>ol li:nth-child(-n+3)</td>
</tr>
</table>

<h4>Still Confused?</h4>

<p>Check out the handy <a href="http://www.nealgrosskopf.com/tech/resources/80/">nth-child visual calculator</a> I created and enter in some of the examples I've provided in my article. It will visually run and select the elements from your selector.</p>

<h4>Further Reading</h4>

<ul>
    <li><a href="http://reference.sitepoint.com/css/understandingnthchildexpressions#understandingnthchildexpressions__para_resultsettableintro">Sitepoint.com Article</a></li>
    <li><a href="http://css-tricks.com/5452-how-nth-child-works/">CSS-Tricks.com Article</a></li>
</ul><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=80">View Comments [42]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=80</guid>
<author>Neal Grosskopf</author>
<category>css</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2011-10-10 07:47:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=79</link>
<description>
<![CDATA[
<figure class="image-caption narrow">
    <object type="application/x-shockwave-flash" data="http://www.youtube.com/v/UJJul6wMA20?rel=0&amp;loop=1&amp;modestbranding=1&amp;autoplay=1&amp;autohide=1&amp;theme=light&amp;showinfo=0" width="204" height="96">
        <param name="movie" value="http://www.youtube.com/embed/UJJul6wMA20?rel=0&amp;loop=1&amp;modestbranding=1&amp;autoplay=1&amp;controls=0"></param>
        <param name="allowscriptaccess" value="always"></param>
    </object>
    <figcaption>
        <h3>Shimmer Effect Animation</h3>	
        <p>Above is an example video of what the effect looks like using CSS transitions. It can be accomplished relatively easily and is completely hidden from browsers that don't support transitions.<br><a href="http://www.nealgrosskopf.com/tech/resources/79">View the demo to see it in action &gt;&gt;</a></p>
    </figcaption>
</figure>

<p>I recently read an <a href="http://www.broken-links.com/2011/09/29/css-animations-on-top10-com/">excellent article by Peter Gasston</a> about creating an image shimmer/swipe effect on a website he was working on. I really liked the effect and after tinkering with how it worked I found that it used an <a href="http://top10.com/media/img/logo-sprite.png">image sprite</a> to achieve the effect.</p>

<p>This inspired me to create a similar effect without the sprite, using only CSS. My goal with pretty much everything I develop is to never have to open Photoshop to edit something and this seemed like a good opportunity to try that out.</p>

<h4>The Swipe Effect</h4>

<p>Below is an example of the effect for browsers that don't support CSS Transitions. Otherwise <b><a href="http://www.nealgrosskopf.com/tech/resources/79">check out my demo to see it in action</a></b>.</p>

<p><iframe width="200" height="112" src="http://www.youtube.com/embed/UJJul6wMA20?rel=0&amp;theme=light" frameborder="0" allowfullscreen></iframe></p>

<h4>How It Works</h4>

<p>The effect is pretty simple. It moves a DIV with a CSS gradient as a <samp>background-image</samp> from <samp>left: -100%</samp> to <samp>left: 100%</samp>. Below I've highlighted the DIV with a red background to show it better:</p>

<p><img src="http://www.nealgrosskopf.com/tech/resources/79/transition.png" alt="Transition" class="frame"></p>

<h4>HTML Setup</h4>

<p>In my particular instance I wanted to use the effect on our site's logo. Here is the HTML I used:</p>

<code>
&lt;h1&gt;
    &lt;a href=&quot;#link&quot;&gt;&lt;span&gt;Site Title&lt;/span&gt;&lt;/a&gt;
    &lt;div class=&quot;shimmer&quot;&gt;&lt;/div&gt;
    &lt;img src=&quot;logo.png&quot;&gt;
&lt;/h1&gt;
</code>

<h4>Container Setup</h4>

<p>The H1 container is setup to hold the child elements. It also uses <samp>overflow: hidden</samp> to hide the DIV with the gradient background when it isn't being shown.</p>

<code>
h1
{
display: inline-block;
overflow: hidden;
position: relative;
}
</code>

<h4>Setting Up the Child Elements</h4>

<p>One issue I ran into was when the DIV was sliding over the logo/anchor, the anchor was behind the DIV and wasn't clickable. I fixed this by positioning the anchor absolute and giving it a higher <samp>z-index</samp> than the DIV. I also gave both elements a height and width of 100% so it was dimension independent, something that I find in front-end development to be very important.</p>

<code>
h1 a, h1 div.shimmer
{
height: 100%;
width: 100%;
position: absolute;
top: 0px;
}

h1 a
{
display: block;
z-index: 3;
}

h1 a span { display: none; }
</code>

<h4>The Hidden DIV</h4>

<p>The DIV is positioned <samp>left: -100%</samp> and given a CSS background-gradient. I also used <samp>background-size</samp> on it. This could be tweaked to make the gradient and effect look different really easily. The gradient can also be quickly modified by importing the CSS into this <a href="http://www.colorzilla.com/gradient-editor/">CSS gradient generator app</a> which is one of my favorite tools on the web.</p>

<code>
h1 div.shimmer
{
background-image: -moz-linear-gradient(160deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0) 25%, rgba(255,255,255,0.85) 60%, rgba(255,255,255,0) 100%); /* FF3.6+ */
background-image: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,0)), color-stop(25%,rgba(255,255,255,0)), color-stop(60%,rgba(255,255,255,0.85)), color-stop(100%,rgba(255,255,255,0))); /* Chrome,Safari4+ */
background-image: -webkit-linear-gradient(160deg, rgba(255,255,255,0) 0%,rgba(255,255,255,0) 25%,rgba(255,255,255,0.85) 60%,rgba(255,255,255,0) 100%); /* Chrome10+,Safari5.1+ */
background-image: -o-linear-gradient(160deg, rgba(255,255,255,0) 0%,rgba(255,255,255,0) 25%,rgba(255,255,255,0.85) 60%,rgba(255,255,255,0) 100%); /* Opera11.10+ */
background-image: -ms-linear-gradient(160deg, rgba(255,255,255,0) 0%,rgba(255,255,255,0) 25%,rgba(255,255,255,0.85) 60%,rgba(255,255,255,0) 100%); /* IE10+ */
background-image: linear-gradient(160deg, rgba(255,255,255,0) 0%,rgba(255,255,255,0) 25%,rgba(255,255,255,0.85) 60%,rgba(255,255,255,0) 100%); /* W3C */
background-repeat: repeat-y;
background-size: 30% 100%;
left: -100%;
z-index: 2;
}
</code>

<h4>The Animation/Tween</h4>

<p>Finally, the real secret behind all of this is the code below. It moves the hidden DIV to the <samp>left: 100%</samp> and uses a CSS transition to tween the movement of the DIV.</p>

<code>
h1:hover div.shimmer
{
left: 100%;
-moz-transition: left .45s linear;
-o-transition: left .45s linear;
-webkit-transition: left .45s linear;
transition: left .45s linear;
}
</code>

<p>Thanks for reading an make sure to <a href="http://www.nealgrosskopf.com/tech/resources/79">check out my demo</a> to see it in action.</p>

<h4>Further Reading</h4>

<ul>
	<li><a href="http://www.broken-links.com/2011/09/29/css-animations-on-top10-com/">Peter Gasston's Article</a></li>
    <li><a href="http://www.colorzilla.com/gradient-editor/">CSS Gradient Generator</a></li>
    <li><a href="http://www.w3.org/TR/css3-transitions/#properties-from-css-">W3C Spec on CSS Transitions Including All Properties</a></li>
    <li><a href="https://developer.mozilla.org/en/CSS/transition">Mozilla Article on CSS Transitions</a></li>
    <li><a href="http://www.the-art-of-web.com/css/timing-function/">CSS Transition Timing Functions</a></li>    
</ul><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=79">View Comments [4]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=79</guid>
<author>Neal Grosskopf</author>
<category>css</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2011-08-18 20:44:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=78</link>
<description>
<![CDATA[
<figure class="image-caption narrow">
    <a href="http://www.nealgrosskopf.com/tech/resources/78/demo.php"><img src="http://www.nealgrosskopf.com/tech/resources/78/examples.jpg" alt="View the Demo"></a>
    <figcaption>
        <h3>The Same CSS Sprite <br>Re-Used Multiple Times</h3>	
        <p>An example of how the same CSS sprite can be used for multiple icons sizes. <a href="http://www.nealgrosskopf.com/tech/resources/78/demo.php">Check out my demo</a> to see this in action.</p>
    </figcaption>
</figure>

<p>I'll admit it, I've been living in a CSS 2.1 world for too long. For almost my enter career as a developer I've only needed to use four CSS background properties - <samp>background-color, background-image, background-repeat &amp; background-position</samp>...until now.</p>

<p>I've been aware of the CSS3 property <samp>background-size</samp> for quite awhile now but I could never think of a useful scenario to implement it. I was working on a project at work that listed out social media icons two times on the same page, but in different sizes. I thought to myself "gez, it would be nice if I could just re-use the same CSS sprite twice for the same set of icons?" With CSS this is possible.</p>

<h4>My CSS Sprite</h4>

<p>I'm still a big fan of CSS sprites as they cut down on unnecessary requests to the server and keep the server free of extra image files. Below is the CSS sprite I originally used for the footer area of the page.</p>

<img src="http://www.nealgrosskopf.com/tech/resources/78/social-sprite.png" class="frame" alt="CSS Sprite">

<h4>Header Example</h4>

<p>Below is an example, to scale, of what the header area of the page looks like with it's social media icons.</p>

<img src="http://www.nealgrosskopf.com/tech/resources/78/header.jpg" class="frame" alt="Header Example">

<h4>Footer Example</h4>

<p>Below is another example, to scale, of what the footer area of the page looks like with it's social media icons.</p>

<img src="http://www.nealgrosskopf.com/tech/resources/78/footer.jpg" class="frame" alt="Footer Example">

<p>As you can see, both areas are identical, other than one is larger than the other.</p>

<h4>HTML Structure</h4>

<p>Below is the HTML structure I used for each list of social media icons. The only thing needed to be tweaked from one size to another is the ID attribute.</p>

<code>
&lt;ul id=&quot;small-social&quot; class=&quot;social&quot;&gt;
    &lt;li class=&quot;facebook&quot;&gt;&lt;a href=&quot;http://www.facebook.com/&quot;&gt;&lt;span&gt;Facebook&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li class=&quot;twitter&quot;&gt;&lt;a href=&quot;http://www.twitter.com/&quot;&gt;&lt;span&gt;Twitter&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li class=&quot;youtube&quot;&gt;&lt;a href=&quot;http://www.youtube.com/&quot;&gt;&lt;span&gt;YouTube&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li class=&quot;linkedin&quot;&gt;&lt;a href=&quot;http://www.linkedin.com/&quot;&gt;&lt;span&gt;LinkedIn&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;li class=&quot;scribd&quot;&gt;&lt;a href=&quot;http://www.scribd.com/&quot;&gt;&lt;span&gt;Scribd&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</code>

<h4>Scaling The Image</h4>

<p>The CSS to scale the sprite from one size to another is quite simple. Below I assign the <samp>background-image</samp> and set the <samp>background-size: 100%</samp>.</p>

<code>
.social li a
{
background-image: url(social-sprite.png);
background-position: no-repeat;
-moz-background-size: 100%;
-webkit-background-size: 100%;
-o-background-size: 100%;
background-size: 100%;
}
</code>

<h4>Positioning the CSS Sprite</h4>

<p>Next I position the CSS sprite hooking into my classes. Originally I had used fixed-height pixel dimensions but I discovered that I could use percentages and save myself 5 lines of code per use.</p>

<code>
.facebook a { background-position: 0% 0%; }
.twitter a { background-position: 0% -100%; }
.youtube a { background-position: 0% -75%; }
.linkedin a { background-position: 0% -50%; }
.scribd a { background-position: 0% -25%; }
</code>

<p>Below is an example of my <b>old code</b> which I was able to get rid of by using the code above. My code above makes it much more flexible!</p>

<code>
#small-social .facebook a { background-position: 0px 0px; }
#small-social .twitter a { background-position: 0px -16px; }
#small-social .youtube a { background-position: 0px -32px; }
#small-social .linkedin a { background-position: 0px -48px; }
#small-social .scribd a { background-position: 0px -64px; }

#large-social .facebook a { background-position: 0px 0px; }
#large-social .twitter a { background-position: 0px -30px; }
#large-social .youtube a { background-position: 0px -60px; }
#large-social .linkedin a { background-position: 0px -90px; }
#large-social .scribd a { background-position: 0px -120px; }
</code>

<h4>Controlling the Size</h4>

<p>Finally the only real customization we need to do to our unordered list is setting the height and width. By simply changing these values, the sprite will automagically resize itself to fill the bounds of the anchor.</p>

<code>
/* Example 1 */
#small-social li a
{
height: 16px;
width: 16px;			
}

/* Example 2 */
#medium-social li a
{
height: 25px;
width: 25px;			
}

/* Example 3 */
#large-social li a
{
height: 30px;
width: 30px;			
}
</code>

<h4>Outcome of Our Code</h4>

<p>The above code would generate the following below - </p>

<a href="http://www.nealgrosskopf.com/tech/resources/78/demo.php"><img src="http://www.nealgrosskopf.com/tech/resources/78/examples.jpg" class="frame" alt="View the Demo"></a>

<p><b><a href="http://www.nealgrosskopf.com/tech/resources/78/demo.php">Check out my demo to see this in action &gt;&gt;</a></b></p>

<h4>What About Browsers That Don't Support <samp>Background-Size</samp>?</h4>

<p>If you need to support browsers that do not have this functionality, simply use <a href="http://www.modernizr.com/">Modernizr</a> to target them and serve them up a resized image.</p>

<code>
.no-backgroundsize #small-social li a { background-image: url(toolbar-social-sprite.png); }
</code>

<p>This works nice, by giving users of a more modern browser a better experience while quasi-punishing users who refuse to upgrade.</p>

<h4>Use in Responsive Designs</h4>

<p>I found another way to use <samp>background-size</samp> was in responsive designs. The site I was working on required this functionality so I decided to see if I could use this to scale a <samp>background-image</samp> as the browser window become smaller.</p>

<p>Below is my code I used for all screen sizes. This is a simple anchor nested within an H1 with a height and width set.</p>

<code>
h1 a
{
background: url(logo.png) no-repeat left top;
display: block;
height: 43px;
width: 180px;
}
</code>

<p>Below is my code used for the responsive design. This uses CSS Media Queries to determine when the browser window is narrower than 180px; When the window becomes smaller than that, the logo automagically resizes to the width of the window. This stops it from being cutoff.</p>

<code>
@media (max-width: 180px) {
    h1 a
    {
    background-size: 100%;
    max-width: 100%;
    width: auto;
    }
}
</code>

<h4>Further Reading</h4>

<ul>
	<li><a href="http://www.modernizr.com/">Modernizr</a></li>
    <li><a href="https://developer.mozilla.org/en/css/scaling_background_images">Scaling background images - MDN</a></li>
    <li><a href="https://developer.mozilla.org/en/CSS/background-size">background-size - MDN</a></li>
</ul><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=78">View Comments [75]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=78</guid>
<author>Neal Grosskopf</author>
<category>css3</category><category>mobile</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2011-04-11 08:32:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=77</link>
<description>
<![CDATA[
<p>I've always looked to Facebook when it comes to adding new features to my own website. I mean, why not? Certainly 500(estimate/exaggeration) developers must be smarter than 1. 
I also look at it like a learning experience trying to emulate all their awesome features.</p>

<p>I've already emulated <a href="http://www.nealgrosskopf.com/tech/thread.php?pid=62">their photo tagging functionality</a> so while I was working on that project, I thought, why not steal their image preloading idea as well.</p>

<p>You may have noticed that when browsing photo albums on Facebook, images seem to load super fast when clicking the next/previous buttons or hitting left/right on your keyboard. There's a reason for this. Facebook is preloading the previous and next image.</p>

<figure class="image-caption">
    <a href="http://www.nealgrosskopf.com/tech/resources/75/"><img src="http://www.nealgrosskopf.com/tech/resources/77/example.jpg" alt="Firebug's Net Panel"></a>
    <figcaption>
        <h3>Firebug's Net Panel</h3>	
        <p>Using Firebug's net panel you can see how each time I hit next, Facebook loads one image ahead and one image back. That means I always have the next and previous images loaded ahead of time.</p>
    </figcaption>
</figure>

<h4>On To The Code...</h4>

<p>The code in it's simplest form is easy, especially with jQuery.</p>

<code>
var nextimage = "/images/some-image.jpg";

$(document).ready(function(){
	window.setTimeout(function(){
		var img = $("&lt;img&gt;").attr("src", nextimage).load(function(){
			//all done
		});
	}, 100);
});
</code>

<h4>setTimeout Explanation</h4>

<p>The reason I wrap this in setTimeout is to take it out of the linear flow of JavaScript as <a href="http://www.stevesouders.com/blog/2009/05/06/positioning-inline-scripts/">Steve Sounders explains</a> -</p>

<blockquote><p>use setTimeout to kick off long executing code - If you have a function that takes a long time to execute, launching it via setTimeout allows the page to render and resources to download without being blocked.</p></blockquote>

<h4>Further Reading</h4>

<ul>
    <li><a href="http://www.stevesouders.com/blog/2009/05/06/positioning-inline-scripts/">Positioning Inline Scripts - Steve Souders</a></li>
    <li><a href="http://stackoverflow.com/questions/4285042/can-jquery-ajax-load-image">Stackoverflow Thread On Preloading Images</a></li>
</ul><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=77">View Comments [5]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=77</guid>
<author>Neal Grosskopf</author>
<category>facebook</category><category>jquery</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2011-01-31 20:22:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=76</link>
<description>
<![CDATA[
<p><img src="http://www.nealgrosskopf.com/tech/resources/76/article-image.jpg" class="article-teaser" alt="Track Embedded YouTube Video Events in Google Analytics Using YouTube's JSAPI"></p>

<p class="center"><a href="http://www.nealgrosskopf.com/tech/resources/76/" class="button" style="margin-right: 15px;">View Demo &raquo;</a> <a href="http://www.nealgrosskopf.com/tech/resources/76/demo.zip" class="button">Download Demo &darr;</a></p>

<p>Ever wonder how many of users watched an embedded YouTube video all the way through? How about how many simply pause the video halfway through out of boredom? This is 
all possible thanks to YouTube's Javascript API (JSAPI).</p>

<h4>The Setup</h4>

<p>First and foremost in order to do JavaScript callbacks from the video a few parameters need to be added to the embed code. Specifically <samp>enablejsapi=1</samp>. Also there's another parameter which will need to match the ID of the OBJECT element <samp>playerapiid=video1</samp>.</p>

<code>
&lt;object data=&quot;http://www.youtube.com/v/L4H8vvGVoS0&amp;enablejsapi=1&amp;playerapiid=L4H8vvGVoS0&quot; id=&quot;L4H8vvGVoS0&quot; type=&quot;application/x-shockwave-flash&quot; height=&quot;344&quot; width=&quot;425&quot;&gt;
&lt;param value=&quot;http://www.youtube.com/v/L4H8vvGVoS0&amp;enablejsapi=1&amp;playerapiid=L4H8vvGVoS0&quot; name=&quot;movie&quot;&gt;&lt;/param&gt;
&lt;param value=&quot;always&quot; name=&quot;allowscriptaccess&quot;&gt;&lt;/param&gt;
&lt;/object&gt;
</code>

<p>One thing to note: In order to get Internet Explorer to play nice, the default YouTube embed code didn't work for me. I needed to modify it to the above to successfully track my video in <b>ALL</b> browsers. I suspect this is related to Non-IE browsers using the <samp>EMBED</samp> element and IE using <samp>OBJECT</samp>. My above example uses <samp>OBJECT</samp> without any extra elements needed. For more on this see my article titled <a href="http://www.nealgrosskopf.com/tech/thread.php?pid=9">Embedding Flash Without Click To Activate Using Valid HTML</a></p>

<h4>Pseudo Code</h4>

<p>Since the Javascript required to accomplish this is about 60 lines long, I'll only explain a top level view of the code. When an action occurs on the YouTube video it will call the <samp>onYouTubePlayerReady</samp> function 
along with the ID of the <samp>OBJECT</samp> element. The details of each video are then stored in an anonymous function <i>(correct me if I've got the wrong terminology on this)</i> using <samp>youTubePlayerLoggers[id]</samp>. 
</p>

<code>
//Global variables

//Function that is called automatically by the embedding videos
function onYouTubePlayerReady(id)
{
	//Define video level variables	
	//Setup video state constants
		
	//Store information specific to each video
	youTubePlayerLoggers[id] = function(state)
	{		
		//Check video state, log action
	};
	
	//Bind events to video
}
</code>

<p><a href="http://www.nealgrosskopf.com/tech/resources/76/" class="button" style="margin-right: 15px;">View Demo &raquo;</a> <a href="http://www.nealgrosskopf.com/tech/resources/76/demo.zip" class="button">Download Demo &darr;</a></p>

<h4>Viewing The Data In Google Analytics</h4>

<p>Below are the reports that will be generated in Google Analytics. The data can be accessed in the Event Tracking report which is found under the Content category.</p>

<p style="overflow: hidden;">
    <a href="http://www.nealgrosskopf.com/gallery/display.php?src=/tech/resources/76/categories.jpg"><img src="http://www.nealgrosskopf.com/tech/resources/76/categories-thumb.jpg" class="frame" alt="Categories Report" style="float: left; margin: 0px;"></a>
    <a href="http://www.nealgrosskopf.com/gallery/display.php?src=/tech/resources/76/actions.jpg"><img src="http://www.nealgrosskopf.com/tech/resources/76/actions-thumb.jpg" class="frame" alt="Actions Report" style="float: left; margin:0px 0px 0px 20px;"></a>
</p>

<h4>Further Reading</h4>

<ul>
    <li><a href="http://code.google.com/apis/youtube/js_api_reference.html">YouTube JSAPI Documentation</a></li>
	<li><a href="http://code.google.com/apis/youtube/youtube_player_demo.html">YouTube Player Demo</a></li>
</ul><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=76">View Comments [9]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=76</guid>
<author>Neal Grosskopf</author>
<category>javascript</category><category>analytics</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2011-01-10 07:22:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=75</link>
<description>
<![CDATA[
<p>My site was recently featured in a <a href="http://speckyboy.com/2011/01/03/32-javascript-alternatives-with-pure-css-updated/">web magazine</a> for an article I had written on a <a href="http://www.nealgrosskopf.com/tech/thread.php?pid=45">CSS only content slider</a>. I noticed another CSS only article featured was a CSS only lightbox. After investigating 
the code I learned a few things but I felt the overall presentation could be improved upon and that I could also use my technique of using URL hash tags as CSS state variables as another solution. I know CSS only lightboxes <a href="http://thinkvitamin.com/design/how-to-create-a-valid-non-javascript-lightbox/">have been</a> <a href="http://www.cssplay.co.uk/menu/lightbox-click.html">done before</a> but I offer you another method.</p>

<figure class="image-caption">
    <a href="http://www.nealgrosskopf.com/tech/resources/75/"><img alt="Example" src="http://www.nealgrosskopf.com/tech/resources/75/screenshot.jpg"></a>	
    <figcaption>
        <h3>CSS Only Lightbox/Shadowbox Example</h3>	
        <p>If you want to skip the article and go straight to the final product view my <a href="http://www.nealgrosskopf.com/tech/resources/75/">CSS Only Lightbox/Shadowbox Demo</a>.</p>	
        <p class="b i">Note: You will need to use Safari/Chrome, Opera 11 or Firefox 4 in order to view the transition effect. It will work in Firefox and IE9 sans the animation.</p>
    </figcaption>
</figure>

<h4>Preface</h4>

<p>I'll start out this article by stating that it won't work in Internet Explorer, and that this is really just a <b>proof of concept</b>. It would, however, work in Internet 
Explorer had it supported the <a href="http://www.w3.org/TR/css3-selectors/#target-pseudo">:target pseudo selector</a>. It should be noted that <a href="http://msdn.microsoft.com/en-us/library/ff974378%28VS.85%29.aspx#_css3_namespaces">IE9 will support this selector</a> as well as quite a few others.</p>

<h4>Clickable Transparent Background</h4>

<p>The first thing people come to expect from a lightbox/shadowbox solution is the ability to click a semi-transparent background and have the window close. I accomplished this by absolutely positioning an anchor on the page with an href of <samp>#close</samp> I'll go into more detail on how this works later.</p>

<code>
&lt;a href=&quot;#close&quot; class=&quot;lightbox-bg&quot; title=&quot;Click to close&quot;&gt;&lt;/a&gt;
</code>

<p>Below is the CSS for our semi-transparent background. You'll notice that it spans the entire viewport and that it has a default <samp>opacity</samp> of <samp>0</samp> to hide it.</p>

<code>
.lightbox-bg
{
background: #000;
height: 100%;
width: 100%;
opacity: 0;
outline: 0px;
position: absolute;
left: 0px;
top: 0px;
z-index: 2;
}
</code>

<h4>Modal Window</h4>

<p>The next major piece of a lightbox/shadowbox solution is the media itself. Most people come to expect the modal window to be centered both vertically and horizontally. From what 
I can tell, the method I used to accomplish this was created by <a href="http://bluerobot.com/web/css/center2.html">BlueRobot.com</a> which uses negative margins which are 
exactly half of the height/width of the modal window.</p>

<code>
.lightbox-content
{
background: #fff;
height: 0px;
width: 0px;
margin: -275px auto auto -275px;
overflow: hidden;
position: absolute;
top: 50%;
left: 50%;
z-index: 3;
}
</code>

<h4>Opening our Lightbox</h4>

<p>And now probably the most interesting part of the code. The part that actually makes it open! This part uses one of my favorite additions to CSS3, <a href="http://www.w3.org/TR/css3-transitions/">CSS Transitions</a>. Currently, they are supported by all Webkit browsers (Safari &amp; Chrome for example) Opera 11, and the soon-to-be released Firefox 4.0.</p>

<p>The code works by animating the transition of values in specific properties. For instance if an element, by default, has an opacity value of <samp>0.0</samp> and it's
animated value is <samp>0.8</samp> it will create a transition effect from 0.0 to 0.8 in the specified amount of time you pick. In my case I chose <samp>.2s</samp> which means 
.2 seconds.</p>


<code>
.lightbox:target .lightbox-bg
{
left: 0px;
opacity: 0.8;
-o-transition: opacity .2s linear;
-webkit-transition: opacity .2s linear;
-moz-transition: opacity .2s linear;
}
</code>

<p>Displaying the modal window works in a similar fashion. Like <a href="http://www.shadowbox-js.com/">Shadowbox</a>, I wanted my modal window to have a size increasing effect 
upon opening. I did this by transitioning the height and width of the window. By default I set these values to <samp>0px</samp> and then increased the size to <samp>550px</samp> 
</p>

<code>
.lightbox:target .lightbox-content
{
height: 550px;
width: 550px;
-o-transition-property: height, width;
-o-transition-duration: .2s, .2s;
-o-transition-delay: .3s, .3s;
-webkit-transition-property: height, width;
-webkit-transition-duration: .2s, .2s;
-webkit-transition-delay: .3s, .3s;
-moz-transition-property: height, width;
-moz-transition-duration: .2s, .2s;
-moz-transition-delay: .3s, .3s;
}
</code>

<h4>Close</h4>

<p>The close effect is very similar to the open effect except it does the reverse action. For the close effect I created transitions for opacity, height and width.</p>

<code>
#close:target .lightbox
{
left: -100%;
-o-transition-property: left;
-o-transition-duration: .0s;
-o-transition-delay: .7s;
-webkit-transition-property: left;
-webkit-transition-duration: .0s;
-webkit-transition-delay: .7s;
-moz-transition-property: left;
-moz-transition-duration: .0s;
-moz-transition-delay: .7s;
}

#close:target .lightbox-bg
{
opacity: 0;
-o-transition-property: opacity;
-o-transition-duration: .3s;
-o-transition-delay: .3s;
-webkit-transition-property: opacity;
-webkit-transition-duration: .3s;
-webkit-transition-delay: .3s;
-moz-transition-property: opacity;
-moz-transition-duration: .3s;
-moz-transition-delay: .3s;
}

#close:target .lightbox-content
{
height: 0px;
width: 0px;
-o-transition-property: height, width;
-o-transition-duration: .2s, .2s;
-webkit-transition-property: height, width;
-webkit-transition-duration: .2s, .2s;
-moz-transition-property: height, width;
-moz-transition-duration: .2s, .2s;
}

#close:target .lightbox-content div
{
opacity: 0.0;
-o-transition: opacity .2s linear;
-webkit-transition: opacity .2s linear;
-moz-transition: opacity .2s linear;
}
</code>

<h4>The :target Pseudo Selector</h4>

<p>As promised in the beginning of the article, I'll explain more about how the <samp>:target</samp> pseudo selector is being used. The <samp>:target</samp> selector is an interesting part of CSS in that it's capable of being aware of what hash is currently present in the browser's URL. A has is something like this: <span class="url">/page.php<em>#hash</em></span></p>

<p>In the CSS I'm able to apply different CSS styling to elements based on what has is currently being used. In this case I have a hash for #window1, #window2, #window3 and #close, the two states of my CSS only lightbox.</p>

<p>The HTML needed to accomplish this looks something like this:</p>

<code>
&lt;div id=&quot;close&quot;&gt;
    &lt;div id=&quot;content&quot;&gt;
        &lt;a href=&quot;#window1&quot;&gt;Open Window 1&lt;/a&gt;
        &lt;a href=&quot;#window2&quot;&gt;Open Window 2&lt;/a&gt;
        &lt;a href=&quot;#window3&quot;&gt;Open Window 3&lt;/a&gt;
    &lt;/div&gt; 
    &lt;div id=&quot;window1&quot; class=&quot;lightbox&quot;&gt;
    ....
    &lt;/div&gt; 
    &lt;div id=&quot;window2&quot; class=&quot;lightbox&quot;&gt;
    ....
    &lt;/div&gt; 
    &lt;div id=&quot;window3&quot; class=&quot;lightbox&quot;&gt;
    ....
    &lt;/div&gt;
&lt;/div&gt;
</code>

<p>The CSS I use to target these specific hashes looks like this:</p>

<code>
.lightbox:target .lightbox-bg
{
....
}
</code>

<p>Notice the <samp>:target</samp> in there? That's the magic.</p>

<h4>Further Reading</h4>

<p>Well, if you've made it this far down my lengthy article I congratulate you. Here's a few links for further reading on topic if you're interested in tinkering with this on your own:</p>

<ul>
    <li><a href="http://www.w3.org/TR/css3-transitions/">W3C Spec on CSS Transitions</a></li>
    <li><a href="http://webkit.org/blog/138/css-animation/">CSS Transition Using Webkit</a></li>
    <li><a href="http://css-infos.net/property/-webkit-transition">CSS Transition Properties</a></li>
    <li><a href="http://bluerobot.com/web/css/center2.html">CSS Vertical &amp; Horizontal Centering</a></li>
    <li><a href="http://www.w3.org/TR/css3-selectors/#target-pseudo">:target Pseudo Selector</a></li>
    <li><a href="http://thinkvitamin.com/design/stay-on-target/">Stay on Target - ThinkVitamin.com</a></li>
    <li><a href="http://www.shadowbox-js.com">Shadowbox</a></li>
    <li><a href="http://www.huddletogether.com/projects/lightbox2/">Lightbox</a></li>
</ul><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=75">View Comments [8]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=75</guid>
<author>Neal Grosskopf</author>
<category>css</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-10-18 20:58:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=74</link>
<description>
<![CDATA[
<figure class="image-caption narrow">
    <img src="http://www.nealgrosskopf.com/tech/resources/74/css.jpg" alt="Testing For CSS Support In Javascript">
    <figcaption>
        <h3>Testing For CSS Support <br>In Javascript</h3>	
        <p>Learn how to test for CSS property <br>support using Javascript</p>
    </figcaption>
</figure>

<p>I was looking to test if a certain browser <i>(I'm looking at you Internet Explorer)</i> supported CSS opacity while writing some jQuery code the other day. While I was aware that you could 
set CSS properties in Javascript, I never bothered to see if you could also feature test those same properties in Javascript. I found a nice snippet I thought I would share since I hadn't seen this before.
</p>

<p>To test if a browser supports a specific CSS property in Javascript is pretty simple. To do so, simply create a temporary element using <samp>document.createElement("div")</samp> and then 
use the <samp>typeof</samp> operator on it like so:<br><br></p>

<code>
var el = document.createElement("div");
var iefilter = typeof el.style.filter == "string";
</code>

<h4>CSS Opacity</h4>

<p>Most likely you'll need to use this to test for the many flavors of opacity like I did. Below is an excerpt from my code:</p>

<code>
var el = document.createElement("div");
if(typeof el.style.opacity == "string")
{
	//Your browser supports the CSS Opacity property";
} else if (typeof el.style.filter == "string"){
	//Your browser doesn't support the CSS Opacity property but does support IE filters";
} else {
	//"Your browser doesn't support the CSS Opacity property";
}
</code>

<h4>Browser Prefixes</h4>

<p>We can also test for specific browser implementations of CSS properties in Javascript like so:</p>

<code>
var el = document.createElement("div");
if(typeof el.style.borderRadius == "string")
{
	//Your browser support the standard CSS3 border radius property
} else if (typeof el.style.MozBorderRadius == "string"){
	//Your browser support the Mozilla CSS3 border radius property
} else if (typeof el.style.WebkitBorderRadius == "string"){
	//Your browser support the Webkit CSS3 border radius property
} else if (typeof el.style.KhtmlBorderRadius == "string"){
	//Your browser support the KHTML CSS3 border radius property
} else {
	//Your browser does not support the CSS3 border radius property
}
</code>

<h4>CSS Hacks</h4>

<p>If you got clever with these, my example above could probably be used for CSS hacks testing for the presence of various rendering engines. Using alittle DOM manipulation you could assign classes to the 
<samp>BODY</samp> element based on what browser prefixes are supported.</p>

<h4>Further Reading:</h4>

<ul>
	<li><a href="http://perfectionkills.com/feature-testing-css-properties/">Feature testing CSS properties </a></li>
	<li><a href="http://blogs.msdn.com/b/ie/archive/2010/08/17/ie9-opacity-and-alpha.aspx">Scripting Opacity With Internet Explorer 9</a></li>
</ul><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=74">View Comments [3]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=74</guid>
<author>Neal Grosskopf</author>
<category>javascript</category><category>css</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-10-11 18:27:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=73</link>
<description>
<![CDATA[
<p><img src="http://www.nealgrosskopf.com/tech/resources/73/browser-code.jpg" class="article-teaser" alt="Media Query Madness: See How Firefox &amp; Opera Handle Images Differently Than Safari &amp; Chrome" style="height: 326px; width: 570px;"></p>

<p>Recently, I was thinking about creating a media queries for my website. Specifically for users on small screen devices and users on the iPad. This is relatively easy 
using media queries and can be accomplished using the following CSS:</p>

<code>
@media screen and (max-width: 600px)
{
	body { background: url(some-image.jpg) }
}
</code>

<h4>The Problem?</h4>

<p>My biggest concern with doing this was the current version of my website is very image heavy, especially with the large background-image I'm using. I was worried that code I presented above 
would <i>actually</i> load the smaller iPad-friendly image, even to users who were on larger monitors, since the image references appear in the stylesheet.</p>

<p>I had previously delved into this underground (see: 'boring') topic in a previous article of mine called <a href="http://www.nealgrosskopf.com/tech/thread.php?pid=23">CSS Image Preload - :hover Pseudo Selector Parent Of display: none Element</a> 
where I discovered that browsers do no load background-images on child elements if the parent element is set to <samp>display: none;</samp></p>

<p>Having somewhat of an interest in the topic of browsers loading background-images used in stylesheets, I decided to create an full-blown data table on the topic for everyone to enjoy.</p>

<h4>Who Cares If The Browser Loads An Image Or Not?</h4>

<p>Your users for one. The large background-image on my site is <b>63kb in size</b>. If a user doesn't actually see that image on their screen, then why waste their time downloading it? Furthermore, if you run a heavily trafficked site, think 
if a million users had to request that image, only to never see it on their screen.</p>

<h4>The Data</h4>

<p>I was able to capture whether or not a browser downloaded the background-images in CSS using an external program called <a href="http://www.fiddler2.com/fiddler2/">Fiddler</a>. Fiddler captures 
all HTTP traffic on your computer, regardless if it's a browser or an update service running requesting the image. Originally I was going to use each browser's web inspector such as Firebug but I decided to use Fiddler to 
get the data from a single source.</p>

<p><img src="http://www.nealgrosskopf.com/tech/resources/73/fiddler.jpg" class="article-teaser" alt="Fiddler" style="height: 395px; width: 570px;"></p>

<table class="data">
<caption>Comparison of Browser Image Pre-loading (Yes=Image loaded on page load; No=Image not loaded on page load)</caption>
<tr>
	<th>Type Of CSS Used</th>
	<th>Firefox 3.6</th>
	<th>Safari 4</th>
	<th>Chrome 5</th>
	<th>Opera 10.5</th>
	<th>Internet Explorer 7</th>
</tr>
<tr>
	<td><b>Default (control data)</b><br><samp>div { background: url(image.jpg); }</samp></td>
	<td>Yes</td>
	<td>Yes</td>
	<td>Yes</td>
	<td>Yes</td>
	<td>Yes</td>
</tr>
<tr>
	<td><b>Element - display: none</b><br><samp>div { background: url(image.jpg); display: none; }</samp></td>
	<td><b>No</b> <a href="#foot-1" class="sup">[1]</a></td>
	<td>Yes</td>
	<td>Yes</td>
	<td><b>No</b> <a href="#foot-1" class="sup">[1]</a></td>
	<td>Yes</td>
</tr>
<tr>
	<td><b>Element - visibility: hidden</b><br><samp>div { background: url(image.jpg); visibility: hidden; }</samp></td>
	<td>Yes</td>
	<td>Yes</td>
	<td>Yes</td>
	<td>Yes</td>
	<td>Yes</td>
</tr>
<tr>
	<td><b>Element - Outside Viewport</b><br><samp>div { background: url(image.jpg); left: -9999px; }</samp></td>
	<td>Yes</td>
	<td>Yes</td>
	<td>Yes</td>
	<td>Yes</td>
	<td>Yes</td>
</tr>
<tr>
	<td><b>Element - :hover</b><br><samp>div:hover { background: url(image.jpg); }</samp></td>
	<td>No</td>
	<td>No</td>
	<td>No</td>
	<td>No</td>
	<td>No</td>
</tr>
<tr>
	<td><b>Element - Parent display: none</b><br><samp>ul { display: none; }<br>ul li { background: url(image.jpg); }</samp></td>
	<td>No</td>
	<td>No</td>
	<td>No</td>
	<td>No</td>
	<td><b>Yes</b> <a href="#foot-2" class="sup">[2]</a></td>
</tr>
<tr>
	<td><b>Single Media Query</b><br><samp>div { background: url(image.jpg);<br>@media screen and (max-width: 600px)<br>{ div { background: url(image.jpg); } }</samp></td>
	<td>No <a href="#foot-5" class="sup">[5]</a></td>
	<td><b>Yes</b> <a href="#foot-3" class="sup">[3]</a></td>
	<td><b>Yes</b> <a href="#foot-3" class="sup">[3]</a></td>
	<td>No <a href="#foot-5" class="sup">[5]</a></td>
	<td><i>Unsupported</i></td>
</tr>
<tr>
	<td><b>Multiple Media Queries</b><br>
    <samp>div { background: url(image.jpg);<br>@media screen and (max-width: 600px)<br>{ div { background: url(image1.jpg); } }<br>@media screen and (max-width: 500px)<br>{ div { background: url(image2.jpg); } }</samp></td>
	<td>No <a href="#foot-5" class="sup">[5]</a></td>
	<td><b>Yes</b> <a href="#foot-4" class="sup">[4]</a></td>
	<td><b>Yes</b> <a href="#foot-4" class="sup">[4]</a></td>
	<td>No <a href="#foot-5" class="sup">[5]</a></td>
	<td><i>Unsupported</i></td>
</tr>
</table>

<ol>
	<li id="foot-1"><span class="sup">[1]</span> Both Firefox and Opera will not load a background-image of an element if it is set to display: none. This means that if the element's display property is later changed to block or inline, 
	the browser will need to fetch the image after page load has occurred.</li>
	<li id="foot-2"><span class="sup">[2]</span> Internet Explorer seems to break from the trend of the other browsers here by loading the background-image of an element that is nested inside of another element that is display: none;</li>
	<li id="foot-3"><span class="sup">[3]</span> Both Safari and Chrome load background-images from <b>both</b> the media query &amp; the non-media query element background-image.</li>
	<li id="foot-4"><span class="sup">[4]</span> Both Safari and Chrome load background-images from <b>both</b> media queries even when the background is trumped by a media query further down in the stylesheet. The image for the non-media query element background-image was also downloaded</li>
	<li id="foot-5"><span class="sup">[5]</span> Both Firefox &amp; Opera <b>only</b> downloaded the background-image used in the media query. If more than one media query was used, it only requested the last image.</li>
</ol>

<h4>Analyzing My Results</h4>

<p>What I found was very interesting. Even amongst the more 'modern' browsers there are differences in how they handle image loading. I'd like to note that the browsers I tested were simply the ones 
I had installed on my machine at the time of testing.</p>

<h4>Default (control <b>data</b>)</h4>

<p>My first test, was simply a <a href="http://en.wikipedia.org/wiki/Control_experiment">control</a>. Yeah...I'm a fan of the <a href="http://en.wikipedia.org/wiki/Scientific_method">scientific method</a>.</p>

<h4>Element - display: none</h4>

<p>Next up I tested elements that are set to <samp>display: none</samp> i.e.</p>

<code>
div
{
	background: url(image.jpg);
	display: none;
}
</code>

<p>What I found was interesting. Both Firefox &amp; Opera did not load the image while Safari, Chrome &amp; IE7 did. This might sound like a minor browser difference but consider the following:</p>

<code>
div
{
	background: url(image.jpg);
	display: none;
}

div:hover { display: block; }
</code>

<p>When the <samp>DIV</samp> is hovered over, both Firefox &amp; Opera need to quickly fetch the image. This causes the evil <a href="http://www.fivesevensix.com/studies/ie6flicker/">image flicker</a>. 
Drawing a conclusion on this is tough. Would you rather have the image ready to use on hover at the expense of your bandwidth or saving some bandwidth and download time for your site's users?</p>

<h4>Element - visibility: hidden</h4>

<p>I found the results for elements set to <samp>visibility: hidden</samp> to be the same across all browsers. Every browser downloaded the background-image immediately on page load. This is a key difference 
between <samp>display: none</samp> and <samp>visibility: hidden</samp> for many browsers.</p>

<h4>Element - :hover</h4>

<p>I found the results for background-image hovers to be the same across all browsers. Every browser waited to download the background-image until the element was hovered on.</p>

<h4>Single Media Query</h4>

<p>For this test I added a single media query to my page along with a background-image for all users:</p>

<code>
body { background: url(body.jpg); }

@media screen and (max-width: 600px)
{
	body { background: url(media-query.jpg) }
}
</code>

<p>The data below breaks down how each browser reacted when I loaded my test page in a browser window that met the requirements of the media query (i.e. the browser window being smaller than 600px.</p>

<table class="data" style="width: 550px;">
<caption>Images Downloaded On Page Load With Browser Viewport Below 600px</caption>
<tr>
	<th>Firefox 3.6</th>
	<th>Safari 4</th>
	<th>Chrome 5</th>
	<th>Opera 10.5</th>
</tr>
<tr>
	<td>media-query.jpg</td>
	<td>body.jpg<br>media-query.jpg</td>
	<td>body.jpg<br>media-query.jpg</td>
	<td>media-query.jpg</td>
</tr>
</table>

<p>Notice the differences? Firefox &amp; Opera reacted much differently than Safari &amp; Chrome. Both Firefox &amp; Opera decided not to bother downloading my original background-image. By doing so, should the browser window become larger than 600px, 
Firefox &amp; Opera would need to quickly download the new background-image.</p>

<h4>Multiple Media Queries</h4>

<code>
body { background: url(body.jpg); }

@media screen and (max-width: 600px)
{
	body { background: url(media-query1.jpg) }
}

@media screen and (max-width: 500px)
{
	body { background: url(media-query2.jpg) }
}
</code>

<table class="data" style="width: 550px;">
<caption>Images Downloaded On Page Load With Browser Viewport Below 500px</caption>
<tr>
	<th>Firefox 3.6</th>
	<th>Safari 4</th>
	<th>Chrome 5</th>
	<th>Opera 10.5</th>
</tr>
<tr>
	<td>media-query1.jpg</td>
	<td>body.jpg<br>media-query1.jpg<br>media-query2.jpg</td>
	<td>body.jpg<br>media-query1.jpg<br>media-query2.jpg</td>
	<td>media-query1.jpg</td>
</tr>
</table>

<p>The results for this test were similar to the single media query. The only difference is Safari &amp; Chrome downloaded <b>all</b> media query background-images regardless if they were being used or not.</p>

<h4>Takeaway</h4>

<p>When using media queries and designing sites for multiple devices, take into consideration how many images your incorporate into your alternate stylesheets. You could potentially force users to download excess files 
depending on which browser they are using.</p><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=73">View Comments [86]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=73</guid>
<author>Neal Grosskopf</author>
<category>css</category><category>media queries</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-09-14 20:06:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=72</link>
<description>
<![CDATA[
<p>It's been awhile since I've posted. Frankly I just haven't had anything to talk about. I thought I'd write up a quick article on a useful tool I found the other day called <a href="http://www.cleancss.com/">CleanCSS</a>. If you're interested 
  in the topic of CSS file maintenance and structure like I am, you may want to read my companion article <a href="http://www.nealgrosskopf.com/tech/thread.php?pid=42">Organize Your Stylesheet Madness & Reduce It's File Size With These Tips</a>.</p>

<p><img src="http://www.nealgrosskopf.com/tech/resources/72/cleancss.jpg" class="article-teaser" alt="Clean CSS"></p>

<h4>What Is CleanCSS</h4>

<p>CleanCSS allows you to take existing CSS and format it to a much more pleasant format. An example of this was a CSS file I was working on that appeared to have multiple contributors i.e. </p>

<code>
BODY { COLOR: #000000; }

.someclass {
	color: black;
	font-size: 24px;
	font-family: Arial, Helvetica, Geneva;
	margin-left: 22px;
	font-weight: 700;
}
.someotherclass {
	color: black;
	font-weight: 700;
}

a.menu{
color: white;
font-size: 10px;
text-decoration: none;
font-family: Arial, Helvetica, Geneva;
margin-left: 5px;
margin-right: 3px;
}

.whitetext-small { color: white; font-size: 9px; line-height: 12px; }
</code>

<p>As you can see, when multiple developers get working on a single file, over time, the formatting of the file loses consistency. Tabs may be ignored, alpha-numeric property sorting may be ignored and some developers might uppercase things while others many not.</p>
<p>CleanCSS offers many quick options to easily format your CSS. On the flip-side it will also compress your CSS if your overly concerned about filesize like my former co-worker and <a href="http://panelpicker.sxsw.com/ideas/view/5726">semi-famous</a> friend <a href="http://timkadlec.com/">Tim Kadlec</a> is. </p>
<h4>Our Example CSS Cleaned Up</h4>

<p>After running the above CSS through our cleaner, it outputted the following nicely formatted code: </p>

<code>
body
{
	color: #000;
}

.someclass
{
	color: #000;
	font-family: Arial, Helvetica, Geneva;
	font-size: 24px;
	font-weight: 700;
	margin-left: 22px;
}

.someotherclass
{
	color: #000;
	font-weight: 700;
}

a.menu
{
	color: #FFF;
	font-family: Arial, Helvetica, Geneva;
	font-size: 10px;
	margin-left: 5px;
	margin-right: 3px;
	text-decoration: none;
}

.whitetext-small
{
	color: #FFF;
	font-size: 9px;
	line-height: 12px;
}
</code>

<p>Feel free to give CleanCSS a spin on your next project at <a href="http://www.cleancss.com/">http://www.cleancss.com/</a></p><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=72">View Comments [3]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=72</guid>
<author>Neal Grosskopf</author>
<category>css</category><category>tools</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-07-26 20:58:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=71</link>
<description>
<![CDATA[
<figure class="image-caption narrow">
    <img src="http://www.nealgrosskopf.com/tech/resources/70/logo.jpg" alt="Google Analytics">
    <figcaption>
        <h3>Outgoing Link Tracking With Google Analytics</h3>
        <p>Learn how to track outgoing links using Google Analytics &amp; jQuery.</p>
    </figcaption>
</figure>

<p>By default Google Analytics will track the exit page, or last page a user views while on a website. What it won't track is what link that user clicked to leave the site. 
With a little jQuery this can become a reality.</p>

<h4>The Old, &amp; Wrong Way</h4>

<p>I've seen it time and time again, developers using the <samp>pageTracker._trackPageview</samp> function to track things that aren't pages. While <samp>pageTracker._trackPageview</samp> will 
do the job it creates false page views and inflates reports.</p>

<p>I would argue that a user clicking a link to leave a website is really a page view on the external site, not the developer's site. Below is the old method to achieve this:</p>

<code>
&lt;a href=&quot;http://www.nealgrosskopf.com/&quot; onclick=&quot;pageTracker._trackPageview('http://www.nealgrosskopf.com/');&quot;&gt;Outgoing Link&lt;/a&gt;
</code>

<h4>The Right &amp; New Way</h4>

<p>Google Analytics has a new method of tracking all things that aren't page views. This new technique uses the <samp>pageTracker._trackEvent</samp> method.</p>

<p>First import Google's hosted jQuery library:</p>

<code>
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js&quot;&gt;&lt;/script&gt;
</code>

<p>Next, within the <samp>$(document).ready</samp> function which is triggered when a page is finished loading, use the following Javascript:</p>

<code>
&lt;script type=&quot;text/javascript&quot;&gt;
$(document).ready(function(){
	$(&quot;a[href^='http://']&quot;).click(function(){
		pageTracker._trackEvent(&quot;links&quot;, &quot;external&quot;, $(this).attr(&quot;href&quot;), 0);
	}); 
});
&lt;/script&gt;
</code>

<p>This will target all link hrefs starting with "http" and add an onclick event handler to them.</p>

<h4>Dissecting pageTracker._trackEvent</h4>

<p>The following is taken directly from Google's guide to <samp>pageTracker._trackEvent</samp></p>

<ul>
	<li><b>Category (required)</b> - The name you supply for the group of objects you want to track.</li>
	<li><b>Action (required)</b> - A string  that is uniquely paired with each category, and commonly used to define the type of user interaction for the web object.</li>
	<li><b>Label (optional)</b> - An optional string  to provide additional dimensions to the event data.</li>
	<li><b>Value (optional)</b> - An integer that you can use to provide numerical data about the user event.</li>
</ul>

<p>And again, as it would appear in Javascript</p>

<code>
pageTracker._trackEvent(&quot;Category&quot;, &quot;Action&quot;, &quot;Label&quot;), Value);
</code>

<p>While Google specifies what each of the variable placeholders should be they can certainly be named whatever you want. Action does not need to be a verb (as you can see in my original example). Feel free to 
use each of the placeholders however you see fit. One thing to note is the last variable (Value) must be an integer.</p>

<h4>How the Data Looks in Google Analytics</h4>

<p>Below is how the report will look in Google Analytics once some data is collected. This data can be sliced and diced using Advanced Segments just like any other dimension in Google Analytics.</p>

<p><img src="http://www.nealgrosskopf.com/tech/resources/71/report.jpg" class="frame" alt="How The Data Looks in Google Analytics"></p>

<h4>Further Reading</h4>

<ul>
	<li><a href="http://code.google.com/apis/analytics/docs/tracking/eventTrackerGuide.html">Google's pageTracker._trackEvent Guide</a></li>
</ul><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=71">View Comments [4]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=71</guid>
<author>Neal Grosskopf</author>
<category>analytics</category><category>jquery</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-07-18 20:00:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=70</link>
<description>
<![CDATA[
<figure class="image-caption narrow">
    <img src="http://www.nealgrosskopf.com/tech/resources/70/logo.jpg" alt="Google Analytics">
    <figcaption>
        <h3>Internal Campaign Tracking With Google Analytics</h3>
        <p>Learn how to implement internal website campaign tracking with Google Analytics</p>
    </figcaption>
</figure>

<p>Many sites nowdays self promote content deep within from the home page. In many ways this should be considered an internal campaign. On larger websites with multiple stakeholders involved, it becomes even more important to measure how successful 
internal campaigns are peforming. By default Google Analytics has the ability to track external campaign links pointing to your website, however it does not come with built in functionality to track internal campaigns.</p>

<p>One solution is to use custom variables to track internal campaigns. By using these campaign variables, you can slice and dice your visitor's movement on your website easier. 
If you're not familiar with campaign link tagging I suggest you click through a couple links in your RSS feeds (Slashdot, specifically uses them) and you'll notice that there are several query strings appended to each link.</p>

<h5>Example Tagged Link:</h5>

<p class="url">http://science.slashdot.org/story/10/07/14/2222239/The-Chicken-May-Have-Come-Before-the-Egg?from=rss<em>&amp;utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed%3A+Slashdot%2Fslashdot+%28Slashdot%29&amp;utm_content=Google+Reader</em></p>

<p>Each of these query strings translates into a dimension in Google Analytics. Below is the anatomy of our URL:</p>

<code>
&amp;utm_source=feedburner
&amp;utm_medium=feed
&amp;utm_campaign=Feed%3A+Slashdot%2Fslashdot+%28Slashdot%29
&amp;utm_content=Google
</code>

<p>I'm not going to go into too much depth on the built in external campaign tracking for Google Analytics since that's been covered by every  blogger in existence already. Google provides an quick and easy 
form with explanations for each query string value here anyway - <a href="http://www.google.com/support/analytics/bin/answer.py?hl=en&amp;answer=55578">http://www.google.com/support/analytics/bin/answer.py?hl=en&amp;answer=55578</a></p>

<h4>Using utm_* Query Strings For Internal Campaign Tracking?</h4>

<p>NO! Never do this! I suspect many people first consider this when attempting to track internal campaigns but here's why you shouldn't. Each of these query strings is written to a cookie within Google Analytics. 
If a user searches "Internet Explorer hacks" on Google the following would happen:</p>

<code>
utm_source = google.com
utm_medium = google / organic
</code>

If you custom 'tagged' an internal link you'd essentially overwrite the existing utm_source &amp; utm_medium data with your new data thus loosing the original source of the users visit. <b>This is very very bad</b>.

<h4>Enough Already, Just Tell Me How To Do This!?!?</h4>

<p>Ok, sorry for the long intro but I needed to get that out of the way before moving any further. Instead of using utm_* query strings let's use our own custom query strings, say one that starts with <samp>int_</samp></p>

<h5>The Following URL:</h5>

<p class="url">http://www.yourdomain.com/landingpage/?<em>utm_source</em>=advertiser.com&amp;<em>utm_medium</em>=bannerad&amp;<em>utm_campaign</em>=summerpromotion&amp;<em>utm_content</em>=horizontal</p>

<h5>Becomes:</h5>

<p class="url">http://www.yourdomain.com/landingpage/?<em>int_source</em>=advertiser.com&amp;<em>int_medium</em>=bannerad&amp;<em>int_campaign</em>=summerpromotion&amp;<em>int_content</em>=horizontal</p>

<h4>Hidding Query Strings Within Google Analytics</h4>

<p>Next, configure the Google Analytics profile to exclude these new query strings. Otherwise the URLs are going to look different within the reports depending on the refering page and it will render your stats very useless.</p>

<ol>
	<li>Navigate to Analytics Settings &gt; Profile Settings &gt; Edit Profile Information</li>
	<li>Under 'Exclude URL Query Parameters:' include the following query strings <samp>int_source, int_campaign, int_medium, int_content</samp> (or your own)</li>
</ol>

<img src="http://www.nealgrosskopf.com/tech/resources/70/google-analytics-exclude-paremeters.png" class="frame" alt="Hidding Query Strings Within Google Analytics">

<h4>Configuring Your Google Analytics Tracking Code For Internal Campaigns</h4>

<p>Finally, you'll need to slightly modify your tracking code to send these custom variables to Google. This uses Google's <samp>pageTracker._setCustomVar</samp> function. The names (i.e. Internal%20Campaign) can be named to whatever you like.</p>

<code>
&lt;script type=&quot;text/javascript&quot;&gt;
var gaJsHost = ((&quot;https:&quot; == document.location.protocol) ? &quot;https://ssl.&quot; : &quot;http://www.&quot;);
document.write(unescape(&quot;%3Cscript src='&quot; + gaJsHost + &quot;google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E&quot;));
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
var pageTracker = _gat._getTracker(&quot;UA-XXXXXX-X&quot;);
&lt;?php
if(isset($_GET[&quot;int_campaign&quot;])) echo 'pageTracker._setCustomVar(1,&quot;Internal%20Campaign&quot;,&quot;'.$_GET[&quot;int_campaign&quot;].'&quot;,1);';
if(isset($_GET[&quot;int_source&quot;])) echo 'pageTracker._setCustomVar(2,&quot;Internal%20Source&quot;,&quot;'.$_GET[&quot;int_source&quot;].'&quot;,1);';
if(isset($_GET[&quot;int_medium&quot;])) echo 'pageTracker._setCustomVar(3,&quot;Internal%20Medium&quot;,&quot;'.$_GET[&quot;int_medium&quot;].'&quot;,1);';
if(isset($_GET[&quot;int_content&quot;])) echo 'pageTracker._setCustomVar(4,&quot;Internal%20Content&quot;,&quot;'.$_GET[&quot;int_content&quot;].'&quot;,1);';
?&gt;
pageTracker._initData();
pageTracker._trackPageview();
&lt;/script&gt;
</code>

<h4>Further Reading</h4>

<ul>
	<li><a href="http://code.google.com/apis/analytics/docs/tracking/gaTrackingCustomVariables.html">Google Analytics Custom Variables</a></li>
	<li><a href="http://www.google.com/support/analytics/bin/answer.py?hl=en&amp;answer=55578">Google Analytics External Campaign Tracking</a></li>
</ul><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=70">View Comments [6]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=70</guid>
<author>Neal Grosskopf</author>
<category>google</category><category>analytics</category><category>jquery</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-05-17 07:01:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=69</link>
<description>
<![CDATA[
<img src="http://www.nealgrosskopf.com/tech/resources/69/jquery.data.png" alt="jQuery's .data() Method" class="frame" style="float: right; margin: 0px 0px 15px 15px;">

<p>I was recently working on a project that required users to input numbers, formatted as currency into textboxes and then calculate said numbers with other formatted textboxes. My 
client-side calculator had 34+ textboxes. I was a bit worried that I'd need to create javascript variables for each of these textboxes and possibly as a number &amp; formatted variable. Another 
requirement was if a user backspaces all of the numbers in a textbox, that it should return to it's original number.</p>

<h4>Say Goodbye to Variables With jQuery's <samp>.data()</samp> Method</h4>

<p>Having read up on jQuery's <samp>.data()</samp> method briefly in the documentation a few times in the past, I wondered to myself it that would be a possible solution. It a nutshell, the <samp>.data()</samp> 
method allows developers to store data <b>inside</b> elements in an array format. In the past I might have done something like this to store data:</p>

<code>
&lt;a href=&quot;/&quot; rel=&quot;some data&quot; rev=&quot;some more data&quot; title=&quot;maybe even more data&quot;&gt;Link With Data&lt;/a&gt;
</code>

<p>While this worked great there was a few drawbacks. For one it was improperly using attributes in a way the W3C spec never intended. Second I was limited to the amount of unique data I 
could store due to limits to the number of attributes at my disposal</p>

<h4>Enter <samp>.data()</samp></h4>

<p>Going back to my original problem, with <samp>.data()</samp> I can now store data inside elements like so:</p>

<code>
$("input").data("original", "$1.75");
$("input").data("currency", "$1.50");
$("input").data("decimal", 1.5);
</code>

<p>To retrieve that data it's as simple as this:</p>

<code>
$("input").data("original");
$("input").data("currency");
$("input").data("decimal");
</code>

<h4>Shorthand</h4>

<p>jQuery also offers a shorthand method of assigning multiple values to a single element. Below is a shorthand variation of my above statements:</p>

<code>
$("input").data("numbers",{original: "$1.75", currency: "$1.50", decimal: 1.5});
</code>

<p>To retrieve these values it's also a bit different since they're now included in a single array called <samp>numbers</samp></p>

<code>
$("input").data("numbers").original;
$("input").data("numbers").currency;
$("input").data("numbers").decimal;
</code>

<h4>Removing Values</h4>

<p>Below is jQuery's method of removing data:</p>

<code>
$("input").removeData("currency");
</code>

<h4>Final Words</h4>

<p>I found this technique to be easier to understand while I developed the application. Also, since I was already querying the element to get the user's input it was just another line of code to get other values I stored inside the element.</p>

<h4>Further Reading</h4>

<p>Feel free to check out jQuery's documentation on the <a href="http://api.jquery.com/data/">.data() method</a>. I also found a Firebug plug that allows you to inspect values assigned to elements which makes <a href="https://addons.mozilla.org/en-US/firefox/addon/12632/">debugging easier</a>.</p><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=69">View Comments [31]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=69</guid>
<author>Neal Grosskopf</author>
<category>jquery</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-03-16 20:32:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=68</link>
<description>
<![CDATA[
<p><i>First let me start with this won't be my typical "how-to-like" article which I typically write on my website. I haven't posted many of those over the past month mostly because I was in the
process of moving but I'm settled in again.</i></p>

<p>I've been following the <a href="http://arstechnica.com/tech-policy/news/2010/03/china-warns-google-partners-as-censored-results-leak-through.ars">Google vs. China fiasco</a> online, 
mostly through my RSS feeds, and I've begun to ponder on what a Google-less China would be like. China has 1.3 billion people, or 20% 
of the earth's population, and is poised to <a href="http://arstechnica.com/tech-policy/news/2007/07/china-set-to-overtake-the-us-in-number-of-internet-users.ars">overtake the US as the 
#1 country in internet users</a>. While China flat-out blocking Google.cn is a big deal (and I suspect this would include <b>all</b> of Google search such as Google.com), 
what if China blocked <b>all</b> of Google's online services?</p>

<figure class="image-caption">
    <img src="http://www.nealgrosskopf.com/tech/resources/68/no-google.png" alt="Google vs. China">
    <figcaption>
        <h3>Google vs. China</h3>
        <p>If China decides to block Google an all its services it could be a headache for web developers.</p>
    </figcaption>
</figure>

<h3>What Makes Google?</h3>

<p><a href="http://www.google.com/options/">To start out with, go and take a look at all the services Google offers &gt;&gt;</a></p>

<p>Let's say China decides to block everything that is Google i.e. all of <a href="http://www.google.com/options/">Google's online services</a>. Think of all the services 
you use that are hosted on Google's servers? Here's a list of just a few things I can think of that would be troublesome to web developers:</p>

<ul>
	<li><a href="http://code.google.com/apis/ajaxlibs/">Google Hosted Javascript Libraries</a> such as jQuery, MooTools etc.</li>
	<li><a href="http://www.youtube.com">YouTube videos</a> &amp; specifically all those embedded videos around the internet.</li>
	<li>Chinese users would no longer be tracked in <a href="http://www.google.com/analytics/">Google Analytics.</a></li>
	<li>You website would lose all the Chinese traffic Google was sending to it via Google search.</li>
	<li><a href="http://feedburner.google.com/">Feedburner</a> would no longer work in China. You would lose any Chinese RSS feed subscribers.</li>
	<li>Embedded <a href="http://maps.google.com/">Google Maps</a> would stop working.</li>
	<li>What about all the Gmail users in China?</li>
	<li>Using the <a href="http://www.google.com/cse/">Google Site Search feature</a> on your website? Not in China you aren't.</li>
</ul>

<h3>Other Problems</h3>

<p>I don't have specific cases for these products but I'm curious as to how a 100% Google blockade would affect these Google services since they can be embedded in external websites:</p>

<ul>
	<li>Google Checkout</li>
	<li>Picasa Embedded Galleries</li>
	<li>Google Translate Widget</li>
	<li>Blogger</li>
</ul>

<h3>So What?</h3>

<p>I did a quick search and if China decided to block Google and its services this won't be the 
<a href="http://techcrunch.com/2009/06/24/censorship-20-china-blocks-google-search-apps-gmail-and-more/">first time</a> so perhaps this would only be temporary. Another argument might 
be that Google isn't a big player in China like their native Baidu search engine. <a href="http://www.searchenginejournal.com/google-losing-market-share-in-china/3816/">Statistics would help 
this argument</a>, but even if Google Search isn't a big player in China, I have a feeling many of their ancillary services <i>are</i> even if only behind the scenes.</p>

<h3>Aftermath</h3>

<p>If China decides to go through with this, I'm predicting that a schism will occur in the internet. There will be the People's Internet of China and the rest of the world's.
If China gets away with this, it will be a lot easier to for them to block other, smaller, websites.</p>

<h3>Other Takeaways</h3>

<p>One takeaway I got from this brainstorming exercise was how reliant many of our websites are on third party providers. Its difficult to build a website nowadays without linking to a resource 
from another site. Will that site/service be there 5-10 years from now? What happens when it's discontinued? Maybe its web developer job security and I should stop complaining?</p>

<p><b>What do you think about it? Speak your mind below -</b></p><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=68">View Comments [1]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=68</guid>
<author>Neal Grosskopf</author>
<category>google</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-02-08 22:45:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=67</link>
<description>
<![CDATA[
<figure class="image-caption narrow">
	<img src="http://www.nealgrosskopf.com/tech/resources/67/screenshot.jpg" alt="Screenshot of the New Facebook home page">
    <figcaption>
        <h3>New Facebook Home Page</h3>	
        <p>Above is a screenshot of the new Facebook home page. One change on the new page is showing all types of updates rather than just status updates.</p>
    </figcaption>
</figure>

<p>Facebook has once again decided to redesign their home page. These types of changes usually result in millions of users joining groups titled "I hate the new design" or something similar. 
Being a web designer I sympathize with Facebook.</p>

<p>One thing they changed with the recent redesign was removing the "status updates only" option on their home page. I'm now forced to sift through every group, fan page, image and application post 
my friends have made. Facebook does give me the option to hide specific applications but with 1000's of apps out there, it isn't practical to hide each and every one. <b>Enter Stylish</b>.</p>

<h3>Hacking Facebook's CSS</h3>

<p>Using a <a href="https://addons.mozilla.org/en-US/firefox/addon/2108">Firefox addon called Stylish</a> I was able to sift through Facebook's HTML &amp; CSS and determine if they did a good job giving their home page elements proper class 
names and IDs. For whatever reason Facebook uses custom HTML attributes. One of these was called <samp>data-ft</samp>. The first value in that attribute is a number that represents various home page types. The example below uses "46" which is plan ol' 
vanilla status updates:</p>

<code>
&lt;div class=&quot;GenericStory UIStory clearfix aid_718391393&quot; data-ft=&quot;{&quot;sty&quot;:&quot;46&quot;,&quot;actrs&quot;:&quot;718391393&quot;,&quot;fbid&quot;:&quot;328181226116&quot;,&quot;s_obj&quot;:&quot;11&quot;,&quot;s_edge&quot;:&quot;1&quot;,&quot;s_prnt&quot;:&quot;11&quot;}&quot; id=&quot;div_story_1630882208_328181226116&quot;&gt;&lt;/div&gt;
</code>

<h3>Show Status Updates Only</h3>

<p>By adding the code below into Stylish it will hide ALL types of updates on the Facebook home except for regular status updates:</p>

<code>
@namespace url(http://www.w3.org/1999/xhtml);
@-moz-document domain("facebook.com") {
.GenericStory { display: none !important; }
#pagelet_intentional_stream  div[data-ft*='sty":"46'] { display: block !important; }
}
</code>

<p>Below is an example of this would be entered into Stylish:</p>

<p><img src="http://www.nealgrosskopf.com/tech/resources/67/stylish-screenshot.png" alt="Screenshot of Stylish"></p>

<h3>Other Update Types</h3>

<p>You could also substitute the number <samp>46</samp> above with one of the below to show only these types of updates by default:</p>

<table class="data">
<caption>Attribute Value Table</caption>
<tr>
	<th>Update Type</th>
	<th>Number Value</th>
</tr>
<tr>
	<td>Fan Page Added</td>
	<td>161</td>
</tr>
<tr>
	<td>Application</td>
	<td>237</td>
</tr>
<tr>
	<td>Friend Added</td>
	<td>8</td>
</tr>
<tr>
	<td>Group Added</td>
	<td>21</td>
</tr>
<tr>
	<td>Photo Added</td>
	<td>65</td>
</tr>
<tr>
	<td>Photo Album Added</td>
	<td>247</td>
</tr>
<tr>
	<td>Video Added</td>
	<td>128</td>
</tr>
</table>

<h3>To Each His Own</h3>

<p>Some people may love seeing <i>everything</i> their friends do on Facebook. I'm more interested in what they have to say and the rest just feels like noise. Feel free to take this code and make it your own.</p><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=67">View Comments [6]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=67</guid>
<author>Neal Grosskopf</author>
<category>facebook</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-01-27 22:05:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=66</link>
<description>
<![CDATA[
<p>As a website grows so does its stylesheet. The problem is, the opposite is not true. As a pages get removed, seldom do the selectors in the 
external stylesheet. This becomes even worse with multiple employees, especially if people come and go. Enter <a href="https://addons.mozilla.org/en-US/firefox/addon/10704">CSS Usage</a>.</p>

<figure class="image-caption">
    <img src="http://www.nealgrosskopf.com/tech/resources/65/main.png" alt="Example of CSS Usage">
    <figcaption>
        <h3>CSS Usage</h3>
        <p>Above is an example screenshot showing selectors in green that were found and selectors in red that were not. As a website is browsed, the tool will continue to re-analyze 
        the stylesheet.</p>
    </figcaption>
</figure>

<p>I found this Firebug extension a couple weeks ago and thought it was worth talking about. CSS Usage shows up as a tab within Firebug so if you don't have that 
extension yet, head over to Mozilla's addon site and download it - <a href="https://addons.mozilla.org/en-US/firefox/addon/1843">https://addons.mozilla.org/en-US/firefox/addon/1843</a></p>

<img src="http://www.nealgrosskopf.com/tech/resources/65/toolbar.png" alt="CSS Usage tab within Firebug">

<p>The jist of CSS Usage is to scan your stylesheet selectors and HTML to determine if each selector is used. Used selectors are colored in <span style="color: #00CC00;">green</span>
 while unused selectors are colored in <span style="color: red;">red</span>. Selectors previously found on other pages are colored in <span style="color: #336600">dark green</span></p>
 
<p>By default it will only analyze a page if you hit 'scan' but I like to turn on the auto-scan feature and just browse around my site for about 20 pages to give it a good mix of selectors. 
After that I had only a handful of selectors that were left unused. I took those selectors and did a site wide search to try to identify if they were used.</p>

<h3>Cons</h3>

<p>There are a few drawbacks with the addon. Currently it will only scan pages you visit. It does not have the ability to scan your entire site. Sites with 100's of pages may be difficult 
to scan with this tool. I also found the line numbering to be a bit flaky (as seen in my screenshot above).</p>

<h3>Pros</h3>

<p>Some great pros of this addon include cleaning up your stylesheets and reducing filesize. You can also save a little bandwidth by making them smaller in size.</p>

<h3>Download</h3>

<p>Head over to the <a href="https://addons.mozilla.org/en-US/firefox/addon/10704">CSS Usage</a> page on Mozilla's addon site and give it a try.</p><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=66">View Comments [13]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=66</guid>
<author>Neal Grosskopf</author>
<category>css</category><category>firefox</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-01-20 18:15:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=65</link>
<description>
<![CDATA[
<figure class="image-caption narrow">
    <img alt="Firefox 3.6" src="http://www.nealgrosskopf.com/tech/resources/52/firefox.jpg">
    <figcaption>
        <h3>Firefox 3.6</h3>	
        <p>Firefox 3.6 looks to have plenty of new features for web developers to play with.</p>
    </figcaption>
</figure>

<p>Firefox 3.6 is set to be released January 21st and is packing several new and exciting properties in it. Perhaps we can rename Firefox 3.6 to Firefox: Background Edition since the majority of those properties are background related.</p>

<h3>CSS Background Gradients</h3>

<p>Backgrounds gradients are something <a href="http://www.webstandards.org/2008/01/18/tell-the-css-wg-what-you-want-from-css3/#comment-59477">I've been requesting for a long time now</a>. 
It looks like the browser vendors finally listened! To use CSS gradients you'll need to use them within the context of a <samp>background-image</samp>.</p>

<p>This example will create a horizontal white to black gradient.</p>

<code>
html
{
background-image: -moz-linear-gradient(left, #fff, #000);  
}
</code>

<h3>Advanced Gradients</h3>

<p>Firefox also supports more advanced gradients such as <a href="https://developer.mozilla.org/en/CSS/-moz-radial-gradient">radial (circle) gradients</a> 
and linear gradients at an <a href="https://developer.mozilla.org/en/CSS/-moz-linear-gradient">angle (i.e. diagonal gradients)</a> much like one would create in Photoshop or Fireworks. 
It will also support <a href="https://developer.mozilla.org/en/CSS/-moz-linear-gradient#Example.3a.c2.a0Multiple_color_stops">color stops</a> which are midpoints in your gradient.</p>

<p>Each of these topics are worthy of their own full length tutorial so I'm not going to dig too deep into them right now. Just be aware that they are now supported by Gecko (Firefox) and Webkit (Safari, and later Google Chrome) based browsers.</p>

<p>To learn more about CSS gradients check out the <a href="https://developer.mozilla.org/en/Using_gradients">Mozilla Developer Center page on CSS Gradients</a>.</p>

<h3>Multiple Backgrounds in CSS</h3>

<p>Multiple backgrounds are what we've all been waiting for. Gone are the days of nesting <samp>DIV</samp>s like this:</p>

<code>
&lt;div id=&quot;top-bg&quot;&gt;
	&lt;div id=&quot;bottom-bg&quot;&gt;
		&lt;div id=&quot;inner-bg&quot;&gt;
		Content
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/div&gt;
</code>

<p>We can now use a single element if our page requires multiple backgrounds using the code below:</p>

<code>
html
{ 
background-image: url(image1.png), url(image2.png), url(image3.png);
background-repeat: no-repeat, no-repeat, repeat;  
background-position: right top, left bottom, top;  
}  
</code>

<p>To learn more about multiple backgrounds check out the <a href="http://www.w3.org/TR/css3-background/#layering">CSS Spec on Multiple Backgrounds</a>.</p>


<h3>CSS Background Scaling</h3>

<p>Another background related addition to Firefox 3.6 is the <samp>-moz-background-size</samp> property. This allows us to resize background images, that are perhaps too big or too small for the element they are in.</p>

<p>If the our image <samp>image.png</samp> default size is 150px x 75px this would scale the image up larger:</p>

<code>
div
{
background: url(image.png) no-repeat left top;
-moz-background-size: 300px;
}
</code>

<h3>Try It Yourself</h3>

<p>Head over to <b><a href="http://www.mozilla.com/firefox/">http://www.mozilla.com/firefox/</a></b> and grab a copy for yourself.</p><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=65">View Comments [11]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=65</guid>
<author>Neal Grosskopf</author>
<category>firefox</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-01-19 21:45:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=64</link>
<description>
<![CDATA[
<p>Adding animations to a webpage can give it a polished appearance to visitors. One effect that can be added, is a bouncing effect on icons or graphics. In many ways 
this is much like the 'dock' in Mac OSX. Here's a <a href="http://www.quantumlaundry.com/">few examples</a> of <a href="http://speedqueen.com/home/products/inner-strength/">the effect</a> that I've done in the past.</p>

<figure class="image-caption">
    <a href="http://www.nealgrosskopf.com/tech/resources/64/"><img src="http://www.nealgrosskopf.com/tech/resources/64/visual.jpg" alt="visual example"></a>
    <figcaption>
        <h3>Icon Bouncing</h3>
        <p>Above is a visual of what happens when an icon is hovered over. Notice how the Opera logo is slightly higher than the other icons? <a href="http://www.nealgrosskopf.com/tech/resources/64/">Click to see a live demo of this effect &gt;&gt;</a></p>
    </figcaption>
</figure>

<h3>HTML Structure</h3>

<p>Here's the barebones HTML structure:</p>

<code>
&lt;ul id=&quot;icons&quot;&gt;
	&lt;li&gt;&lt;img src=&quot;image.jpg&quot;&gt;&lt;/li&gt;
	....
&lt;/ul&gt;
</code>

<h3>CSS Code</h3>

<p>The <samp>UL</samp> gets collapsed by floating the <samp>LI</samp>'s left. One thing I'd recommend is giving the <samp>LI</samp>'s a fixed height. Otherwise 
the list will be growing taller and shorter as users hover over it causing content on the rest of the page to shift around. Also the <samp>padding-top</samp> should equal the same amount of pixels as the 
<samp>margin-top</samp> in the jQuery code.</p>

<code>
#icons
{
list-style-type: none;
margin: 0px;
padding: 0px;
overflow: auto;
}

#icons li
{
float: left;
height: 100px;
padding: 10px 0px 0px 0px;
}

#icons li img
{
display: block;
border: 0px;
}
</code>

<h3>jQuery Code</h3>

<p>This is actually quite simple. I used a custom animation since <a href="http://docs.jquery.com/Effects">jQuery's built in effects</a> cannot accomplish this. In my example below, I changed the 
<samp>marginTop</samp> &amp; <samp>opacity</samp> properties on hover. Also, I added <samp>.stop()</samp> so that if a user hovers over the elements quickly it won't be lagging behind on the animations.</p>

<code>
$(document).ready(function(){
	$("#icons img").hover(function(){
		$(this).stop().animate({opacity: 0.75, marginTop: -10}, 400);
	},function(){
		$(this).stop().animate({opacity: 1.0, marginTop: 0}, 400);
	});
});
</code>

<h3>CSS Transitions</h3>

<p>This same effect can be accomplished using CSS Transitions in browsers that support it:</p>
 
<code>
#icons li img
{
-webkit-transition-property: margin-top, opacity;
-webkit-transition-duration: .4s, .4s;
}

#icons li img:hover
{
margin-top: -10px;
opacity: .75;
}
</code>

<h3>Demo</h3>

<p><a href="http://www.nealgrosskopf.com/tech/resources/64/">Click to see a live demo of this effect &gt;&gt;</a></p><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=64">View Comments [5]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=64</guid>
<author>Neal Grosskopf</author>
<category>jquery</category><category>css</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-01-17 17:30:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=63</link>
<description>
<![CDATA[
<figure class="image-caption">
    <a href="http://www.nealgrosskopf.com/tech/resources/63/"><img src="http://www.nealgrosskopf.com/tech/resources/63/jquery-dom-tool.png" alt="A jQuery Tool That Generates External Stylesheets From Your HTML Structure"></a>
    <figcaption>
        <h3>HTML to CSS Tool</h3>
        <p>My HTML to CSS tool will parse through your HTML structure, pull out IDs, classes and any inline CSS and create a basic stylesheet for you. 
        To see this article in action, feel free to skip right to the <b><a href="http://www.nealgrosskopf.com/tech/resources/63/">live demo &gt;&gt;</a></b></p>
    </figcaption>
</figure>

<p>I find myself converting Photoshop files to HTML &amp; CSS quite frequently. Whenever I find myself repeating a task I look for ways to make that task more 
efficient and therefore waste less of my time. One way my time is wasted during this process is when I rip out all of my inline CSS into an external stylesheet (or 
most likely an embedded stylesheet in the HTML document temporarily). Usually this involves identifying the IDs and class names of all my HTML elements as well as any inline styles I may have 
applied in the short-term.</p>

<p>Because of this, I set out to write some javascript that would parse my HTML, look for any elements with and ID or class name. The code also pulls out the inline styles and sorts them by property name. 
Finally, it also builds unordered list's CSS because whenever I have a unordered list within my template, it almost always needs further styling (think, navbar, footer etc.)</p>

<h3>Import jQuery</h3>

<p>As with any project, I import Google's hosted jQuery library. This will hopefully be cached in a users browser already:</p>

<code>
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&quot;&gt;&lt;/script&gt;
</code>

<h3>jQuery Pseudo Code</h3>

<p>Below is a quick overview of the jQuery:</p>

<code>
//Dim variables
//Check in DOM is ready to be used
//Select elements with an ID or CLASS

	//Select unique CLASSES

	//Create UL-LI placeholder CSS

	//Extract inline style CSS

//Push results to TEXTAREA
</code>

<h3>Variables</h3>

<p>Below are globally scoped variables which are outside the <samp>$(document).ready</samp> function. <samp>output</samp> is used for the final CSS. <samp>selector</samp> 
is really just a helper variable which can used to narrow the search for IDs and classes. This means you could look for elements <b>only</b> within another element i.e 
<samp>#content [id], #content [class]</samp>. Finally <samp>tclasses</samp> is used to store the names of classes so there are not duplicate class names in the stylesheet.</p>

<code>
var output = "";
var selector = "";
var tclasses = new Array();
</code>

<p>The rest of the code is wrapped within the <samp>$(document).ready</samp> function below. This basically checks to see if the DOM is loaded. Next it loops through elements that have an ID or class and finally 
sends the output to a textarea.</p>

<code>
$(document).ready(function(){
	$(selector + " [id]," + selector + "[class]").each(function(i){
	});
	
	//Code here
		
	$(&quot;body&quot;).append(&quot;&lt;textarea id='output'&gt;&quot;+output+&quot;&lt;\/textarea&gt;&quot;);
	$("#output").css({height: 400, width: 800});
});
</code>

<h3>Weed Out Duplicate Classes</h3>

<p>Next up, the ID/class names are pulled from the element list being looped through. Class names are then added to a global array. Finally since I find myself styling <samp>UL</samp> 
and <samp>LI</samp> elements frequently, I added some code in to create placeholder CSS for these i.e:</p>

<code>
#parent ul
{
}

#parent li
{
}
</code>

<p>Here's the code that creates that:</p>

<code>
	var tmp = "", childOutput = "";
	var tid = $(this).attr("id");
	var tclass = $(this).attr("class");
	var tstyle = $(this).attr("style");

	//Avoids adding duplicate CLASSES to stylesheet
	if(jQuery.inArray(tclass, tclasses) == -1)
	{
		//Adds current CLASS to array
		if(tclass) tclasses.push(tclass);

		//Adds UL and LI placeholder styles if they are children of a CLASS or ID
		$(this).children("ul").each(function() {
			if(tid)
			{
				childOutput = "#" + tid;
			} else {
				childOutput = "." + tclass;
			}
			childOutput = childOutput + " ul\n{\n}\n\n" + childOutput + " li\n{\n}\n\n";
		});
</code>

<h3>Extracting Inline CSS</h3>

<p>Next, the inline CSS is extracted from the elements. I'll explain later why this is tricky between different browsers:</p>

<code>
if(typeof(tstyle) != "undefined")
{
	properties = new Array();
	properties = tstyle.toLowerCase().split(";");

	//Raw input for testing
	//$("#test").html($("textarea").html() + "\n\n" + properties)

	//Loops through style attribute properties and trims them
	for ( var i=0, len=properties.length; i&lt;len; ++i )
	{
		if(properties[i] != "") properties[i] = jQuery.trim(properties[i]);
	}

	//Sorts array and finally merges it into a string with a seperator
	tmp = properties.sort().join(";\n") + ";";

	//First branch is for non-ie browsers, second is for IE			
	if(tmp.substring(0,1) == ";")
	{
		tstyle = tmp.substring(1,tmp.length);
	} else {
		if(tmp != "") tstyle = "\n" + tmp;
	}
} else {
	tstyle = "";
}
</code>

<h3>Sending the Results to a Textarea</h3>

<p>Finally the results of the above code is dropped in a <samp>textarea</samp>:</p>

<code>
//Creates output depending on if current element is a CLASS or an ID
if(tid)
{
	output = output + "#" + tid + "\n{" + tstyle + "\n}\n\n" + childOutput;
} else {
	output = output + "." + tclass + "\n{" + tstyle + "\n}\n\n" + childOutput;
}
</code>

<h3>Browser Variances</h3>

<p>I found the inline CSS returned from Javascript could vary by browser, especially when working with CSS shorthand notation. <b>Internet Explorer</b> 
prefers to seperate out <samp>border: 1px solid #000;</samp> to the following:</p>

<code>
border-bottom: black 1px #000;
border-left: black 1px #000;
border-right: black 1px #000;
border-top: black 1px #000;
</code>

<p>While <b>Firefox</b> does the following:</p>

<code>
border: 1px solid rgb(0, 0, 0);
</code>

<p><b>Webkit</b> based browsers such as Safari &amp; Google Chrome seem to be more web developer friendly by leaving the original CSS intact:</p>

<code>
border: 1px solid #000;
</code>

<h3>Other Browser Variances</h3>

<p>This gets further complicated when using the <samp>background</samp> property especially in Firefox:</p>

<code>
-moz-background-clip: border;
-moz-background-inline-policy: continuous;
-moz-background-origin: padding;
background: rgb(221, 221, 221) none repeat scroll 0% 0%;
</code>

<p>Fortunately, Safari and Google Chrome again, keep the original CSS intact:</p>

<code>
background-color: #f1f1f1;
</code>

<p>Because of this, you may consider using my tool in Google Chrome or Safari as they seem to keep the original code the same.</p>

<p>Check out the <b><a href="http://www.nealgrosskopf.com/tech/resources/63/">final results &gt;&gt;</a></b></p>

<h3>A Bookmarklet</h3>

<p>Finally, I created a <a class="b" href='javascript:void(function(){ var s=document.createElement("script"); s.setAttribute("src","http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"); if(typeof jQuery!="undefined") { var msg="This page already using jQuery v" + jQuery.fn.jquery; } else { document.getElementsByTagName("head")[0].appendChild(s); }  alert("Click to proceed"); var output="";var selector="";var tclasses=new Array();$(selector+" [id],"+selector+"[class]").each(function(i){var tmp="",childOutput="";var tid=$(this).attr("id");var tclass=$(this).attr("class");var tstyle=$(this).attr("style");if(jQuery.inArray(tclass,tclasses)==-1){if(tclass)tclasses.push(tclass);$(this).children("ul").each(function(){if(tid){childOutput="#"+tid}else{childOutput="."+tclass}childOutput=childOutput+" ul\n{\n}\n\n"+childOutput+" li\n{\n}\n\n"});if(typeof(tstyle)!="undefined"){properties=new Array();properties=tstyle.toLowerCase().split(";");for(var i=0,len=properties.length;i<len;++i){if(properties[i]!="")properties[i]=jQuery.trim(properties[i])}tmp=properties.sort().join(";\n")+";";if(tmp.substring(0,1)==";"){tstyle=tmp.substring(1,tmp.length)}else{if(tmp!="")tstyle="\n"+tmp}}else{tstyle=""}if(tid){output=output+"#"+tid+"\n{"+tstyle+"\n}\n\n"+childOutput}else{output=output+"."+tclass+"\n{"+tstyle+"\n}\n\n"+childOutput}}});$("body").prepend("&lt;textarea&gt;"+output+"&lt;/textarea&gt;"); $("textarea").css({height: 400, width: 800});  }())'>Bookmarklet</a> 
that can be used on any webpage or website on the internet. This means you can add this as a bookmark/favorite and run it on any website.</p>

<h3>Thoughts?</h3>

<p>So what do you think? Does this look like something that could help you speed up your development time? Leave your thoughts below &gt;</p><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=63">View Comments [11]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=63</guid>
<author>Neal Grosskopf</author>
<category>html</category><category>css</category><category>jquery</category>
</item>
<item>
<title>Geek Speak From www.NealGrosskopf.com - 2010-01-03 17:05:00</title>
<link>https://www.nealgrosskopf.com/tech/thread.php?pid=62</link>
<description>
<![CDATA[
<figure class="image-caption">
    <a href="http://www.nealgrosskopf.com/tech/resources/62/"><img src="http://www.nealgrosskopf.com/tech/resources/62/example.jpg" alt="View the Facebook-esque Photo Tagging demo"></a>
    <figcaption>
        <h3>Example vs. Facebook</h3>
        <p>In this article I'll show you how to create a Facebook-like photo tagging feature. If you're like me you're probably more interested in a live example than digging through this 	entire article so here is a <b><a href="http://www.nealgrosskopf.com/tech/resources/62/">live demo of the above example</a></b>.</p>
    </figcaption>
</figure>

<h3>Importing the jQuery Library</h3>

<p>As with all my examples using jQuery, I link to Google's hosted version. If a user already has the file in their browser cache, it cuts down on another HTTP request thus 
saving your users time.</p>

<code>
&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"&gt;&lt;/script&gt;
</code>


<h3>HTML Setup</h3>

<p>Below is all the HTML needed for my image tagging example. I dynamically insert much of the other needed HTML via jQuery. Originally I planned to make this a jQuery plugin. This could still easily be accomplished by taking the code within 
<samp>$(document).ready</samp> &amp; adding it into a standard plugin code block.</p>

<code>
&lt;img src="image.jpg" style="width: 604px; height: 423px;"&gt;
</code>


<h3>CSS Setup</h3>

<p>Unlike many of my other articles, there is a lot more code needed to achieve the desired effect. Because of this I probably won't walk you through line-by-line. Instead 
I'll give a brief description for some of the main elements in the DOM.</p>

<p><b>#tag-wrapper</b> - This is wrapped around the <samp>IMG</samp> element and is given a relative position. This allows us to position other elements absolute.</p>
<p><b>#tag-target</b> - This is a <samp>DIV</samp> which boxes in the target which a user has clicked on within the photo.</p>
<p><b>#tag-input</b> - This is a <samp>DIV</samp> which contains a label, input box &amp; submit/reset buttons. It is attached to the #tag-target <samp>DIV</samp>.</p>
<p><b>.hotspot</b> - Finally after a tag has been assigned, a .hotspot <samp>DIV</samp> is created and positioned over the desired location on the image.</p>

<code>
html, body { margin: 0px; padding: 0px; }
body
{
color: #666;
font-size: 12px;
font-family: Arial, Helvetica, sans-serif;
}

#tag-wrapper
{
border: 1px solid #ccc;
box-shadow: 0px 0px 10px #bbb;
-webkit-box-shadow: 0px 0px 10px #bbb;
-moz-box-shadow: 0px 0px 10px #bbb;
display: block;
padding: 10px;
position: relative;
}

	#tag-target, #tag-wrapper img { cursor: crosshair; }
	
	#tag-wrapper img { position: absolute; }
	
	#tag-target
	{
	display: none;
	border: 4px solid #fff;
	box-shadow: 0px 0px 20px #000;
	-webkit-box-shadow: 0px 0px 20px #000;
	-moz-box-shadow: 0px 0px 20px #000;
	height: 100px;
	width: 100px;
	position: absolute;
	top: 0px;
	left: 0px;
	z-index: 2;
	}
	
	#tag-input
	{
	background: #fff;
	display: none;
	padding: 5px;
	position: absolute;
	top: 0px;
	left: 0px;
	width: 137px;
	z-index: 2;
	}
	
		#tag-input label
		{
		display: block;
		font-weight: bold;
		}
		
		#tag-input input
		{
		border: 1px solid #ccc;
		color: #888;
		display: block;
		margin: 5px 0px;
		outline: 0px;
		padding: 3px;
		width: 124px;
		}
	
	.hotspot
	{
	border-width: 0px;
	box-shadow: 0px 0px 0px #000;
	-webkit-box-shadow: 0px 0px 0px #000;
	-moz-box-shadow: 0px 0px 0px #000;
	height: 100px;
	width: 100px;
	position: absolute;
	}
	
		.hotspot:hover, .hotspothover
		{
		border: 4px solid #fff;
		box-shadow: 0px 0px 20px #000;
		-webkit-box-shadow: 0px 0px 20px #000;
		-moz-box-shadow: 0px 0px 20px #000;
		z-index: 1;
		}
		
		.hotspot span { display: none; }
		.hotspot:hover span, .hotspothover span
		{
		background: #fff;
		display: block;
		font-weight: bold;
		padding: 3px 0px;
		text-align: center;
		}

.remove { color: #748950; cursor: pointer; text-decoration: underline; }
</code>


<h3>Global Javascript Variables</h3>

<p>Below are the global Javascript variables used. <samp>targetX</samp> &amp; <samp>targetY</samp> plot coordinates for where the user clicks on the image. <samp>tagCounter</samp> is used 
to give each of the tags a unique <samp>ID</samp></p>

<code>
//Placed outside .ready for scoping
var targetX, targetY;
var tagCounter = 0;
</code>


<h3>$(document).ready Javascript</h3>

<p>In the main code block I've liberally added comments to explain each line of code:</p>

<code>
$(document).ready(function(){
	//Dynamically wrap image
	$("img").wrap('&lt;div id="tag-wrapper"&gt;&lt;/div&gt;');
	
	//Dynamically size wrapper div based on image dimensions
	$("#tag-wrapper").css({width: $("img").outerWidth(), height: $("img").outerHeight()});
	
	//Append #tag-target content and #tag-input content
	$("#tag-wrapper").append('&lt;div id="tag-target"&gt;&lt;/div&gt;&lt;div id="tag-input"&gt;&lt;label for="tag-name"&gt;Person\'s Name:&lt;/label&gt;&lt;input type="text" id="tag-name"&gt;&lt;button type="submit"&gt;Submit&lt;/button&gt;&lt;button type="reset"&gt;Cancel&lt;/button&gt;&lt;/div&gt;');
	
	//$("#tag-wrapper").click(function(e){
	$("img").click(function(e){		
		//Determine area within element that mouse was clicked
		mouseX = e.pageX - $("#tag-wrapper").offset().left;
		mouseY = e.pageY - $("#tag-wrapper").offset().top;
		
		//Get height and width of #tag-target
		targetWidth = $("#tag-target").outerWidth();
		targetHeight = $("#tag-target").outerHeight();
		
		//Determine position for #tag-target
		targetX = mouseX-targetWidth/2;
		targetY = mouseY-targetHeight/2;
		
		//Determine position for #tag-input
		inputX = mouseX+targetWidth/2;
		inputY = mouseY-targetHeight/2;
		
		//Animate if second click, else position and fade in for first click
		if($("#tag-target").css("display")=="block")
		{
			$("#tag-target").animate({left: targetX, top: targetY}, 500);
			$("#tag-input").animate({left: inputX, top: inputY}, 500);
		} else {
			$("#tag-target").css({left: targetX, top: targetY}).fadeIn();
			$("#tag-input").css({left: inputX, top: inputY}).fadeIn();
		}
		
		//Give input focus
		$("#tag-name").focus();	
	});
	
	//If cancel button is clicked
	$('button[type="reset"]').click(function(){
		closeTagInput();
	});
	
	//If enter button is clicked within #tag-input
	$("#tag-name").keyup(function(e) {
		if(e.keyCode == 13) submitTag();
	});	
	
	//If submit button is clicked
	$('button[type="submit"]').click(function(){
		submitTag();
	});

}); //$(document).ready
</code>

<h3>Functions</h3>

<p>Finally, here is a few functions I use for adding/removing tags:</p>

<code>
function submitTag()
{
	tagValue = $("#tag-name").val();	
	
	//Adds a new list item below image. Also adds events inline since they are dynamically created after page load
	$("#tag-wrapper").after('&lt;p id="hotspot-item-' + tagCounter + '"&gt;' + tagValue + ' &lt;span class="remove" onclick="removeTag(' + tagCounter + ')" onmouseover="showTag(' + tagCounter + ')" onmouseout="hideTag(' + tagCounter + ')"&gt;(Remove)&lt;/span&gt;&lt;/p&gt;');
	
	//Adds a new hotspot to image
	$("#tag-wrapper").append('&lt;div id="hotspot-' + tagCounter + '" class="hotspot" style="left:' + targetX + 'px; top:' + targetY + 'px;"&gt;&lt;span&gt;' + tagValue + '&lt;/span&gt;&lt;/div&gt;');
	
	tagCounter++;
	closeTagInput();
}

function closeTagInput()
{
	$("#tag-target").fadeOut();
	$("#tag-input").fadeOut();
	$("#tag-name").val("");
}

function removeTag(i)
{
	$("#hotspot-item-"+i).fadeOut();
	$("#hotspot-"+i).fadeOut();
}

function showTag(i)
{
	$("#hotspot-"+i).addClass("hotspothover");
}

function hideTag(i)
{
	$("#hotspot-"+i).removeClass("hotspothover");
}
</code>

<h3>Above &amp; Beyond</h3>

<p>I did add a few effects that Facebook does not have. For instance I added fading effects on pretty much everything I could. I often find that adding a fade or slide effect 
gives applications a more "polished look". I also added an animation if you click a new location for the target tag. Once again, here's a link to the 
<b><a href="http://www.nealgrosskopf.com/tech/resources/62/">finished product &gt;&gt;</a></b></p><p><a href="https://www.nealgrosskopf.com/tech/thread.php?pid=62">View Comments [68]</a></p>]]>
</description>
<pubDate>Sat, 04 Apr 2026 12:51:02 -0500</pubDate>
<guid>https://www.nealgrosskopf.com/tech/thread.php?pid=62</guid>
<author>Neal Grosskopf</author>
<category>css</category><category>jquery</category>
</item>
</channel>
</rss>
