THAT Agency Design Studio Blog

If you’d like to see part one of the series you can go here: CSS Absolute Positioning.

In part 2, I’d like to go over CSS rounded corners. For ages I’ve spent time poring over websites trying to figure out what method would work best for getting me those coveted round corners in my site. The method we will be discussing today provides you with a box that is not only stretchable horizontally, but vertically as well, thus making this solution totally dynamic.

This method makes use of absolute positioning to create our edges and corners. There are quite a few variations based on what you’re trying to do with your rounded corners, but we’ll just be covering a simple box with a 1px rounded border like so:

The first thing you’re going to need are the images for each of the corners, and a one pixel image that is the same color. You can do this manually, or you can use a site like http://www.generateit.net/rounded-corner/ to generate your corners for you. I generally do the latter since everything is pre-cut and ready to go.

After you have the images, the HTML to create the box is pretty straightforward:

<div class="roundBox">
          <span class="top"> </span>
 
		 <span class="left">   </span>
		 <span class="right">   </span>
		 <span class="top-left">   </span>
		 <span class="top-right">   </span>
		 <span class="bottom-right">   </span>
		 <span class="bottom-left">   </span>
<div class="roundBoxText">
        This is some text inside the rounded box</div>
<!-- End Round Box Text --></div>
<!-- End Round Box -->

To explain the above code, we are basically creating a container “roundBox” to house the borders, and then creating the ‘s for each corner and edge of the box. This can be used as the basic html for a wide variety of rounded corner boxes.

Next, the css gets a little more inolved:

On to the css:

.roundBox {
position: relative;
padding: 4px 0px 4px 6px;
font-size: 14px;
height: 200px;
width: 200px;
text-align: center;
}
.roundBox .roundBoxText {
position: relative;
z-index: 2;
}
.roundBox .top-left, .roundBox .top-right, .roundBox .bottom-right, .roundBox .bottom-left, .roundBox .top, .roundBox .bottom, .roundBox .left, .roundBox .right {
position: absolute;
z-index: 1;
font-size: 0;
line-height: 0;
}
.roundBox .top, .roundBox .bottom {left: 3px;right: 3px; height: 3px;  }
.roundBox .left, .roundBox .right { top: 3px;bottom: 3px;width: 3px;}
.roundBox .top { top: 0; background: url(img/border.jpg) left top repeat-x;}
.roundBox .bottom {bottom: 0; background: url(img/border.jpg) left bottom repeat-x;}
.roundBox .left {left: 0; background: url(img/border.jpg) left top repeat-y;}
.roundBox .right { right: 0; background: url(img/border.jpg) right top repeat-y;}
.roundBox .top-left, .roundBox .top-right, .roundBox .bottom-right, .roundBox .bottom-left { height: 3px; width: 3px;}
.roundBox .top-left {top: 0; left: 0; background: url(img/tpl.png) left top no-repeat;}
.roundBox .top-right {top: 0;right: 0;background: url(img/tpr.png) right top no-repeat;}
.roundBox .bottom-right {bottom: 0; right: 0; background: url(img/btr.png) right bottom no-repeat;}
.roundBox .bottom-left { bottom: 0; left: 0;background: url(img/btl.png) left bottom no-repeat;}

This CSS looks very complicated, but is actually quite simple. In the first part, we are setting the general width and height of the box, and setting a few styling things like font size. The most important part of this is the position: relative. Building upon our previous post where we dealt with absolute positioning, this is necessary in order for the borders to be contained inside the container.

Next we are going to set each of the corners to position: absolute;, and give them a lower z-index than the content div (this isn’t necessary for this example, but you may have large borders that go under text in your own work). We then take each corner and edge and set them to their appropriate positions. For example, top-left would end up with top:0 and left:0;. For the edges, you will notice that the positions are not 0. This is done to keep the repeating edges from overlapping the corners.

And there you have it, a box with rounded corners with compatibility for all major browsers. This solution is great because it doesn’t require javascript, or any CSS hacks to work. It is just plain HTML and CSS. I do apologize to the HTML purists out there who don’t like the extra markup in their code, but it is my opinion that the tradeoff for universal support is well worth it.

See the live demo below, or download the source files:
Demo
Source Code

Share this article

So you’re not really into flash?
Don’t know how to code flash?
Don’t want to know how to code flash?
Love jQuery?

Well all this is pretty much me. Now a days most of the things you can do in flash, you can now do with jQuery; well somewhat. But that doesn’t stop us developers from trying right? One of our latest clients wanted a cool feature that I thought would be nicely shared with the rest of the web development community.

Let’s think of a box with rotating images inside. along with the images, we have a navigation menu that slides up / down while the images rotate. Pretty cool huh? well lets show you how I made this happen.

bg-rotate-slideup-nav-closed
Check out the Demo

Lets begin with the Basics of what is needed:

1. JQuery/ custom js
2. css/html/images

Javascript
<script src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js" type="text/javascript"><!--mce:0--></script>
<script src="bg-rotate-slide-up-js.js" type="text/javascript"><!--mce:1--></script>
<script type="text/javascript"><!--mce:2--></script>
CSS
body{margin:0;padding:0;}
#mainImageBox{position:relative;height:300px;margin-top:20px;margin-bottom:20px;margin-left:20%;}
#mainImageBox img{float:left;position:absolute;margin:0;padding:0;border:1px solid #6a39b3;}
#mainImageBox img.show{z-index:100}
.snapShot{margin:0;padding:9px;left:0;position:absolute;top:0;z-index:0;}
#mainImageBox #subNavBox{position:absolute;z-index:200;top:1px;left:1px;width:650px;height:300px;}
#mainImageBox #subNavBox .sNavWrap{float:left;position:relative;bottom:0;background-color:#6a39b3;margin:0 0 0 20px;padding:0;font-size:12px;text-align:center;top:269px;}
#mainImageBox #subNavBox .sNavWrap a{margin:0;padding:8px 10px;font-size:12px;font-family:Arial, Helvetica, sans-serif;color:#f9f9f9;text-decoration:none;text-align:center;display:block; text-transform:uppercase;font-weight:bold;}
#mainImageBox #subNavBox .sNavWrap .sSub{border-top:1px solid #ddd;margin:0;padding:0;}
#mainImageBox #subNavBox .sNavWrap .sSub a{display:block;margin:5px 0;padding:5px 0 8px 0;font-size:12px;font-family:Arial, Helvetica, sans-serif;color:#080808;text-decoration:none;text-align:center;display:block;text-transform:uppercase;font-weight:normal;}
.clear {clear: both;display: block;overflow: hidden;visibility: hidden;width: 0;height: 0;}.clearfix:after {clear: both;content:' ';display: block;font-size: 0;line-height: 0;visibility: hidden;width: 0;height: 0;}.clearfix {display: inline-block;}* html .clearfix {height: 1%;}.clearfix {display: block;}
HTML
<!-- begin main image box -->
 
<div id="mainImageBox">
    <img class="snapShot show" src="one.jpg" alt="One" width="650" height="300" />
    <img class="snapShot" src="two.jpg" alt="Two" width="650" height="300" />
    <img class="snapShot" src="three.jpg" alt="Three" width="650" height="300" />
    <!-- begin sub nav slide up box -->
 
<div id="subNavBox" class="sNav">
        <!-- list 1 -->
 
<div class="sNavWrap">
 
<div class="sHead">
            <a href="#">Header Link 1</a>
 
<div class="sSub">
                <a href="#">sub link for 1</a>
                <a href="#">sub link 2 for 1</a>
                <a href="#">sub link 3 for 1</a></div>
</div>
</div>
 
 
<!-- list 2 -->
 
<div class="sNavWrap">
 
<div class="sHead">
            <a href="#">Header Link 2</a>
 
<div class="sSub">
                <a href="#">sub link for 2</a>
                <a href="#">sub link 2 for 2</a>
                <a href="#">sub link 3 for 2</a></div>
</div>
</div>
</div>
 
 
<!-- end sub nav slide up box --></div>
 
 
<!-- end main image box -->

Building off of a carousel foundation I found, I stripped down to the bare minimum and ran from there. Here is all the Javascript written for this example:

Javascript (bg-rotate-slide-up-js.js)
$(document).ready(function(){
	/*****************************************************************************
		dealing with the navigation
	*****************************************************************************/	
 
	$(".sSub").each(function(){
		var newWidth = $(this).width();
		$(this).prev().css("width",newWidth);
		$(this).css("display","none");
		//alert( 300 - $(this).height() );
	});
	// Deal with Sub Nav
	$(".sNavWrap").hover(function(){
		// I Loath you IE fix
		if ($.browser.msie &amp;&amp; $.browser.version.substr(0,1)&lt;8){var minusPX = "33";}
		else{var minusPX = "32";}
 
		var newHeight = (300 - $(this).children().children(".sSub").height() ) - minusPX +"px";
		//alert(newHeight);
		$(this).animate({
			top: newHeight
		}, 300, function() {
			$(this).children().children(".sSub").show();
		}).stop(true, true);
		$(this).children().children(".sSub").slideDown(300);
	},function(){
      	$(this).animate({
			top: '269px'
		}, 300, function() {
			$(this).children().children(".sSub").hide();
		}).stop(true, true);
		$(this).children().children(".sSub").slideUp(300);
    });
 
}); // END THE DOM
 
/*****************************************************************************
	dealing with the rotating images
*****************************************************************************/
function mainImageFlow()
{
	// set the opacity of image(s) to 0 (can't see them)
	$('#mainImageBox img').css({opacity: 0.0});
	// set the first image to be seen
	$('#mainImageBox img:first').css({opacity: 1.0});
	// set the function for 'mainImageGallery' to run every 3 seconds.
	setInterval('mainImageGallery()',3000);
}
function mainImageGallery()
{
	// if the images have no class (class='show') then show the first one anyway
	var current = ($('#mainImageBox img.show')?  $('#mainImageBox img.show') : $('#mainImageBox img:first'));
	//Get next image, if it reached the end of the slideshow, rotate it back to the first image
	var next = ((current.next().length) ? ((current.next().hasClass('sNav'))? $('#mainImageBox img:first') :current.next()) : $('#mainImageBox img:first'));
	//Set the fade in effect for the next image, show class has higher z-index
	next.css({opacity: 0.0})
	.addClass('show')
	.animate({opacity: 1.0}, 1000);
	//Hide the current image
	current.animate({opacity: 0.0}, 1000)
	.removeClass('show');
	$("#subNavBox").removeClass('show');
}

bg-rotate-slideup-nav-open
Check out the Demo

OR

Download the zip file

Update: Per your requests, here is an updated script and CSS code that gives your menu an animated scrolling effect. This code has also been cleaned up quite a bit from the previous version.

$(document).ready(function(){
	/*****************************************************************************
		dealing with the navigation
	*****************************************************************************/	
 
	$(".sSub").each(function(){
		var newWidth = $(this).width();
		$(this).prev().css("width",newWidth);
		//$(this).css("display","none");
		//alert( 300 - $(this).height() );
	});
	// Deal with Sub Nav
	$(".sNavWrap").hover(function(){
		// I Loath you IE fix
		if ($.browser.msie &amp;&amp; $.browser.version.substr(0,1)&lt;8){var minusPX = "33";}
		else{var minusPX = "32";}
 
		var newHeight = $(this).height() - minusPX +"px";
		//alert(newHeight);
		$(this).stop().animate({
			bottom: newHeight
		}, 'slow')
	}, function(){
      	$(this).stop().animate({
			bottom: '0'
		}, 'slow')
    });
 
}); // END THE DOM
 
/*****************************************************************************
	dealing with the rotating images
*****************************************************************************/
function mainImageFlow()
{
	// set the opacity of image(s) to 0 (can't see them)
	$('#mainImageBox img').css({opacity: 0.0});
	// set the first image to be seen
	$('#mainImageBox img:first').css({opacity: 1.0});
	// set the function for 'mainImageGallery' to run every 3 seconds.
	setInterval('mainImageGallery()',3000);
}
function mainImageGallery()
{
	// if the images have no class (class='show') then show the first one anyway
	var current = ($('#mainImageBox img.show')?  $('#mainImageBox img.show') : $('#mainImageBox img:first'));
	//Get next image, if it reached the end of the slideshow, rotate it back to the first image
	var next = ((current.next().length) ? ((current.next().hasClass('sNav'))? $('#mainImageBox img:first') :current.next()) : $('#mainImageBox img:first'));
	//Set the fade in effect for the next image, show class has higher z-index
	next.css({opacity: 0.0})
	.addClass('show')
	.animate({opacity: 1.0}, 1000);
	//Hide the current image
	current.animate({opacity: 0.0}, 1000)
	.removeClass('show');
	$("#subNavBox").removeClass('show');
}

And the modified CSS:

body{margin:0;padding:0;}
#mainImageBox{position:relative;height:300px;margin-top:20px;margin-bottom:20px;margin-left:20%; overflow: hidden;}
#mainImageBox img{float:left;position:absolute;margin:0;padding:0;border:1px solid #6a39b3;}
#mainImageBox img.show{z-index:100}
.snapShot{margin:0;padding:9px;left:0;position:absolute;top:0;z-index:0;}
#mainImageBox #subNavBox{position:absolute;z-index:200;bottom:0;left:0;width:650px; height: 30px;}
#mainImageBox #subNavBox .sNavWrap{float:left;position:relative;bottom: 0;background-color:#6a39b3;margin:0 0 0 20px;padding:0;font-size:12px;text-align:center;}
#mainImageBox #subNavBox .sNavWrap a{margin:0;padding:8px 10px;font-size:12px;font-family:Arial, Helvetica, sans-serif;color:#f9f9f9;text-decoration:none;text-align:center;display:block; text-transform:uppercase;font-weight:bold;}
#mainImageBox #subNavBox .sNavWrap .sSub{border-top:1px solid #ddd;margin:0;padding:0;}
#mainImageBox #subNavBox .sNavWrap .sSub a{display:block;margin:5px 0;padding:5px 0 8px 0;font-size:12px;font-family:Arial, Helvetica, sans-serif;color:#080808;text-decoration:none;text-align:center;display:block;text-transform:uppercase;font-weight:normal;}
.clear {clear: both;display: block;overflow: hidden;visibility: hidden;width: 0;height: 0;}.clearfix:after {clear: both;content:' ';display: block;font-size: 0;line-height: 0;visibility: hidden;width: 0;height: 0;}.clearfix {display: inline-block;}* html .clearfix {height: 1%;}.clearfix {display: block;}

Share this article

I think the more examples people post out there, the overwhelming some things might get. Google maps and the interaction between the code and the functionality behind it has for the most part, been something that some developers might might a little hard to deal with.

Well I am not trying to add to the confusion, but hopefully shed some light on this matter. I believe this example and straight to the point and pretty easy to understand.

Here we go.

What Does it do?

This example is pretty simple. It will render a map on a web page based on items that it sees in an XML file.

What Do I need?

You will need a couple of things.

1. First you are going to need a Google Map API Key.  Dont worry this is way less complicated than you might think, but remember that an API key is based on a domain.  So if you are testing everything on mysitedev.com  you will need a new API key when you launch live to mysite.com.

2. You will need to get lattitude and longitude coordinates for the location(s) you wish to plot. I do it using google maps itself, but maybe there is something easier out there than you can share?

google-map-example





code for actual map file

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Google Map Example</title>
<style>
*{margin:0;padding:0;}
body{background-color:#d9d9d9;text-align:center;}
.mapBox{width:640px;height:480px;display:block;}
</style>
<script type="text/javascript" src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=YOUR_API_KEY"></script>
<script type="text/javascript">
//<![CDATA[
function load(lat, lng){
	if (GBrowserIsCompatible())
	{
		var map = new GMap2(document.getElementById("map"));
		map.addControl(new GSmallMapControl());
		map.setCenter(new GLatLng(lat, lng), 6);
 
		function createMarker(point, name, address, index)
		{
			// Create a lettered icon for this point using our icon class
			var letter = String.fromCharCode("A".charCodeAt(0) + index);
			var icon = new GIcon(baseIcon);
			icon.image = "http://www.google.com/mapfiles/marker" + letter + ".png";
			var marker = new GMarker(point, icon);
			GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml("<p><strong>" + name + "</strong><p><p>" + address + "</p>");
		});
		return marker;
	}
	// Create a base icon for all of our markers that specifies the
	// shadow, icon dimensions, etc.
	var baseIcon = new GIcon();
	baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
	baseIcon.iconSize = new GSize(20, 34);
	baseIcon.shadowSize = new GSize(37, 34);
	baseIcon.iconAnchor = new GPoint(9, 34);
	baseIcon.infoWindowAnchor = new GPoint(9, 2);
	baseIcon.infoShadowAnchor = new GPoint(18, 25);
	// Grab actual information from the properties xml to use.     
	GDownloadUrl("properties.xml", function(data, responseCode)
	{
		var xml = GXml.parse(data);
		var markers = xml.documentElement.getElementsByTagName("marker");
		for (var i = 0; i < markers.length; i++) {
			var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")), parseFloat(markers[i].getAttribute("lng")));
			map.addOverlay(createMarker(point, markers[i].getAttribute("name"), markers[i].getAttribute("address"), i));
			}
	});
	}
}
//]]>
</script>
</head>
<body onload="load(28.551957,-81.419678)" onunload="GUnload()">
    <div id="map" class="mapBox"></div>
</body>
</html>

Please note that the line load(num,num) is the center of the map.

<body onload="load(28.551957,-81.419678)" onunload="GUnload()">


code for properties XML file.

<?xml version="1.0" encoding="utf-8"?>
<markers>
	<marker name="Walt Disney World Resort" address="7100 Municipal Drive Orlando, FL 32819" lng="-81.419678" lat="28.551957" />
	<marker name="Sea World Orlando" address="Orlando, FL 32821" lng="-81.458044" lat="28.420844" />
	<marker name="THAT Agency" address="120 S. Dixie Hwy WPB, FL 33401" lng="-80.049219" lat="26.725144" />
	<marker name="Art Deco Welcome Center" address="1200 Ocean Drive Miami Beach, FL 33139" lng="-80.125952" lat="25.795718" />
	<marker name="Daytona International Speedway" address="1801 W Internatl Speedway Blvd Daytona Beach, FL 32114" lng="-81.058674" lat="29.215856" />
</markers>

Click Here View a Working example using the code noted here

Later on we can look at how to create the properties.xml file dynamically using php as well as some other goodies. Stay Tuned.

Share this article

There are characteristics that every web developer has.  One of those things is the way a project is started. While some developers might use open source Content Management Systems / Blogging software like: WordPress, Joomla, Movable Type or any of the other systems out there, some developers chose to have a foundation to their projects.

Here at THAT Agency, we write alot of custom code for our clients, but I personally still like building off of my own foundation. Here is my breakdown.

Note that we usually build in PHP.

  • css/
  • inc/
  • js/
  • img/
  • template.php

Seems pretty simple right? well lets look inside the folders themselves.

css

This folder includes 2 files (which you can merge into 1, but i like the two files).  We have been really utilizing the 960 Grid System for our development standards, so the first css file (reset-960.css) is pretty much what you expect. It contains the condensed versions of reset as well as the 960 grid. I opted not to use the text.css file that is included in the 960 grid download but wrote my own (this you can change to your own).

The next file site.css contains some regular standard css elements:

/* important */
html{background-color:#F9F9F9;}
body{font-family:Arial, Helvetica, sans-serif;font-size:14px;line-height:1.3em;}
*{margin:0;padding:0;}
/* headers */
h1{font-family:Georgia, "Times New Roman", Times, serif;font-size:24px;font-weight:normal;}
h2{font-family:Georgia, "Times New Roman", Times, serif;font-size:22px;font-weight:normal;}
h3{font-family:Georgia, "Times New Roman", Times, serif;font-size:20px;font-weight:normal;}
h4{font-family:Georgia, "Times New Roman", Times, serif;font-size:18px;font-weight:normal;}
h5{font-family:Arial, Helvetica, sans-serif;font-size:16px;font-weight:bold;}
h6{font-family:Arial, Helvetica, sans-serif;font-size:14px;font-weight:bold;}
h1,h2,h3,h4,h5,h6{margin:10px 0;padding:0;display:block;clear:both;}
/* Text and links */
p{font-family:Arial, Helvetica, sans-serif;line-height:1.5em;margin:0 0 10px 0;padding:0;}
blockquote{font-style:italic;display:block;margin:20px 0;padding:10px;background-color:#fff;border-top:1px solid #ccc;border-bottom:1px solid #ccc;}
a,a:link,a:visited{color:#21759B;}
a:hover{color:orange;}
ul{margin:0 0 0 10px;}
ul li{margin:0 0 0 10px;padding:0;}
/* clear pieces */
.clear5{height:5px;}
.clear10{height:10px;}
.clear15{height:15px;}
.clear20{height:20px;}
.clear25{height:25px;}
.clear50{height:50px;}
.clear100{height:100px;}
/* Text Classes */
.textRight{text-align:right;}
.textLeft{text-align:left;}
.textCenter{text-align:center;}

inc

The inc(ludes) folder for starters contains 3 files:

header.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>DEVELOPMENT TEMPLATE</title>
<link rel="stylesheet" media="all" type="text/css" href="/css/reset-960.css" />
<link rel="stylesheet" media="all" type="text/css" href="/css/site.css" />
<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="/js/site.js"></script>
</head>

analytics.php
This file was created to house your analytics code for your website. I find it annoying to have to copy and past something as simple as that on every page of your website.

footer.php

</body>
</html>

Like the idea? Check it out for yourself and download the zip file. It contains 2 folders. 1 for HTML and the other PHP

Download the template-foundation zip

Share this article