Saturnboy
 6.3

Going from SVG data to a Degrafa Path couldn’t be easier: just copy & paste. You can watch this video tutorial or you can check out this demo.

But there is one trick for Inkscape: even though the coordinate origin on the Inkscape document is the normal cartesian origin in the bottom left and the y-axis points up, the SVG output always uses the upper left corner of the document as the origin and the y-axis points down (per the SVG Spec, § 7.3).

To demonstrate, I created a new document in Inkscape, set my dimensions to 500 x 500, and placed a simple path (which happens to be a square) in the upper left corner:

square

You can see by the rulers in Inkscape that the square’s origin is at (0,500).

If we save our square and examine the SVG output, we see:

<svg ...>
  <g ...>
    <path d="M 0,0 L 100,0 L 100,100 L 0,100 L 0,0 z" />
  </g>
</svg>

If we ignore everything in the file except the relevant path data, we can see the very first path command is M 0,0 which is path-speak for move to (0,0). This is exactly as expected from the SVG spec: upper left is the coordinate origin. The cartesian origin in Inkscape is bogus!

Next, we can just copy the path data from the SVG file and paste it into the data attribute of a Degrafa Path component.

<Degrafa:Path data="M 0,0 L 100,0 L 100,100 L 0,100 L 0,0 z">
    <Degrafa:fill>
        <Degrafa:SolidFill color="#EECCEE" />
    </Degrafa:fill>
    <Degrafa:stroke>
        <Degrafa:SolidStroke color="#FF00FF" weight="3" />
    </Degrafa:stroke>
</Degrafa:Path>

Give it a fill color and a stroke color, and we get a pretty purple square. Now I know my Degrafa Path component will have a square in the upper left, because I know my square was in the upper left in Inkscape. Nice and easy.

Files

 3.4

A while back I started digging into the WindowShade component in Flexlib. I really needed a set of cool collapsable buckets for a project at work, and WindowShade was perfect for the task. Alas, I couldn’t find too much info on styling a WindowShade other than Doug McCune’s awesome example of WindowShade and Degrafa. So, here is how I went about achieving the look and feel I needed with WindowShade.

Plain Vanilla

I started with an unstyled, super vanilla WindowShade wrapping a List. And of course, I get this super-vanilla output:

shade 1 (view source enabled)

The only styling magic was to add padding="0" to the WindowShade to get the child List component to suck up to the bottom of the WindowShade button.

My First Attempt

In the next pass, I ditched the lame WindowShade button, and went with Flexlib’s CanvasButton, which contains a simple Label plus a CheckBox skinned with a plus or minus graphic. The code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
        xmlns:mx="http://www.adobe.com/2006/mxml"
        xmlns:flexlibContainer="flexlib.containers.*"
        xmlns:flexlibControl="flexlib.controls.*"
        viewSourceURL="srcview/index.html">
 
    <mx:Script>
    <![CDATA[
        [Bindable]
        private var goodies:Array = [
            { header:'Ice Cream', items:['Vanilla', 'Chocolate', 'Strawberry', 'Cookies & Cream'] },
            { header:'Candy', items:['Twix', 'Snickers', 'Fire Balls', 'Hot Tamales', 'Mike & Ikes', 'Pez'] },
            { header:'Cookies', items:['Chewy Chips Ahoy', 'Mint Milano', 'Oreo', 'Nutter Butter', 'Fig Newtons'] }];
    ]]>
    </mx:Script>
 
    <mx:Style source="style.css" />
 
    <mx:VBox width="140" styleName="container">
        <mx:Repeater id="r" dataProvider="{goodies}">
            <flexlibContainer:WindowShade width="100%" styleName="shade"
                    data="{r.currentItem.header}"
                    opened="{r.currentIndex == 0}">
                <flexlibContainer:headerRenderer>
                    <mx:Component>
                        <flexlibControl:CanvasButton width="100%" height="30" styleName="shadeBtn">
                            <mx:Script>
                            <![CDATA[
                                import flexlib.containers.WindowShade;
                            ]]>
                            </mx:Script>
 
                            <mx:Label id="header" top="3" left="4" text="{WindowShade(parent).data}" styleName="shadeHead"/>
                            <mx:CheckBox id="chk" top="9" right="6" selected="{WindowShade(parent).opened}" styleName="shadeChk"/>
                        </flexlibControl:CanvasButton>
                    </mx:Component>
                </flexlibContainer:headerRenderer>
 
                <mx:List width="100%" dataProvider="{r.currentItem.items}" rowCount="{r.currentItem.items.length}" styleName="shadeList"/>
            </flexlibContainer:WindowShade>
        </mx:Repeater>
    </mx:VBox>
</mx:Application>

After throwing in some colors from a sweet Kuler theme and embedding Helvetica, we get this:

shade 2 (view source enabled)

At this point, I was really happy with look and feel, but there we still a few minor issues with the CanvasButton header that needed to be fixed before declaring victory.

Fixups

First, I needed the rollover event to flow down to the checkbox, so it would correctly show the overSkin on mouse over. Second, I wanted a color change on the Label on rollover to provide better visual feedback to the user. And lastly, I wanted the entire CanvasButton header to be clickable, not just the label text or the checkbox graphic.

Focusing just on the modified CanvasButton code, used in the headerRendered:

<flexlibControl:CanvasButton width="100%" height="30" styleName="shadeBtn"
        rollOver="header.setStyle('color', 0xffffff); chk.dispatchEvent(event);"
        rollOut="header.setStyle('color', 0xcccccc); chk.dispatchEvent(event);">
    <mx:Script>
    <![CDATA[
        import flexlib.containers.WindowShade;
    ]]>
    </mx:Script>
 
    <mx:Label id="header" top="3" left="4" text="{WindowShade(parent).data}" styleName="shadeHead"/>
    <mx:CheckBox id="chk" top="9" right="6" selected="{WindowShade(parent).opened}" styleName="shadeChk"/>
    <mx:Canvas width="100%" height="100%" backgroundColor="#000000" backgroundAlpha="0" />
</flexlibControl:CanvasButton>

The final result, a nice styled WindowShade:

shade 3 (view source enabled)

I used the parent CanvasButton’s rollover event to set the child Label color and forward the event to the child CheckBox. To make the entire button clickable, I used one of my favorite Flex UI hacks: I added a space-filling transparent Canvas.

Comparison Shopping

And finally, a side-by-side comparison of all three WindowShade skins:

Flash is required. Get it here!

 2.8

Flex is awesome. In many ways, it’s the right tool for the job of bringing beautiful design to the web. I use flex every day at work, and also at home on my own fun projects. Today’s challenge is to take a very simple blog design and re-implement it in flex.

In The Red Corner

I’ll start with my simple two-column blog design that I like to call Circles of Doom. The original design was done in Inkscape, and assembled for the web using Blueprint CSS. You can read all the gory details of the design and assembly in a series of earlier posts: part 1, part 2, part 3, part 4.

Skipping right to the end result, you can view the final results here:

 

In The Blue Corner

Flex provides a lot of design leverage with its support for fills & strokes, gradients, rounded corners, and filters like drop shadow and glow. The original html design required the use of images to handle these features, but Flex’s CSS is powerful enough to handle everything with the exception of the blood red background circles.

The design architecture can be thought of as a simple three layer structure show here:

flex layers diagram

The bottom layer has the blood red background circle image. It is absolutely positioned vertically (y="-65") and horizontally centered (x="{(this.width - 950)/2}"). Like this:

<mx:Image source="@Embed(source='assets/circ.png')"
        x="{(this.width - 950)/2}" y="-65" />

The middle layer has the main box with rounded corners and a black glow. Like this:

<mx:VBox width="870" x="{(this.width - 870)/2}" y="130" styleName="body">
    <mx:filters>
        <mx:GlowFilter blurX="22" blurY="22" color="#111111" alpha="0.6" />
    </mx:filters>
</mx:VBox>

And the Flex CSS:

VBox.body {
	horizontalAlign: center;
	backgroundColor: #ffffff;
	borderStyle: solid;
	borderThickness: 10;
	borderColor: #886655;
	cornerRadius: 28;
	verticalGap: 10;
	paddingTop: 20; paddingBottom: 4;
}

And the top layer has the main content, sidebar & sidebar content, and footer. Like this:

<mx:Canvas width="790">
    <mx:Text text="main" width="590" styleName="contentTxt" />
 
    <mx:VBox width="190" x="600" styleName="sidebar">
        <mx:Text text="sidebar" width="100%" styleName="sidebarTxt" />
    </mx:VBox>
</mx:Canvas>
 
<mx:Text textg="footer" styleName="footerTxt" />

And the associated Flex CSS:

Text.contentTxt {
	fontFamily: Arial;
	fontSize: 12;
	fontWeight: normal;
	color: #000000;
}
 
VBox.sidebar {
	backgroundColor: #aa1100;
	borderStyle: solid;
	borderThickness: 2;
	borderColor: #ff2200;
	cornerRadius: 12;
	paddingLeft: 10; paddingRight: 10;
	paddingTop: 10; paddingBottom: 10;
}
 
Text.sidebarTxt {
	fontFamily: Arial;
	fontSize: 12;
	fontWeight: normal;
	color: #ffffff;
}
 
Text.footerTxt {
	fontFamily: Arial;
	fontSize: 10;
	fontWeight: normal;
	color: #886655;
}
The Result

Put it all together with some dummy Lorem ipsum text and you get a decent looking Flex blog design (just right-click, and select “view source” to see the code). It compares favorably to the original html design. The only obvious difference is the browser font rendering versus Flex’s font rendering.

The Files

 2.1

Once everything is done (meaning I have a layout, I have a design, and I have it sliced and assembled), I like to make another pass to optimize both the size of the image files, and the number of files. My two favorite techniques are using Sprites to reduce the total number of images, and using OptiPNG to compress the images.

Sprites

It is fairly common to see sprites used in high performance web design. The Gmail team has a great blog post discussing various performance enhancements currently in use, including sprites. But for some reason, almost everyone thinks of sprites for icons and buttons. In my opinion, any time you can fuse two images into one, you’re making a “sprite” and you’re improving performance. Using a grid-based framework like Blueprint CSS tends create a lot of rectangular layout imagery, which are often ideally suited for fusing into a larger sprite.

The current web page has two candidates for spriting: the main header image can be fused to the footer, and the sidebar header to the sidebar footer. Just like this:

fuse diagram

So the original circ-head.png and circ-foot.png are fused to create circ.png. Similarly, the sidebar header and footer are fused to create sidebar.png.

The original circ.css is simply modified with the new image filenames and a negative vertical offsets on the footer backgrounds. Here are the relevant parts of the new circ.css:

#header {
background:#111 url(img/circ.png) 0 0 no-repeat;
height:160px;
min-height:160px;
}
 
#footer {
background:#111 url(img/circ.png) 0 -160px no-repeat;
height:30px;
min-height:30px;
text-align:center;
}
 
#sidehead {
background:transparent url(img/sidebar.png) 0 0 no-repeat;
height:14px;
min-height:14px;
}
 
#sidefoot {
background:transparent url(img/sidebar.png) 0 -14px no-repeat;
height:14px;
min-height:14px;
}
Compression

Using OptiPNG is really easy. Just run it over a folder of PNGs, and it losslessly compresses what it can, and leaves the rest untouched. When I’m not using source control on a design, I’ll often perform the compression step exclusively on the server to keep things simple.

Here is a simple command to perform maximum compression of all the PNGs in a folder:

optipng -o7 *.png

Digging Deeper: I have noticed that OptiPNG, in it’s quest for maximum optimization, will sometimes alter the image type (either by reducing the bit depth or switching from full color to indexed color) in such a way as to make Photoshop very unhappy with the resulting image. In these cases, the GIMP is your friend.

The Results

We fused four images totaling 52552 bytes into two images totaling 52356 bytes. So we saved two whole HTTP requests and a meager 200 bytes. Not much to write home about (or even blog about), but hopefully it serves as a useful demonstration that design optimization is fairly simple. Next up, we’ll take our design and layout into Flex. What fun!

The Files

 12.7

The design from the last post is finished, and it follows a very simple blog layout. In this post, I’ll slice the design and turn it into a pretty html page with the magic of Blueprint CSS.

Slice It

Before we get slice happy, we need to think. First, Blueprint is grid-based, so that means rectangles are good. And second, the default Blueprint container width is 950px. The defaults are intelligently chosen and have always worked great for me. By sticking with the defaults, we will get a 950px wide, centered, fixed-width site, which is exactly what we want.

We could get all clever and try to slice out just the circles as a background image, but that would force the top border to be a transparent PNG because of the shadow. Similarly, we could cut out all four rounded corners and all four edges of the sidebar, but that would force us to reassemble humpty dumpty with some fancy css and markup. In both cases, just say No! The simplest possible choice is to slice the entire header, the entire footer, and then a thin slice for the body that can be vertically tiled. Exactly like this:

slice diagram

And we get: the header, the background tile, and the footer. Slicing the sidebar in the exact same manner gives: sidebar header, sidebar background tile, and sidebar footer.

Code It

The original simple blog layout had four divs: header, content, sidebar, and footer. This is exactly want we want, but the original markup won’t exactly work, because the current design has a vertically-tiled background. The solution is simple – just wrap the content and sidebar inside a div with a bit of padding (via a prepend-2 and append-2). If we ignore the sidebar design for a moment, and just insert a placeholder, the markup is:

<div class="container">
  <div id="header" class="span-24">header</div>
 
  <div id="bg" class="prepend-2 span-20 append-2">
    <div id="content" class="span-15">content</div>
    <div id="sidebar" class="span-5 last">sidebar</div>
  </div>
 
  <div id="footer" class="span-24">footer</div>
</div>

That’s just beautiful Blueprint markup! Adding some simple css:

body {
background-color:#111;
}
 
#header {
background:#111 url(img/circ-head.png) 0 0 no-repeat;
height:160px;
min-height:160px;
}
 
#footer {
background:#111 url(img/circ-foot.png) 0 0 no-repeat;
height:30px;
min-height:30px;
text-align:center;
}
 
#bg {
background:#fff url(img/circ-bg.png) 0 0 repeat-y;
}

And that gives us Circles of Doom, version 0! View it, or download it. I’ve included the latest-and-greatest Blueprint CSS, which is v0.8 at the time of writing. I’ve chosen to enforce the vertical height of the header and footer via height and min-height which seems to work fine in Firefox, Safari, and IE7.

Sidebar Me

Since the sidebar graphic was sliced in the exact same manner as the body graphic, we just add the exact same markup to the sidebar div – header, bg, and footer.

<div id="sidebar" class="span-5 last">
  <div id="sidehead" class="span-5"><!-- sidebar header --></div>
  <div id="sidebg" class="span-5">sidebar content</div>
  <div id="sidefoot" class="span-5"><!-- sidebar footer --></div>
</div>

Style it like this:

#sidehead {
background:transparent url(img/sidebar-head.png) 0 0 no-repeat;
height:14px;
min-height:14px;
}
 
#sidefoot {
background:transparent url(img/sidebar-foot.png) 0 0 no-repeat;
height:14px;
min-height:14px;
}
 
#sidebg {
background:transparent url(img/sidebar-bg.png) 0 0 repeat-y;
}

Putting everything together with some dummy Lorem Ipsum text gives us Circles of Doom, version 1! View it, or download it.

Debug It

Lorem Ipsum text is the basic unit testing for HTML+CSS. I always fill out every content div with some dummy text, just to see what breaks. This time around, I noticed the sidebar content was touching the edges. I decided against adding a prepend-1 and append-1 because that’s too much padding. Instead, I thought I might just add some padding to sidebg, but this is bad, bad, bad! You can not add padding or margins to a Blueprint node, which sidebg clearly is because of the class="span-5". I could add another div inside sidebg, but that seemed like too much markup. So, I took the easy way out and just padded the known sidebar content markup (in this case, just p and h3).

#sidebar h3, #sidebar p {
color:#fff;
padding:0 10px;
}

Digging Deeper: Blueprint CSS uses margin and padding to create the grid. Thus it should have been obvious to me that you can NOT add margins or padding to a Blueprint element (any markup element with a Blueprint grid class). Alas, it was not immediately obvious, but I was able to catch my mistake during debugging.

And that’s it for the visual aspect of Circles of Doom. Next, I’ll cover web design optimization.

The Files

© 2010 saturnboy.com