Furious Angel

Pom down under

SVG Tutorials: Building a Three-State Button

clock April 8, 2008 21:21 by author Dave

This tutorial will walk you through creating a three-state button image that can be used in combination with CSS to create a similar button effect used by a standard Windows (and I assume Mac OS) button. I've chosen to create a button that looks just like one used by Windows Vista Aero but goal is to show how it can be done - don't be put off by my lack of imagination. There are any number of different images, shapes, colours to use when creating the same functionality.


The image below is of the SVG file with all three button states. Over the course of this tutorial we'll be building the file that displays this image.

SVG Button

Getting Started

In order to get the SVG images to render on your machine you need to register Svg.Web.SvgHandler to ensure that all requests made to *.svg files are picked up by the Svg.dll assembly.

(Note: If you're running in IIS7 or Visual Studio Development Server this is all you need to do. If you're running in IIS 5/6 you'll need to add *.svg files to be handed by the ASP.NET worker process.)

   1: <httpHandlers>
   2:   <add verb="GET" path="*.svg" type="Svg.Web.SvgHandler, Svg"/>
   3: </httpHandlers>

Creating the image

We'll start off by creating a simple rectangle representing the default button view.

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="246" height="25">
   3:   <rect width="80" height="22" rx="5" x="1" y="1" fill="#eee" stroke="#707070" />
   4: </svg>

The <svg/> element in the code above is the root of all SVG documents. This element must be the root element of all SVG documents.

Rectangles are represented by <rect/> elements. Why rect and not rectangle? One of the goals of SVG is to create lightweight files - rect is simply shorter and keeps file size just that little it smaller.

The width, height, x and y attributes from <rect/> shouldn't need any explaining but rx, fill and stroke do. SVG supports rounded corners on rectangles and the rx attribute value determines the x-axis radius of the rounded corners and the rx attribute (which I haven't specified - ry takes the value of rx if it hasn't already been specified) determines the y-axis radius of the rounded corner.

rr

The fill attribute allows a hex (e.g. #f00), rgb  (e.g. rgb(255, 0, 0)) or colour name (e.g red) to be specified. The stroke attribute allows the same values.

Knowing all this we know that the above is a light grey rectangle, 80 pixels wide, 22 pixels high with rounded edges 5 pixels in diameter. To create the three button states we need to add another two <rect/> elements to the document. They simply need to be positioned in the adjacent to each other in the same fashion above (you can out the positions pretty easily).

Text can be added using the <text/> element and placed using the x and y attributes. "Hello!" will do just fine for now. Now we can create three text elements with the same text or we can create the text element once and reuse it later on in the document.

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="246" height="25">
   3:   <defs>
   4:     <text text-anchor="middle" id="buttonText" fill="black" font-family="Verdana" font-size="12" y="16">Hello!</text>
   5:   </defs>
   6:   <rect width="80" height="22" rx="5" x="1" y="1" fill="gray" stroke="#707070"/>
   7:   <rect width="80" height="22" rx="5" x="83" y="1" fill="gray" stroke="#3C7FB1"/>
   8:   <rect width="80" height="22" rx="5" x="165" y="1" fill="gray" stroke="#2C628B"/>
   9:   <use xlink:href="#buttonText" x="40" />
  10:   <use xlink:href="#buttonText" x="122" />
  11:   <use xlink:href="#buttonText" x="204" />
  12: </svg>

All that's left is to add a little gradient here and there and add some strokes of various colours. Gradients are created by defining a <linearGradient/> element with two or more <stop/> elements. Any colour can be specified and an offset can be specified - this allows use to control where the colours begin and start to fade. I won't go into much detail here as you'll be able to fiddle with this yourself pretty easily.

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="246" height="25">
   3:   <defs>
   4:     <text text-anchor="middle" id="buttonText" fill="black" font-family="Verdana" font-size="12" y="16">Hello!</text>
   5:     <rect id="innerGlow" width="78" height="20" rx="5" x="2" y="2" fill-opacity="0"/>
   6:     <linearGradient id="button" x2="0%" y2="100%">
   7:       <stop stop-color="#F1F1F1" offset="47%"/>
   8:       <stop stop-color="#D1D1D1" offset="50%"/>
   9:     </linearGradient>
  10:     <linearGradient id="buttonOver" x2="0%" y2="100%">
  11:       <stop stop-color="#E7F4FB" offset="47%"/>
  12:       <stop stop-color="#C3E3F6" offset="50%"/>
  13:     </linearGradient>
  14:     <linearGradient id="buttonDown" x2="0%" y2="100%">
  15:       <stop stop-color="#DDF0FA" offset="40%"/>
  16:       <stop stop-color="#78BDE2" offset="50%"/>
  17:     </linearGradient>
  18:   </defs>
  19:   <rect width="80" height="22" rx="5" x="1" y="1" fill="url(#button)" stroke="#707070"/>
  20:   <rect width="80" height="22" rx="5" x="83" y="1" fill="url(#buttonOver)" stroke="#3C7FB1"/>
  21:   <rect width="80" height="22" rx="5" x="165" y="1" fill="url(#buttonDown)" stroke="#2C628B"/>
  22:   <use xlink:href="#buttonText" x="40" />
  23:   <use xlink:href="#buttonText" x="122" />
  24:   <use xlink:href="#buttonText" x="204" />
  25:   <use xlink:href="#innerGlow" stroke="white" />
  26:   <use xlink:href="#innerGlow" x="82" stroke="#30D5FE" />
  27:   <use xlink:href="#innerGlow" x="164" stroke="#9EB0BA" />
  28: </svg>

Okay, so how do I use it?

This next part is a little XHTML and CSS. There are likely multiple ways to achieve this (especially in XHTML) but I'm going to keep things pretty simple. The XHTML is an <a/> element with a class.

   1: <a class="svg-button" href="SimpleButton.aspx">Hello!</a>

With the XHTML in place we add the CSS that creates the three-state effect. There are probably a couple of different ways of doing this; some may not use a large negative indentation to hide the original link text for accessibility reasons. The perfect CSS for achieving this is beyond the scope of this post.

   1: .svg-button
   2: {
   3:     background: url(button.svg);
   4:     padding: 0;
   5:     margin: 0;
   6:     display: block;
   7:     width: 82px;
   8:     height: 24px;
   9:     text-indent: -9999px;
  10: }
  11: .svg-button:hover, .svg-button:focus
  12: {
  13:     background-position: 50% 0%;
  14: }
  15: .svg-button:active
  16: {
  17:     background-position: 100% 0%;
  18: }

Conclusion

I've kept this post pretty vague. I'm not going to recreate the documentation from the W3C site and I recommend you go there to learn more. My intention is to give a bit of a taster of what SVG is all about and how it can be used. Not only that but this post should let you see how easy it is to use the SVG rendering software.

The current release of the software (0.5.1) was used to create this sample.



SVG 0.5 Released to Codeplex

clock March 24, 2008 15:03 by author Dave

Around two weeks ago I released the first version of SVG to Codeplex. I've been putting off blogging about this until I'm familiar with the source control and happy with the Codeplex processes. Just seeing if it fits, I guess.

The released version supports a great deal of SVG features but certainly not all. It has been tested against many *.svg documents too. Most render properly, some render partially, some don't render at all. Most importantly though, this release can be used to create some pretty nifty images for a website.

Coming up in the next few weeks will be simple tutorials on how to use SVG to create some of those images. The first will be on how to create three-state buttons and another on how to create gradient images for use in a menu. They'll be a mix of SVG and CSS with no C#/.NET coding required. These tutorials will not require any image editor - Visual Studio or even notepad will do fine.

Even if you're not interested in using these tools the tutorials may still be of interest - SVG is a W3C language after all.



Upcoming SVG release details

clock March 4, 2008 21:06 by author Dave

As some of you may know I've been going on about a C# .NET SVG rendering engine for... well probably about a year now. I've made a lot of progress but it's a big specification and trying to even meet the simplest specs has been tough.

The rendering engine I'm talking about is an assembly that can be used in your .NET applications to load and render SVG documents. The need for this in the desktop world is very little. XAML does the job perfectly and I'd never try and replace that. I've been building this implentation primarily for the ASP.NET world.

Note that in no way am I trying to reduce the need for Silverlight or Flash. These plugins have their purpose and they do a damn fine job.

So what does it do?

Using an IAsyncHttpHandler you're able to register all files with extension *.svg to be handled by this SVG framework. When a request is made for one of these files the XML is loaded and then rendered to the output stream.

I see this being useful for several purposes.

  • List item bullet points
  • Menu item backgrounds
  • Image buttons
  • Any images that are fairly trivial - e.g. background gradients, button images with text on them.

That's not to say it can't be used for more complex images, but the goal of this project was to enable easy editing of the most common image files used by a website.

SVG files are extremely easy to edit using any text editor. This means that instead of having to open Photoshop and change that gradient and have *.psd files saved all over the place all you have is an XML file containing all the image data. If you decide to change the colour of a gradient it's a matter of changing say "#333" to "#666" via notepad (see Butterfly1(raw) and Butterfly2(raw) for examples). This change is instantly reflected on your site. Not only is it easy to change colours but it's also easy to change the size of an image without affecting image quality simply by opening the file in notepad and changing height and width.

Firefox and Opera do have SVG support but cannot be used everywhere you would like i.e. they have to be embedded and cannot (yet) be referenced in a CSS file for example. Using this SVG implementation will allow you to do this. The beauty of using this software is that in years to come when all browsers support SVG the handler can just be removed but until then there is no reason why we shouldn't be able to use SVG.

The version that's about to be released (on codeplex) does not render everything but it does support the most commonly used elements.

  • ellipse
  • rect
  • line
  • path
  • linearGradient
  • use
  • many more

Going forward

There are many more elements and attributes to support and there will of course be bugs to fix. Other than that I'm hoping to get a web service running to allow non-ASP.NET apps to use SVG files.

I'll post with more details and some examples later on in the week.