Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Wednesday, October 8, 2008

Scalable DOM Module With Rounded Corners

I am working on a homepage for this site and several other site improvements. For that work, I wanted a reusable DOM fragment with accompanying CSS that had rounded corners, a slight gradient background, and scaled well. Here is an example of what I designed. The HTML markup is fairly simple:

Example 1: Module HTML Markup

<div class="module"> <div class="moduleHeaderOuter"> <div class="moduleHeaderInner"><h3>Header Content Here</h3></div> </div> <div class="moduleContentOuter"> <div class="moduleContentInner">Content Here</div> </div> <div class="moduleFooterOuter"><div class="moduleFooterInner"></div></div> </div>

The “div.module” element is just a container and can be styled the way you like it, although it will need to be at least as wide as the graphics you use for the right-side of the backgrounds (more on this later). I chose to use 6 divs to manage the background in a scalable, x-browser way. The outer divs render the right side of the background, while the inner divs contain content and render the left side of the content. The background sides have to be separated for two reason: we do not want to use a fixed width for the module content, so the CSS and background images need to be size naive; and the rounded corners backgrounds cannot overlap, or the solid background of one will cover the transparent part of the other.

You can add content to the inner header, which I have done with a sectional ‘h3′ tag, and to the inner content. The inner content has no height constraints as we are repeating an image with a 1px height, but the header row should only have one line height. I used image spriting for the backgrounds and the header only has 60px of background height, which should be reserved for user-driven font scaling. The footer is only an image of 10px height, so it is currently designed as a placeholder and cannot contain any content (this is to reduce the image size of the sprite). Originally, I used the ‘h3′ tag instead of the inner and outer header divs, but in the end I decided to use extra divs because the ‘h3′ tag has differing font-sizes from the other wrapper divs, and this way is easier to read and more consistent.

For the background to work, I need three image files: a sprite image for the header and footer (4 images in this sprite, one for each corner), a 1px height image for the left background, and a 1px height image for the right background. The left-side images need to be 2x wider than the intended width of your widest module widget, so that they can scale, while the right-side images need only be 1/4 the width of the left-side images, as they do not need to scale very much. The height of the header sprite is 3x greater than the intended height of the headers in the example, to allow for scaling. If you decide that you want to put content into the footers, simply increase the height of the footer sprites to a value 3x greater than the default height of your footer.

So now that we have the images and the HTML, here is the CSS that puts it all together:

Example 2: Module CSS

div.moduleFooterOuter, div.moduleContentOuter, div.moduleHeaderOuter { margin-left: 1em; margin-right: 1em; padding-right: 1em; } div.moduleFooterInner, div.moduleContentInner, div.moduleHeaderInner { padding: 0em 1em; /* this spaces the content away from the module edge */ } div.module div.moduleHeaderOuter { background: transparent url(../images/sprite/module_sprite.gif) no-repeat right -120px; } div.module div.moduleHeaderInner { background: transparent url(../images/sprite/module_sprite.gif) no-repeat left top; padding: 0.2em 1em; } div.moduleFooterOuter { background: transparent url(../images/sprite/module_sprite.gif) no-repeat right -360px; } div.moduleFooterInner { background: transparent url(../images/sprite/module_sprite.gif) no-repeat left -240px; height: 11px; } div.moduleContentOuter { background: transparent url(../images/bg/module_bg_right.gif) repeat-y right top; } div.moduleContentInner { background: transparent url(../images/bg/module_bg_left.gif) repeat-y left top; }

The outer containers use margins, because the “div.module” class will most likely have a width applied, and IE 6 behaves poorly when you apply a width or height and a margin or padding to an element. The “padding-right” of the outer container is what prevents the background images from overlapping each other. The only other tricky part is the negative positions on some of the backgrounds, which are used to find the right sprite as they are positioned every 120px in ‘module_sprite.gif’.

See it all working together in this Module Example.

posted by Matt Snider at 10:14 am  

Wednesday, September 10, 2008

Absolute Position Layer

In my projects, I frequently find the need to absolute position a div somewhere on the page (on Mint.com we things like position popups and autocomplete/menu widgets). At one time absolute positioning elements was a real chore, as browsers treat absolute positioning differently, depending on where the element is in the DOM and the positioning of the parent elements (more on positioning: Position Everything). I needed a technique to that allowed me to position any number of elements absolutely, without having to worry about x-browser hacks. The solution is to insert a ‘layer’ div as the first element of body, which will parent all other elements needing to be position absolutely.

Example 1: HTML for Layer

<body> <div id="layer"></div> ... the rest of the page </body>

This layer then needs the following CSS:

Example 2: CSS for Layer

#layer { height: 0px; left: 0px; overflow: visible; position: absolute; top: 0px; width: 100%; z-index: 10; }

This CSS positions the layer, absolutely itself to the top left of the page and will work in all browsers (unless your body element is absolutely positioned). We give it a height of ZERO so that it doesn’t affect or cover up any portion of the DOM. The width of 100% is a fix for browsers where overflow doesn’t work right when the element has no width, and the z-index is set so that all children of ‘layer’ have a slightly higher z-index than the rest of the page (as you will probably be positioning over other elements on the page). The final key to make this all work is setting the ‘overflow’ to ‘visible’. That way, even though the children will have vertical dimensions greater than the ‘layer’ div, they will still be visible and not affect other elements in the DOM.

Now if you include ‘layer’ on your sites main template, then you always have the ability to add an x-browser enabled, absolutely positioned element. Simply append the element to the layer, position it to your liking, and manage whether it is visible or not. Here is a fun little layer example where I put a bunch of elements in layer and positioned them to look like the acid 2 test.

posted by Matt Snider at 10:19 am  

Powered by WordPress