Box with round corners - 4 divs?

Hi all

I have this simple round cornered box, I have a div with a border to create the surrounding box and 4 divs inside to hold the 4 corners.

The corner images are placed in the corners but they seem to 1 px away from the corners so the lines don’t match up.

The box is a set dimension so I’m not sure if this the best way to do this.
Would it be better to have an image of the whole box that is a background image on the containing div, then arrange the text inside of it.

Here is a link to the problem and an image of how it should look. (I’m not worried about styling the text at the moment)

http://www.ttmt.org.uk/box/


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

	<title></title>
	<style type="text/css" media="screen">
	  *{
	    margin:0;
	    padding:0;
	  }
	 #box{
   	width:230px;
   	height:158px;
   	border:1px solid #d6d4d4;
   	position:relative;
   	margin:20px;
   }

   #box #tl, #box #tr, 
   #box #bl, #box #br{
   	position:absolute;
   	width:10px;
   	height:10px;
   }
   #box #tl{
   	background:url(tl.gif) 0 0 no-repeat;
   	top:2;
   	left:2;
   }
   #box #tr{
   	background:url(tr.gif) 0 0 no-repeat;
   	top:0;
   	right:0;
   }
   #box #bl{
   	background:url(bl.gif) 0 0 no-repeat;
   	bottom:0;
   	left:0;
   }
   #box #br{
   	background:url(br.gif) 0 0 no-repeat;
   	bottom:0;
   	right:0;
   }
   #box h2, #box p{
     padding:10px 0 0 10px;
   }
   
   #box h2{
   	color:#3a8f99;
   	text-transform:uppercase;
   	font-weight:bold;
   	font-size:120&#37;;
   	padding-bottom:15px;
   	background:url(fade.jpg) 0 0 repeat-x;
   }
   
   #box a{
     float:right;
     margin-right:10px;
     text-transform:uppercase;
   }
   #ex{
     position:absolute;
     bottom:0;
     left:20px;
   }
   #ex h2{
     padding-bottom:20px;
     color:dimgray;
   }
	</style>
</head>
  
<body>  
  <div id="box">
      <div id="tl"></div>
      <div id="tr"></div>
      <h2>Instructors Needed</h2>
      <p>Looking for a new Career ?</p>
      <p>Become an Approved Driving Instructor</p>
      <a href="">More Info</a>
      <div id="bl"></div>
      <div id="br"></div>
  </div><!-- #box -->   
  <div id="ex">
    <h2>How I wanted it to look</h2>
    <img src="box.jpg" />
    
  </div><!-- #ex -->       
</body>
</html>


While the advice so far kind-of works, there are a multitude of issues I’d be trying to address.

First, the fixed height on #box is pretty much guaranteed to break on large font/120dpi systems, and even if you changed all the fonts inside it to px metric (an accessibility /FAIL/) all it takes is a different renderer or a wider fallback font to push that ‘more’ link right out of the box… just as it’s pushed out of the box on my machine here by about 30px as well as the bottom of the last P… So, lose the fixed height.

Next, it’s using five separate images to do what one image could handle quite easily.

Third, the borders are STILL depth-sorting over the images in IE6 on win mobile, and you are unlikely to fix that.

Fourth, your comment placement is risky – since that could trip IE rendering bugs like “double render” or “dissapearing content” – so I’d move those BEFORE the div being closed instead of after.

Finally, you’ve gotten REALLY complicated with positioning given that you don’t need transparency on any of this… Can be done a LOT simpler than you’re thinking.

To address all this I would suck it up and add one more div, and lose trying to do use CSS’ border property… at the very least for top and bottom… I would also NEST the top and bottom div’s so you need less classes and can just target the second ones (right side) off the parent.

That would change the markup to this:


	<div class="box">
		<div class="borderTop"><div></div></div>
		<div class="borderSides">

			<h2>Instructors Needed</h2>
			<p>Looking for a new Career ?</p>
			<p><strong>Become an Approved Driving Instructor</strong></p>
			<a href="#">More Info</a>

		<!-- .borderSides --></div>
		<div class="borderBottom"><div></div></div>
	<!-- .box --></div>

To make it work, I use my take on sliding doors, which means you need a new image.

I also used tweakpng to strip the GAMA line off that png so no IE color matching issues

Which despite it’s rather hefty dimensions (1280x54@48 color is smaller than your separate images combined. This allows you to use this exact same code for any box up to 1280 wide.

On the CSS side, with ‘box’ I’d just set the width and margin, and NOT the height since you want it to grow… if you don’t want it’s height to dynamically adjust to the height of it’s content, there’s probably something fundamentally flawed with the desired layout (the so called “But I can do it in Photoshop” syndrome)

.box{
	width:230px;
	margin:20px;
	color:#666;
}

.borderTop and .borderBottom both share a lot of behaviors - rather than dick with absolute positioning, we can just nest them and set a margin on one side of it’s child. IE has a bug where it won’t let you set a height on a element smaller than font-size – setting a 1px font size takes care of that… and of course the background image which we’ll show bottom-left revealing that rounded corner. We don’t need to declare the height here since they can pull it off their child elements.


.borderTop,
.borderBottom {
	font-size:1px; /* prevent IE height bug */
	background:url(images/borders.png) bottom left no-repeat;
}

Because our gradient is now in that master image, we want to pull the content up over .borderTop. This is easily done with a negative margin. We also want top to show the top left, not the bottom left.


.borderTop {
	margin-bottom:-34px;
	background-position:top left;
}

As with the parents, the nested DIV’s share a number of like properties. They both margin-left:10px, and both share the same background image. I set the height to 10px since we only need to override that for the top one - no sense declaring bottom separately when we don’t have to.

.borderTop div,
.borderBottom div {
	float:right;
	height:10px;
	background:url(images/borders.png) bottom right no-repeat;
}

and much like the parent, we change the values for borderTop. CSS 101 – it’s easier to target everything at once then change the couple minor differences than it is to target every single element individually.


.borderTop div {
	height:44px;
	background-position:top right;
}

Which you can see, we just make the top one taller and slide the background over to reveal the proper corner.

That’s it for the corners, now to just add the sides. Since you are just using 1px sides, rather than use a image we will use border, but just on the sides. Top/bottom borders make it too much of a complicated mess for it’s own good, and just side borders is ‘good enough’ for people browsing with CSS enabled but images disabled.

Big thing I do to the sides is give it float wrapping behavior because of your floated anchor.


.borderSides {
	overflow:hidden; /* wrap floats */
	height:1&#37;; /* trip haslayout, wrap floats IE */
	border:solid #d6d4d4;
	border-width:0 1px;
}

Pretty much all there is to it. I uploaded a working copy to my server for you to look at, which I also added a min/max-width version to which lets you see that it can indeed go up to 1280 wide. You’ll also notice I swapped it all to classes instead of ID’s. Usually when I have styling like that I prefer to be able to use it more than once on a page for consistency, and ID’s don’t do that.

http://www.cutcodedown.com/for_others/ttmt/template.html

as with all my examples the directory:

http://www.cutcodedown.com/for_others/ttmt

is unlocked for easy access to the bits and pieces. Valid XHTML 1.0 Strict, would be valid CSS if not for the expression to support min/max-width in IE, tested IE 5.5, 6, 7 & 8, Opera 10.6, FF 2, 3.5 and 3.6, and the latest flavors each of Safari and Chrome.

Sure, it adds two div, but in the process removes four file handshakes, cuts the total file sizes for images in half, and opens it up to dynamic width and variable height content… and has none of the “1px jog” IE issues. Doesn’t use absolute positioning OR floats to pull it off either - which in my book is always a good thing.

Thanks for that Paul O’B, ralph.m

You want to put the images on top of the border therefore you have to offset everything by -1px because the starting point 0,0 is inside the border to start with.

e.g.


#box #tl, #box #tr, #box #bl, #box #br {
    position:absolute;
    width:10px;
    height:10px;
    overflow:hidden;
}
#box #tl {
    background:url(http://www.ttmt.org.uk/box/tl.gif) 0 0 no-repeat;
    top:-1px;
    left:-1px;
}
#box #tr {
    background:url(http://www.ttmt.org.uk/box/tr.gif) 0 0 no-repeat;
    top:-1px;
    right:-1px;
}
#box #bl {
    background:url(http://www.ttmt.org.uk/box/bl.gif) 0 0 no-repeat;
    bottom:-1px;
    left:-1px;
}
#box #br {
    background:url(http://www.ttmt.org.uk/box/br.gif) 0 0 no-repeat;
    bottom:-1px;
    right:-1px;
}


As Ralph said odd widths and odd heights will be 1px out in IE6.

ralph.m

Thanks for the reply but that doesn’t really help me - the containing div has an even width (230), height(158) and I haven’t tested in IE yet, the problem is in Safari and Firefox

Have a look at this post from a few days ago. Post #10 mentions the 1px problem in IE6: