Well, this is the story of a guy who knows pretty much nothing of CSS, and his findings about it during a weekend. The story doesn’t end like “and the guy found the zen of CSS and he made great CSS for the rest of his life”, because everytime the guy touches CSS, ends angry with CSS, browser makers, Micro$oft, and a bloke called Murphy.
You might have noticed that I use Vistered Little in my blog. It comes with various styles and skins. One is narrow, another is wide (the one you’re seeing now), and a third called flex, which adapts the width of the main boxes to the browser window, leaving the menus floating gracefully. Unfortunately, flex doesn’t work with IE6. Windows XP SP2 comes with IE6, and currently I believe it’s the most used browser in the world (unfortunately too). That means that a page must work with IE6, at least. More on that later.
So, I had to use the wide style, which isn’t bad either. After some days playing with the site, I moved onto other things, like designing a style for the rest of my domain (everything else besides Pi in the Sky. I created a not very original but IMHO very nice symbol, a couple of banners and buttons, and I wanted to make a cool graphic frame. I tried to look at flex, but it had two disadvantages: it didn’t actually work with IE6, and it doesn’t have vertical side borders (maybe a limitation in the design?)
Then I searched for my cool graphic frame. It had to meet a few requirements:
- Work with all major browsers, including IE6.
- Uses CSS, not tables, in a clean way, which validates.
- Have a graphic element for each side and corner, totalling eight elements.
- Graphic elements shouldn’t overlap, so they can be transparent and have, for example, rounded corners.
- The frame should adapt its width to the width of the container, be it the browser window or another container.
- The frame should adapt height to the content of the frame.
After hours of searching (and I don’t consider myself a bad searcher), I had to give up. There are dozens, if not thousands, of CSS frames out there. Some people have come up with really smart and elegant solutions for some of these points. CSS tricks which really showed me the power and flexibility of CSS. But in one way or the other, all solutions I found failed the requirements in a way that made them unsuitable for me. Some were really close, but none made me happy.
Since I know pretty much nothing of CSS, I thought of asking someone to do the CSS for me, but actually I’m not very up to asking for help to anyone right now…
Instead, I started from scratch, thinking that at least I could try. I was having a hard time with my illness and writing a few lines of CSS was something I could do. So I designed the graphic elements of the frame, and prepared myself to distribute them with CSS.
Looking and customizing Vistered Little taught me a bit about CSS and divs. What I wanted was, apparently, nine divs, four for the corners, four for the sides, and a center one where the actual content is. In the graphic just next to this paragraph, you can see this structure. The blue squares would contain the rounded corners. The green sides will tile the corresponding border. The pink box will have the content. Nine divs not overlapping, didn’t seem hard.
Well, it was hard. It was easy at the beginning, floating divs left and right for the corners, leaving the center one with auto width, and bingo, there it was a frame which adapted to the width of the container. The top and bottom parts were easy. Not so much the center parts. While the center div would adapt to the width of the window, and height of the content, the side divs wouldn’t show anything. They didn’t have height. I tried many ways and combinations of enclosing divs one inside the other, to no avail. I found a way to make equal height divs, but the trick didn’t work in IE6 at all. I wasted one friday afternoon with this, without results.
Next day, I was in bed not feeling very well, when I imagined a solution. The problem was that the middle of the frame was made of two floating div sides and a center div, and the side divs have no way to know the height of the center div. Well, then let’s get rid of the floating divs! What I did was making a middle div which spanned the whole width, and inside it, another div,moved to one side, which will have the content. This way, the content div’s height adapts to what it contains, and the middle div which contains this one will adapt too. Correctly placed border backgrounds tiled perfectly. Beautiful!
However, when it came to test under IE6, a little bug appeared. Well, I already saw this bug, but I was focusing with the other problem. If you examine the image at the right side, you will see that in the top part of the frame, there’s a small gap between the top-left corner, and the top-center div. I tried and tried to eliminate this gap, using hidden overflow, negative margins and paddings, absolute positions (which rarely work with IE6), and a lot of tricks; none worked. And that’s how I wasted a second afternoon.
I was starting to think that I didn’t find my 8-element CSS frame anywhere because, for some reason, it couldn’t be done. Next day, I was again feeling bad in bed, and I really wasn’t thinking about CSS and this frame. But somehow I realized that I could apply the same principle of the middle divs to the top and bottom ones. If floating divs give problems, get rid of them! I also realized that this would simplify the div usage, because the CSS I did used nine divs, and it was a bit cumbersome.
So when you do the same to the top and bottom divs, you end with only six sections, instead of the starting nine, or the eight I had (plus a ninth surrounding everything). Each of the blue corners would have the corner elements, while the green ones would have the right corner elements, with the top and bottom borders joined to them. I still had 8 graphic elements, but two of them where merged together.
Maybe you’d prefer to see graphically how the divs enclose one another. It could look a bit cumbersome, but IMHO it’s better than to stack div after div one next another, and allow IE6 bugs to show. There’s a div, the green one, which encloses everything. It has the top-left corner as non-repeating background. Inside it, the first div, the grey, has a left margin as wide as the top-left corner is, and its background is the top-right corner plus a wide tiling of the top center border. I made mine 2000px wide, should be enough for all browser windows for a few years. This background is positioned to the top-right corner, of course. The height of this frame is determined by the height of the top corners (which should be the same).
After that, there’s a middle div, the red one, which spans all the width. Its background is the left border, and tiles only vertically. Inside this div, the pink div is the actual box which will have the content. The pink div has a left margin so it doesn’t overlap the border. Its background is the right border, positioned at the top-right, and tiling vertically. Since this div has still transparent background, unless the graphic background is wide enough, it will not have background. Again, the graphic background was widened to 2000px.
Finally, the bottom part is similar to the top part. The blue div spans all the width, and has as background the bottom-left corner graphic, without tiling. This div contains the yellow div, which has a left margin like it’s counterpart at the top, and behaves accordingly. But, the background is the bottom-right corner.
And since one image is worth 1,792 words, here you have some sample graphics over the divs. You can see how the graphic elements are laid, one for each div. And the best is, the frame looks good in IE6!
And that’s how, more or less, my CSS adventure ended. Well, not exactly. I still refined the results a bit, finding a couple of bugs and quirks, and documenting a bit the whole. Then I made a couple of examples. One, with sample (ugly) graphics, showed a single graphic frame adapting to its window and contents. The other was supposedly a fine example of stacking these frames one next to the other, and even inside themselves.
This last part was a real headache. My first experiments with stacking divs and IE6 were not very successful. Although my frame was working nicely alone, it failed miserably when more were around. It had to nest (one frame inside another), it had to stack (one frame over another frame), and it had to column (one frame next to another). All this worked quickly under Firefox, but no go under IE6. I wanted to do something like the distribution you see right now: some side frames for menus, and some center frames with the space left. What flex from Vistered Little tried to achieve. Argh!
Well, in the end, and don’t ask me why or how, I succeeded. It was a matter of try after try, until the columns and stuff looked the same way in both browsers. I still don’t know why the code which looked good didn’t work, and the current code, which looks incomplete to achieve the effect, actually works.
Oh, I’ve not made the perfect and definitive frame, it actually has one bug, but I don’t know if it’s the frame’s fault, the html’s fault, or just that IE6 is more buggy than I can imagine. It happens that, when there’s something floating next to a liquid frame, the next div of it which doesn’t have anything floating will misalign a bit. Three pixels in the example picture… Oh well, maybe someone can fix that.
Then I made a final test: the version you’re going to see validates against XHTML 1.0 Strict and CSS on the W3C validators. It is important that a page works with IE6, since it’s the apparently most popular browser and pretty much what nowadays is considered the oldest acceptable. And I think I (almost) got it. But I also think that adhering to the standards, which will work for years, is more important. If you can do both, then you’re doing it the right way (and you’re damn lucky!) So what I made is a two-way liquid frame with transparent graphic elements in the borders, which meets all my requirements. And I’m damn proud of having made it!
Ok, enough talking. Here you have the results of my CSS div hell trip:
8 Element frame example (buggy).
8 Element frame CSS in case you’re curious.
6 Element frame example (sorry for the ugly graphics).
6 Element frame example with stacking, nesting, and column-ing (with a small small bug).
6 Element frame CSS, I tried to put useful comments.
The CSS, the example graphics, and the example HTML, zipped so you can download it and use it or whatever (11kb). Do what you want, the CSS is released to the public domain.
Tell me if all this is useful for you!
Más sobre el monitor »« Otra vez