Using Four-Sided Positioning In CSS (Cascading Style Sheets)

Posted August 22, 2011 at 9:41 AM by Ben Nadel

Tags: HTML / CSS

Typically, when it comes to positioning elements with CSS (Cascading Style Sheets), I am used to using two-sided positioning; that is, I define two of the four offsets on a given element. This is most often "top" and "left"; but, I make frequent use of the "bottom" and "right" offsets as well. Recently, however, as I was going through some of the code that Ryan Jeffords was working on, I noticed that some of his UI (User Interface) elements had four-sided positioning; that is, he defined all four offsets - top, right, bottom, and left - on a single element. To be honest, I didn't even know this was possible. But, upon some light testing, this approach appears to be quite well supported.

To see what I'm talking about, take a look at the following code. In it, we have two nested elements. The outer element has a "fixed" position relative to the page. The inner element has an "absolute" position relative to the outer element. Neither of these elements has any defined width or height; they simply rely on the four offsets to resize the boxes in a fluid manner.

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Four-Sided Positioning With CSS</title>
  •  
  • <style type="text/css">
  •  
  • div.fixed {
  • background-color: #E8E8E8 ;
  • border: 1px solid #CCCCCC ;
  • bottom: 20px ;
  • left: 20px ;
  • position: fixed ;
  • right: 20px ;
  • top: 75px ;
  • }
  •  
  • div.absolute {
  • background-color: #FFFFCC ;
  • border: 1px solid #FFCC00 ;
  • bottom: 50px ;
  • left: 50px ;
  • padding: 30px 30px 30px 30px ;
  • position: absolute ;
  • right: 50px ;
  • top: 50px ;
  • }
  •  
  • </style>
  • </head>
  • <body>
  •  
  • <h1>
  • Four-Sided Positioning With CSS
  • </h1>
  •  
  • <!-- This will be FIXED on the page. -->
  • <div class="fixed">
  •  
  • <!-- This will be ABSOLUTE to the Fixed div. -->
  • <div class="absolute">
  •  
  • CSS Positioning, For The Win!
  •  
  • </div>
  •  
  • </div>
  •  
  • </body>
  • </html>

As you can see, no width or height is being defined on any of the elements. And yet, when we render this page, we get the following output:


 
 
 

 
 HTML elements can be positioned with more than two offsets at one time; these use all four offsets to define layout. 
 
 
 

As you can see, each element is rendered exactly as we would hope it to be rendered! I tested this on Firefox, Chrome, Safari, and IE7-9. This worked across the board.

NOTE: IE7 and IE8 testing was done using IE9 on a Windows 7 machine when the IE browser was put into IE7/IE8 rendering mode. I am not sure how accurate that is; but, I assume they know what they are doing.

Furthermore, since no width was defined, neither the "border" nor the "padding" values have an additive affect on the final width of any of the elements. This is particularly exciting as it will make creating complex user interfaces much easier.

I don't know if this four-sided position approach is well known in CSS. Before looking at Ryan's code, I can't remember ever seeing it in action - I'm pretty sure it would have blown my mind at the time. If you weren't aware of it, I hope this post helps. I'm definitely gonna be making much more use of this four-offset position going forward. And, just in case it wasn't obvious, you can also make use of three-sided position as well.




Reader Comments

Aug 22, 2011 at 9:49 AM // reply »
24 Comments

Just like Flex. It's very nice, but you have to be careful about using padding for the container being position. It'll throw things off. User margins on inner children to push them away from the edges.


Aug 22, 2011 at 9:50 AM // reply »
9 Comments

I can't believe I never thought to try this before...


Aug 22, 2011 at 9:52 AM // reply »
11,238 Comments

@Andy,

Yeah, I've definitely seen it done in Flex. In all the demos and keynotes, they always have that cool little widget in the bottom-right where they lock down all the sides. I was always secretly jealous :) As far as the margins, though, I think it only becomes an issue if the inner element has a defined width... which, in all fairness, it probably will *most* of the time.

@Gary,

Right?! I just assumed this wasn't possible. It would be too easy ;)


Aug 22, 2011 at 10:15 AM // reply »
4 Comments

The padding sizing issue was always a pain in my rear. UNTIL I found out that you can specify a different box sizing model via CSS.

The standard box model uses padding when calculating the overall width. So, if you have a div with a css width of 100px and add 10px padding to each size, the REAL width will be 120px.

If you use the border-box box model for that same div. 100px wide + 10px padding on either side. The actual width will be 100px and the inside of the box will be padded by 10px on either side.

This was a huge breakthrough for me...

Here's a relevant link: http://www.quirksmode.org/css/box.html


Aug 22, 2011 at 10:32 AM // reply »
158 Comments

Ben,

Perfect timing. I knew (assumed) 4-sided was possible, as I had used left and right + top previously.

What I plan on using this for is in combination with MOD and a WinPhone 7/Win8 "look".

Thus the page would look something like this:

Home Search Link1
Link2 Link3 Link4
Link5 Link6 Link7

But maybe it would adjust if the browser was resized down to:

Home
Search
Link1
...

Or
Home Search
Link1 Link2
...


Aug 22, 2011 at 10:55 AM // reply »
2 Comments

IE6 and IE7 screenshots: http://gyazo.com/fad7909f9830dc5600cf92a87336faa2


Aug 22, 2011 at 10:59 AM // reply »
11,238 Comments

@Ben D,

Yeah, the box model can be funky stuff to think about. One of the ways I've started to deal with it is to have an outer container that handles the dimensions; and then, to have an inner buffer to handle the paddings and what not. Sometimes, I definitely miss the old IE-style box model.

@Randall,

It sounds like a "media query" might also help your stuff. I know nothing about media queries; but, I think they can help take screen dimensions into account by applying specific styles.

@Vladikoff,

Yeah, I didn't even test in IE6. In fact, IE9 doesn't even provide an IE6 option. Basically, not even Microsoft cares about IE6 any more :D


Aug 22, 2011 at 11:50 AM // reply »
158 Comments

Ah, yes, I appreciate the reminder.

http://www.w3.org/TR/css3-mediaqueries/

The short version:
<link rel="stylesheet" type="text/css" media="screen" href="sans-serif.css">
<link rel="stylesheet" type="text/css" media="print" href="serif.css">

Other media types (http://www.w3schools.com/CSS/css_mediatypes.asp):

all Used for all media type devices
** handheld Used for small or handheld devices
aural Used for speech and sound synthesizers
braille Used for braille tactile feedback devices
embossed Used for paged braille printers
print Used for printers
projection Used for projected presentations, like slides
screen Used for computer screens
tty Used for media using a fixed-pitch character grid, like teletypes and terminals
tv Used for television-type devices


Aug 22, 2011 at 12:05 PM // reply »
3 Comments

about ie6 support:

ie6 doesn't support

  • position:fixed

You can emulate it with

  • position:absolute; top:expression(js-goes-here)

but it's slow and bad practice overall ( like using ie6 )


Aug 22, 2011 at 12:23 PM // reply »
3 Comments

Indeed, this technique is very useful. I use it a lot for what I call "inner shadow". If I use box-shadow with the `inset` keyword, I have few control on opacity.

See http://jsfiddle.net/tbassetto/gyZhg/ => If you comment the line with the "four-sided positioning" and uncomment the one above (using with and height at 100%), the result is not what I expect :)


Aug 22, 2011 at 1:00 PM // reply »
270 Comments

@Ben,

I do this (top, right, bottom, left) too, but only in strict mode. You don't want to attempt it in IE quirks mode.

Unfortunately, that includes TRYING to use IE strict mode but someone putting an HTML element (even just an HTML comment) above the doctype. That's pretty easy to do in ColdFusion with shared look-and-feel cfincludes/customtag and a new employee not knowing how to use the routines properly.

But when it works, here's how it works: Suppose you've specified left and top. If you give width, right is calculated. If you give right, width is calculated. If you give height, bottom is calculated. If you give bottom, height is calculated.

I've also done it the other way around. Suppose you've specified right and bottom. If you give height, top is calculated. If you give top, height is calculated. If you give width, left is calculated. If you give left, width is calculated.

To sum up, to specify bounds on an absolutely positioned element, you need exactly two of left, right and width, and you need exactly two of top, bottom and height.


Aug 22, 2011 at 1:37 PM // reply »
9 Comments

Seems like an interesting technique, but I'm having trouble coming up with a good use-case for it. In the example given, the same result can be accomplished using margin instead.


Aug 22, 2011 at 5:58 PM // reply »
1 Comments

Ben,

Microsoft actually has a neat tool (I know, hard to believe) for their own browser testing that comes with their IE10 Platform Preview

http://ie.microsoft.com/testdrive/Info/Downloads/Default.html

You put the page in and choose the version you want to view it in from the 'Debug' menu.

Careful if using it with browser checking logic, as it will still make your application believe it's being viewed in IE 10.

What you find funny is you can view it in IE 5, but like you said, I think they have given up on IE 6 as it's not even an option =)


Aug 22, 2011 at 7:31 PM // reply »
270 Comments

@JGarrido,

Here's an excellent use case: a "C clamp" (different kinds of navigation on top, left and bottom, roughly forming the shape of a letter C), with a non-navigational content region that's dynamically expandable both to the right and down.

Or an "O clamp". You don't see too many good examples of O clamps. MapQuest doesn't do that anymore, ever since their navigational overload was featured so prominently as something never, ever to do in Nielsen's Designing Web Usability.

Or a box that you'd like to end at a fixed pixel distance from the right edge, rather than a percentage of the available width, which varies according to window size.


Bob
Aug 22, 2011 at 8:45 PM // reply »
3 Comments

Oh wow, what a great technique. This is definitely something I would've liked to know a long time ago.


Aug 23, 2011 at 12:48 PM // reply »
270 Comments

@JGarrido, P.S.:

In answer to your alternative suggestion of using margin, that doesn't work with absolutely positioned elements.

Specifically, if you specify top and left, but not right, bottom, height or width, an absolutely positioned block will be sized just like an inline-block. That is, it will have the minimum height and width necessary to accommodate its contents. Margin has no effect.

In order for a div to naturally expand to the width of its container, it has to be rendered "in the document flow". Absolute positioning takes a block out of the document flow. As far as its container is concerned, it's as if it didn't even exist. Absolutely positioned elements take up 0 pixels in the document flow.


Sep 4, 2011 at 5:02 PM // reply »
9 Comments

Not to denigrate your post, but I just remembered where I first saw this. http://www.alistapart.com/articles/conflictingabsolutepositions/ for what it's worth.

There's a workaround for getting IE <7 to work.


Sep 7, 2011 at 10:01 AM // reply »
4 Comments

Hmm, have been using this for a lot of personal projects (e.g. http://ngtunes.hosting.apriol.com [CHROME only for optimal display, it will start working in the future in other browser as well once HTML5 becomes more common]). But as far as the box model itself goes: http://www.css3.info/preview/box-sizing/


Sep 12, 2011 at 10:24 AM // reply »
11,238 Comments

@Stryju,

Yeah, I basically don't care about IE6 anymore... it's time to let go :) I'm think the fact that it's supported (fixed position) in IE7 is good enough for me. I am not typically building things that cater to such old systems.

@WebManWalking,

I'm not exactly sure what you're saying. When I'm using a 4-sided position, I am not setting height or width (thought I might for a parent container). It depends on the situation.

@JGarrido,

A cool use-case for it might be having a visual module. Then, someone performs an action and you show a "modal" over the module. Instead of having to calculate the dimensions of the module, you can just use 4-sided positioning to make sure the "modal" (which is really a hidden child of the module) covers it completely.

@Jim,

MS has actually been doing some good stuff for Dev lately, as far as testing goes. I'm pretty happy with it!

@Jon,

Good link, thanks! I had seen other ALA posts about positioning, but not that one in particular.

@David,

Good example of exactly the kind of stuff that this sort of position can make easier!



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 19, 2013 at 2:31 PM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
It's funny really just how well that image describes the way I would imagine most people that go with angular for some project is. I have had a similar roller-coaster ride with it as well, but not qu ... read »
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools