Archives

Archives / 2007 / September
  • Adding Gravatars to your ASP.NET site in a few lines of code

    Gravatar (Globally Recognized Avatar) provides a simple way to add avatars to community based sites. Users set up an account at http://site.gravatar.com with an avatar image and an e-mail address, then their avatar shows up on any site which support Gravatars - blogs, community sites, etc. Gravatar take care of hosting and resizing the images, handles things like decency ratings, and they've got a nice UI for image upload / cropping.

    Read more...

  • Taking CSS beyond a simple style library

    Summary

    CSS based design is really all about your HTML structure. We'll look at bad examples, then good examples. Finally, I'll point out some resources for generating stylable HTML in ASP.NET.

    Ugly HTML, bad CSS

    A lot of web developers haven't really gotten the point of CSS, so they're not getting the full benefit. They see CSS as a kind of global style constants file, in the same way they'd pack all their string constants into a resource or config file. Need a bold blue heading? Yep, I think I've got one of them... There it is:

    .BigBlueText

    { color: #99f; font-size: 16px; }

    No... that's not big enough. Time for BiggerBlueText!

    .BiggerBlueText

    { color: #99f; font-size: 22px; }

    The HTML reflects this mentality: ID's and Classes are assigned as necessary to apply the styles. There's often no rhyme or reason to them other than to map the styles to the HTML elements. Unfortunately, that completely misses the point. Although it's unfortunate that you aren't getting the maximum value out of CSS based styling, but the real crime is that those who want to restyle your work in the future don't have the hooks they need.

    A classic example of that kind of unstylable HTML (impervious to CSS) is that returned by SQL Server Reporting Services. I've made some attempts to style SSRS and make it work cross-browser, but there are major limits to what can be done. Often parent elements have no class names assigned; other times class names are assigned but are re-used based on style. That makes it impossible to change the style of the class without destroying the entire page. Here's a short snippet (by far not the worst!) to show you what I mean - notice that the class "msrs-normal" has nothing to do with structure or content; it's only included to simplify styling the page.

    <td valign="top" width="50%"><table width="100%" class="msrs-normal" cellpadding="0" cellspacing="0"> <tr> <td valign="top" width="50%"><table width="100%" class="msrs-normal" cellpadding="0" cellspacing="2"> <tr> <td valign="top" width="18px"> <a href="..."> <img src="..." height="16" width="16" alt="Report" border="0" /> </a> </td> <td valign="top"><a href="..." id="ui_a0">...</a></td> </tr> <tr> <td valign="top"><img src="..." height="2" width="1" border="0" /></td> </tr> </table> </td> </tr> <tr> <td valign="top" width="50%"><table width="100%" class="msrs-normal" cellpadding="0" cellspacing="2">

    Once we talk about how this SHOULD work, the problem with doing it wrong will be more obvious.

    Stylable pages don't mean you have to go nuts with classes

    You might think that really stylable HTML needs classes all over the place. That's not true, thanks to descendant selectors, which let you target elements inside a parent element. For instance, descendant selectors will let you style all <a> elements which appear inside a <div> with and id of "nav":

    div#nav a { font-weight:bold; }

    This is great because we're able to target specific elements (only <a> tags inside <div id="nav">) without a lot of extra work or code.

    CSS that's based on page structure

    CSS Zen GardenThe classic example of great CSS is CSS Zen Garden. It's a beautiful example of what good designers can do with CSS, but most people don't consider the unsung hero: cleanly structured HTML. The page structure is designed for styling. Since the page is designed so that it can be styled via descendant selectors:

    • The HTML is very simple, structured around the page's information rather than design
    • It's got ID's assigned to all of the containers elements

    So, now, let's look at a the structure of the  HTML used in CSS Zen Garden.

    <BODY id=css-zen-garden> <DIV id=container> <DIV id=intro> <DIV id=pageHeader> <H1>...</H1> <H2>...</H2> </DIV> <DIV id=quickSummary> <P>...</P> <P>...</P> </DIV> <DIV id=preamble> <H3>...</H3> <P>...</P> <P>...</P> <P>...</DIV> </DIV> <DIV id=supportingText> <DIV id=explanation> <H3>...</H3> <P>...</P> <P>...</P> </DIV> <DIV id=participation> <H3>...</H3> <P>...</P> <P>...</P> <P>...</P> </DIV> <!-- Okay, Jon, we get the point. You can skip the rest. --> </DIV> </DIV> </DIV> </BODY>

    So, we've got a really simple page that's been restyled hundreds of times by a wide variety of cutting edge designers. It's all possible because the HTML was constructed in such a way as to expose the page elements as something like a design API (application programmer's interface). There are no ID's or classes titled "big text" or "red footnote" because they're not at all necessary for a CSS developer to get at the elements they need. For example, let's say we want to modify the heading inside the "participation" div. No problem:

    div#participation h3 { margin-top: 2em; }

    Writing CSS Friendly HTML in ASP.NET

    The default rendering of ASP.NET controls isn't CSS Friendly, you can build CSS friendly sites in ASP.NET without too much effort. Take a look at the remix gallery for the VisitMix site, the most remix friendly ASP.NET site I'm aware of.

    By far, the nicest thing you can do for your markup is to use the ASP.NET CSS Friendly Control Adapters. Scott Guthrie has a tutorial on them, as does Scott Mitchell. They're really easy to setup and use - you drop some files in your site, and your controls go from <span><table><tr><td><table><tr> parties to using stylable elements like <ul>'s. They went a little nuts with spraying classes on every single element (pretty redundant when you can do the same thing with descendant selectors), but it's a major improvement. Steve Harman and I used them on a project this past year, and it worked great.

    When you start using Visual Studio 2008 (if you're not already), be sure to look at the greatly improved CSS editing features. You'll also want to abandon the GridView for the new ListView control, which gives you a lot more control over the HTML your page generates. Here's how Rick Strahl describes the ListView:

    The ListView is a sort of hybrid between a DataGrid and Repeater that combines the free form templating of the Repeater with the editing features of the data grid. It looks interesting because it basically allows you much more control over the layout than a DataGrid does while still giving you many of the more advanced features of the data grid.

    Note: ID's and Classes

    An ID can only exist once on a page; a class can exist multiple times on a page. Generally, it's best to use a class rather than an ID if you're not sure. ID's are best used for structural containers like headers and footers, classes are used everywhere else. Every ASP.NET element is assigned an ID, but it may be munged a bit due to the effects of naming containers on nested controls. You can assign classes to any element you'd like - even the <body> tag - and ASP.NET won't touch them.

    David Shea's gone with a lot more ID's than classes for the CSS Zen Garden HTML, which makes sense because this page is completely static. There will never be another "preamble" here, mostly to allow graphic designers to tune their look down to the pixel. We're not so lucky, though. The client always wants to add another "preamble", usually late Saturday night. For that reason, I stick with Classes over ID's most of the time.

    Read more...

  • [Tip] Use RUNAS to set your Windows Auth domain for database connections

    Ever run into problems connecting to a database using Windows Authentication when you're not on that domain? I sure have - I was connecting over VPN, wanting to use SQL Server Management Studio, but my VPN account wasn't in the correct domain to authenticate. I ended up just using Remote Desktop whenever I needed to connect to that database for the length of that project... which dragged out more than year. Johnny Coder ran into it, too, but he's got the solution:

    Read more...

  • Why aren't Windows file copies restartable?

    Windows has supported restartable file copies for a while. CopyFileEx() has supported COPY_FILE_RESTARTABLE for a long, long time. ROBOCOPY has handled restartable file copies since Windows NT4 - maybe eight years ago? So you might think Windows Explorer would handle restartable file copies. Unfortunately, here's what you get when your connection drops for even a second:

    Read more...

  • Easier VPN connections from a Windows desktop

    Connecting to a VPN in Windows is a bit painful if you do it frequently. It's a relatively simple task, but it's "death by a thousand right clicks", and it takes a good fifteen seconds. If you're on and off VPN's frequently, it's worth taking the time to improve the process.

    Read more...

  • We should be virtualizing Applications, not Machines

    One of the benefits of my new job at Vertigo Software is that I have more frequent opportunities to talk with my co-worker, Jeff Atwood. If everything goes right, we argue... because if we agree, neither of us is going to learn anything. Recently, we argued about virtual machines. I think machine virtualization is hugely oversold. We let the technical elegance (gee whiz, a program that lets me pretend to run another computer as another program!) distract us from the fact that virtual machines are a sleazy, inelegant hack.

    Read more...