Amending a design from fixed to proportional layout

Typically, for the foreseeable future, any design composite you receive or create will have fixed dimensions. Currently we measure (in pixels) the element sizes, margins, and so on within the graphics files from Photoshop, Fireworks, and so on. We then punch these dimensions directly into our CSS. The same goes for text sizes. We click on a text element in our image editor of choice, note the font size, and then enter it (again, often measured in pixels) into the relevant CSS rule. So how do we convert our fixed dimensions into proportional ones?

A formula to remember

It's possible I'm coming off too much of an Ethan Marcotte fan boy, but at this point it's essential that I provide another large tip of the hat (it should probably be a bow, maybe even a kneel) to him. In Dan Cederholm's excellent book, Handcrafted CSS, Mr. Marcotte contributed a chapter covering fluid grids. In it, he provided a simple and consistent formula for converting fixed width pixels into proportional percentages:

target ÷ context = result

Smells a bit like an equation to you? Fear not, when creating a responsive design, this formula soon becomes your new best friend. Rather than talk any more theory, let's put the formula to work converting the current fixed dimension for the And the winner isn't... site to a fluid percentage based layout.

If you remember, back in Chapter 2, Media Queries: Supporting Differing Viewports, we established that the basic markup structure of our site looked like this:

<div id="wrapper">
  <!-- the header and navigation -->
  <div id="header"> 
    <div id="navigation"> 
      <ul>
        <li><a href="#">navigation1</a></li>
        <li><a href="#">navigation2</a></li>
      </ul>
    </div>   
  </div> 
  <!-- the sidebar -->
  <div id="sidebar">
    <p>here is the sidebar</p>
  </div>
  <!-- the content -->
  <div id="content"> 
    <p>here is the content</p>  
  </div> 
  <!-- the footer -->
  <div id="footer"> 
    <p>Here is the footer</p>
  </div> 
</div> 

Content was later added but what's important to note here is the CSS we are currently using to set the widths of the main structural (header, navigation, sidebar, content, and footer) elements. Note, I've omitted many of the styling rules so we can concentrate on structure:

#wrapper {
  margin-right: auto;
  margin-left: auto;
  width: 960px;
}

#header {
  margin-right: 10px;
  margin-left: 10px;
  width: 940px;
}

#navigation { 
  padding-bottom: 25px; 
  margin-top: 26px; 
  margin-left: -10px; 
  padding-right: 10px; 
  padding-left: 10px; 
  width: 940px;  
}

#navigation ul li { 
  display: inline-block; 
}

#content {
  margin-top: 58px;
  margin-right: 10px;
  float: right;
  width: 698px;
}

#sidebar {
  border-right-color: #e8e8e8;
  border-right-style: solid;
  border-right-width: 2px;
  margin-top: 58px;padding-right: 10px;
  margin-right: 10px;
  margin-left: 10px;
  float: left;
  width: 220px;
}
#footer {
  float: left;
  margin-top: 20px;
  margin-right: 10px;
  margin-left: 10px;
  clear: both;
  width: 940px;
}

All the values are currently set using pixels. Let's work from the outermost element and change them to proportional percentages using the target ÷ context = result formula.

All our content currently sits within a div with an ID of #wrapper. You can see by the CSS above that it's set with automatic margin and a width of 960 px. As the outermost div, how do we define what percentage of the viewport width it should be?

Setting a context for proportional elements

We need something to "hold" and become the context for all the proportional elements (content, sidebar, footer, and so on) we intend to contain within our design. We therefore need to set a proportional value for the width that the #wrapper should be in relation to the viewport size. For now, let's knock off a naught and roll with 96 percent and see what happens. Here's the amended rule for #wrapper:

#wrapper {
  margin-right: auto;
  margin-left: auto;
  width: 96%; /* Holding outermost DIV */
}

And here's how it looks in the browser window:

Setting a context for proportional elements

So far, so good! 96 percent actually works quite well here although we could have opted for 100 or 90 percents—whatever we felt and set the design within the viewport in the most aesthetically pleasing manner.

Now changing from fixed to proportional gets a little more complicated as we move inwards. Let's look at the header section first. Consider the formula again, target ÷ context = result. Our #header div (the target) sits within the #wrapper div (the context). Therefore, we take our #header (the target) width of 940 pixels, divide it by the width of the context (the #wrapper), which was 960 px and our result is .979166667. We can turn this into a percentage by moving the decimal place two digits to the right and we now have a percentage width for the header of 97.9166667. Let's add that to our CSS:

#header {
  margin-right: 10px;
  margin-left: 10px;
  width: 97.9166667%; /* 940 ÷ 960 */
}

And as both the #navigation and the #footer divs also have the same declared width, we can swap both of those pixel values to the same percentage-based rule.

Finally, before we take a peek in the browser, let's turn to the #content and #sidebar div's. As the context is still the same (960 px) we just need to divide our target size by that figure. Our #content is currently 698 px so divide that value by 960 and our answer is .727083333. Move the decimal place and we have a result of 72.7083333 percent—that's the width of the #content div in percentage terms. Our sidebar is currently 220 px but there's also a 2 px border to consider. I don't want the thickness of the right-hand border to expand or contract proportionately so that will stay at 2 px. Because of that I need to subtract some size from the width of the sidebar. So in the case of this sidebar, I have subtracted 2 px from the sidebar width and then performed the same calculation. I've divided the target (now, 218 px) by the context (960 px) and the answer is .227083333. Shift the decimal and we have a result of 22.7083333 percent for the sidebar. After amending all the pixel widths to percentages, the following is what the relevant CSS looks like:

#wrapper {
  margin-right: auto;
  margin-left: auto;
  width: 96%; /* Holding outermost DIV */
}

#header {
  margin-right: 10px;
  margin-left: 10px;
  width: 97.9166667%; /* 940 ÷ 960 */
}

#navigation { 
  padding-bottom: 25px; 
  margin-top: 26px; 
  margin-left: -10px; 
  padding-right: 10px; 
  padding-left: 10px; 
  width: 72.7083333%; /* 698 ÷ 960 */  
}

#navigation ul li { 
  display: inline-block; 
}

#content {
  margin-top: 58px;
  margin-right: 10px;
  float: right;
  width: 72.7083333%; /* 698 ÷ 960 */
}

#sidebar {
  border-right-color: #e8e8e8;
  border-right-style: solid;
  border-right-width: 2px;
  margin-top: 58px;
  margin-right: 10px;
  margin-left: 10px;
  float: left;
  width: 22.7083333%; /* 218 ÷ 960 */
}
#footer {
  float: left;
  margin-top: 20px;
  margin-right: 10px;
  margin-left: 10px;
  clear: both;
  width: 97.9166667%; /* 940 ÷ 960 */
}

The following screenshot shows what it looks like in Firefox with the viewport around 1000 px wide:

Setting a context for proportional elements

All good so far. Now, let's go ahead and replace all the 10 px instances used for padding and margin throughout with their proportional equivalent using the same target ÷ context = result formula. As all the 10 px widths have the same 960 px context, the width in percentage terms is 1.0416667 percent (10 ÷ 960).

Note

Can't we just round the numbers?

Some critics of responsive design techniques (for example, see http://tripleodeon.com/2010/10/not-a-mobile-web-merely-a-320px-wide-one/) argue that entering numbers such as .550724638 em into stylesheets is daft. You may wonder yourself, why aren't these simply rounded to something more sensible? The counter argument is that it's a more accurate answer to the question being asked. Providing a browser with the most accurate answer should make it more able to display that answer in the most accurate manner. As a related aside, if you stayed awake through more than a couple math classes I'm sure you've heard of the Golden Ratio (http://en.wikipedia.org/wiki/Golden_ratio)? The mathematical ratio, found and used throughout almost every discipline we know, is expressed as approximately 1:1.61803398874989 (if you want it to 10,000 decimal places, knock yourself out here http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/phi10000dps.txt). Not a neat number by any means but quite an important one. If the Golden Ratio can suffer such precise measurements, I'm inclined to believe our web designs can too.

Everything still looks fine at the same viewport size. However, the navigation area isn't behaving. If I bring the viewport size in, just a little, the links start to span two lines:

Setting a context for proportional elements

Furthermore, if I expand my viewport, the margin between the links doesn't increase proportionally. Let's take a look at the CSS associated with the navigation and try and figure out why:

#navigation { 
  padding-bottom: 25px; 
  margin-top: 26px; 
  margin-left: -1.0416667%; /* 10 ÷ 960 */ 
  padding-right: 1.0416667%; /* 10 ÷ 960 */ 
  padding-left: 1.0416667%; /* 10 ÷ 960 */ 
  width: 97.9166667%; /* 940 ÷ 960 */ 
  background-repeat: repeat-x; 
  background-image: url(../img/atwiNavBg.png); 
  border-bottom-color: #bfbfbf; 
  border-bottom-style: double; border-bottom-width: 4px; 
}

#navigation ul li { display: inline-block; }

#navigation ul li a { 
  height: 42px; 
  line-height: 42px; 
  margin-right: 25px; 
  text-decoration: none; 
  text-transform: uppercase; 
  font-family: Arial, "Lucida Grande", Verdana, sans-serif; 
  font-size: 27px; color: black; 
}

Well, on first glance, looks like our third rule there, the #navigation ul li a, still has a pixel-based margin of 25 px. Let's go ahead and fix that with our trusty formula. As the #navigation div is based on 940 px our result should be 2.6595745 percent. So we'll change that rule to be as follows:

#navigation ul li a { 
  height: 42px; 
  line-height: 42px; 
  margin-right: 2.6595745%; /* 25 ÷ 940 */
  text-decoration: none; 
  text-transform: uppercase; 
  font-family: Arial, "Lucida Grande", Verdana, sans-serif; 
  font-size: 27px;
  color: black; 
}

That was easy enough! Let's just check all is OK in the browser…

Setting a context for proportional elements

Oh, wait, that isn't exactly what we were gunning for. OK, the links aren't spanning two lines but we don't have the correct proportional margin value, clearly. The navigation links look like one big word, and not one I can find in my dictionary…

It's always important to remember the context

Considering our formula again (target ÷ context = result), it's possible to understand why this issue is occurring. Our problem here is the context. Here's the relevant markup:

<div id="navigation"> 
  <ul>
    <li><a href="#">Why?</a></li>
    <li><a href="#">Synopsis</a></li>
    <li><a href="#">Stills/Photos</a></li>
    <li><a href="#">Videos/clips</a></li>
    <li><a href="#">Quotes</a></li>
    <li><a href="#">Quiz</a></li>
  </ul>
</div>

As you can see our <a href="#"> links sit within the <li> tags. They are the context for our proportional margin. Looking at the CSS for the <li> tags, we can see there are no width values set:

#navigation ul li { display: inline-block; }

As if often the case, it turns out that there are various ways of solving this problem. We could add an explicit width to the <li> tags but that would either have to be fixed-width pixels or a percentage of the containing element (the navigation div), neither of which allows any flexibility for the text that ultimately sits within them.

We could instead amend the CSS for the <li> tags, changing inline-block to be simply inline:

#navigation ul li { 
  display: inline;
}

Opting for display: inline; (which stops the <li> elements behaving like block level elements), also makes the navigation render horizontally in earlier versions of Internet Explorer (versions 6 and 7) that have problems with inline-block. However, I'm a fan of inline-block as it gives greater control over the margins and padding for modern browsers so instead I'm going to leave the <li> tags as inline-blocks (and perhaps add an override style for IE 6 and IE 7, later) and instead move my percentage based margin rule from the <a> tag (which has no explicit context) to the containing <li> block instead. Here's what the amended rules now look like:

#navigation ul li { 
  display: inline-block;
  margin-right: 2.6595745%; /* 25 ÷ 940 */
}

#navigation ul li a { 
  height: 42px; 
  line-height: 42px; 
  text-decoration: none; 
  text-transform: uppercase; 
  font-family: Arial, "Lucida Grande", Verdana, sans-serif; 
  font-size: 27px; color: black; 
}

And the following screenshot shows how it looks in the browser with a 1200 px wide viewport:

It's always important to remember the context

So the navigation is getting there now, but I still have the problem of the navigation links spanning two lines as the viewport gets smaller, right until I get below 768 px wide when the media query we wrote in Chapter 2, Media Queries: Supporting Differing Viewports, then overrides the current navigation styles. Before we start fixing the navigation I'm going to switch all my typography sizes from fixed size pixels to the proportional unit, "ems". Once that's done we'll look at the other elephant in the room, getting our images to scale with the design.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.61.30