Centering images
categories: css, front-end development
An excellent article explaining the pros and cons of different image-centering methods. I love when I find something that gives me exactly the answer I need.
categories: css, front-end development
An excellent article explaining the pros and cons of different image-centering methods. I love when I find something that gives me exactly the answer I need.
categories: css
Occasional the folks at 37signals write a blog post that seems to channel thoughts that I've just never put to paper [blog]. This week they did it twice, with two posts about how they prefer to skip Photoshop and work with HTML and CSS when it comes to designing a web site.
I've found it incredibly pleasant to work with designers who have demonstrated knowledge and skill when it comes to CSS and HTML -- at my last job, our lead designer was also the guy you went to if you were stumped by a CSS issue. Knowing the tools means that production considerations become an active part of the design process: you don't create an element without giving some thought to how it will be built. In the best of worlds, you weigh the cost of building the element -- in time, in HTTP requests, in excessive markup -- against the benefit of having it on the site, and make educated decisions about what is "worth it."
I've never found Photoshop to be an adequate tool for mocking up a design -- it just doesn't "think" the way the web does, it just doesn't observe the constraints that the web imposes, and it just doesn't make accessible the parts of CSS that are truly powerful.
While I am no designer, I play one sometimes for freelance clients. When I haven't wanted to go straight to code, I've found that another Adobe product, InDesign, can be incredibly powerful. It's an application intended for print layout (and some of its related assumptions can be a little frustrating, such as its lack of a hex-based color picker/setter), but generally it is exponentially closer to the realities of the web than Photoshop. It thinks in boxes, not pixels, and offers paragraph-, character- and object-level stylesheets that can ... cascade! Just like with CSS, you can rapidly and dramatically alter the appearance of a page once you establish the base, semantic elements of it. It steers you to think about a page's structure, not just its presentation.
I'm hoping that the number of web designers who think that Photoshop is a sufficient tool will dwindle, but I'm not sure what the route is to get to that point. Photoshop's inadequacy in this regard is so clear to me -- and to people like the 37signals folks -- that I'm not sure how you persuade someone who still believes otherwise.
categories: front-end development, javascript
Ajaxian has the latest article I've come across about remote Javascript using document.write() (and a bit of a related issue when it comes to Google Analytics). They a link to yet another way to get around it by hijacking the browser's document.write(), just as John Resig suggested to me the last time I complained about this.
I said it before, I said it in my comment on the Ajaxian post, and I'll say it again: could the good folks at Google, and all the other sites that want us to give them traffic and/or money by placing their script tags all over our sites, maybe possibly spend some time coming up with methods that would:
Thanks. I'll be waiting.
categories: analytics, howto, jquery, plugins
We recently added a new feature to dailystrength.org, and there was much debate about whether users would use it as we intended. To find out, I wrote a clicktrack ditty that sends some data to the server when a link is clicked. It was somewhat inspired by a post I wrote a while ago about tracking outbound links with Google Analytics and jQuery, but is actually even simpler. I've retooled my clicktrack script to work as a generic, 2.5k plugin, which you can download here.
To use this plugin, add a distinct classname to all links you would like to track. For example:
<a href="foo.html" class="clicktrack">this is a link</a>
You can also add additional classes to a link with a distinct prefix — the default prefix is "ct_". These classes will be passed to the server along with other clicktrack data:
<a href="foo.html" class="clicktrack ct_type_1">this is a link</a>
Then, include the script and a line of code to initialize it in the foot of your page. Note that you must at least pass a URL for the remote (server-side) script that will handle the clicktrack data ("foo.php" in the example below):
<script src="/includes/js/jquery.clicktrack.js">
type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() { $("a.clicktrack").clicktrack("foo.php"); });
</script>
This will pass the following data to a script called "foo.php" on your server:
The only required parameter is the URL of the remote script. However, you can pass a more elaborate configuration object. The options and their defaults are as follows:
var defaults = { remote_script: null, prefix: 'ct_', extraData: null, callback: function(){}, dataType: null, sendOnce: true, preventDefault: false };
window.location within the callback as required.categories: front-end development, javascript
It sounds like TechCrunch got burnt yesterday by some remote Javascript appearing too high in their pages' HTML. Visitors' browsers were waiting and waiting for the remote script to load, and refusing to render the rest of the page until it did.
All we knew is that our sites all simultaneously went down three times yesterday. After the first time we identified the likely problem as Seesmic and contacted the company. They assured us there was no way the plugin could take the site down. When it happened a second time we disabled the Seesmic plugin and the sites went back up. We identified the problem - the plugin was loading an external Javascript file, and when Seesmic’s servers were down, we just sat and waited for it for up to two minutes before timing out.
The remedy to this, of course, is to load remote scripts in the foot of the page, after all of the actual content has loaded. However, plenty of remote Javascript "widgets" aim at the least common denominator without offering a viable option for skilled users who don't actually want their site to break. The widget publishers simply require sites to put a remote script call exactly where the site wants the widget to appear. If the widget server chokes, the site is out of luck.
I wrote about a related problem with ad-related Javascript, and my attempts to get around its desire to appear wherever the ad appears, making page rendering grind to a halt if the ad network was slow. We ended up getting around that problem with a bit of utter absurdity: using an iframe that called some server-side code that would generate an HTML page that contained little more than a script tag.
Our solution, as it were, meant an extra HTTP request to our server for every ad on the page, just to avoid a problem that wouldn't exist in the first place if the authors of these widgets and ads would offer some real options to their savvier users. A simple method like
widget.appendToElement('foo')
seems like it would do the trick -- something that could be called at the end of a page and fail fairly silently by just leaving the destination element empty. I imagine that the use of such a method is hardly out of the reach of the good folks at TechCrunch, or plenty of other sites. Until an approach like this becomes a bit more common, expect many more rants like the one we saw from TechCrunch.
categories: front-end development, javascript
I have been coming across way too much remote Javascript that uses document.write() to insert its contents. From ad providers to video hosting services, it's common practice to provide a Javascript tag like:
<script src="http://some-remote-server.com/some-tiny-file.js" type="text/javscript"></script>
and tell the site owner to just include it in their page where the ad or content should appear.
This is a great least-common-denominator approach for folks who don't want to be bothered with understanding how this stuff works. The problem is that when an ad or a video or any other content loaded via remote Javascript needs to appear near the top of the HTML document, before the content, the site user doesn't see any more content while the browser fetches the file. In the case of one service we tried, the initial script tag actually wrote five more remote script tags, each of which requires a separate HTTP request, amounting to a total delay of more than a second before the content appeared. In the meantime, the user was staring at a near-empty page.
There are various hacks for getting around this, which involve loading the content low on the page and using (yet more) Javascript to move it to the appropriate place once the page has loaded, but they are hacky and not necessarily foolproof when it comes to ads. My initial experiments with doing this with some ad providers led to multiple ads appearing on the page, or to the whole page being replaced with just an ad.
If these services want people to stop complaining that their sites are loading slowly as a result of adding these tags (and perhaps looking at least for solutions that minimize the number of scripts that need to be loaded), it's time that they expose an API that will allow sites to include their script tag at the end of the page's HTML, where it belongs. Then sites could call a method to insert the ad wherever it's needed, once the content has finished loading.
For example:
ad.appendTo('#my_ad_container');
I grant that this would require a bit more code from the ad providers (and that their ads would load a little bit later than they do now), but the improvement in user experience would be tremendous, relative to waiting as much as a second or two for the ad — and thus the rest of the page — to load.
--
Update: If you're looking for a fix to this problem, also check out John Resig's document.write() rewrite.
categories: howto, javascript, troubleshooting
Google's AdSense ads, and lots of others, are added to pages using Javascript, and if that Javascript appears early in the page's HTML, it can seriously slow down the rendering of the rest of the page. That's because browsers generally refuse to do any further rendering of the page until they have a requested Javascript file in hand.
We ran into this with the ad in the left column of some pages on DailyStrength.org, which appears above the page content in the HTML; when we switched to a new ad provider, which required fetching multiple Javascript files, the issue was even more pronounced.
Since these ads only work when Javascript is enabled anyway, I decided to use some DOM manipulation (via jQuery, which is already on the page) to load the ad script in a hidden div at the bottom of the HTML, and then relocate the Javascript-generated iframe containing the ad to an empty, visible div where the ad needed to be:
$('#ad_hide').find('iframe').appendTo('#ad');
Now, loading the Javascript doesn't slow down the rendering of the content, and the ad appears right after the page is loaded.
categories: javascript, jquery
My friend Matt Henry and I are going to try to get a Javascript users group started in Durham so we can meet other users (and probably do a bit of jQuery evangelizing). If you're interested, visit the Triangle Javascript Users Group page, and join us at the Federal in downtown Durham on May 6.
categories: front-end development, javascript
I've been doing some serious work this week cutting down on YUI bloat -- our site was including the entire YUI library at the top of every page, at a cost of more than 200k. Worse, because the library was included at the top of every page, the rest of the page had to wait for it to load before it would render.
First, I switched all of our AJAX to use jQuery, the library we've standardized on going forward -- the fact that we had a wrapper function for all of our AJAX calls made this pleasantly easy. Then, I went through the code and figured out which YUI components were being used where. Once that was done, I was able to roll up a few core YUI files into a file to be included in the global header, and call other components only as needed. Total savings: 170k. Holy crap.
I'd still like to see us do away with YUI all together -- Ajaxian wrote about Ojay the other day, and all I could think was "OMG, you want me to use another library to make this library easier to use? I'll stick with jQuery, thanks" -- but considering how much javascript we'd have to rewrite, I'm at least feeling much better about 38k than 208k.
By the way, Marcus sent me a link to a great article about why this stuff matters: Use "SCORN" to test the front end of a website for performance by Scott Barber. It's made me get serious about cutting down on our number of HTTP requests, and so far, it seems to be making a difference.
categories: Uncategorized
I've been juggling 1.5 jobs for the last few weeks, but starting Monday it's back down to one, but a new one: I'll be doing front-end development for DailyStrength.org, which will hopefully give me plenty of front-end goodness to write about again. For all two of you paying attention to this site, sorry for the blackout.