Rubber (fluid grids)

Original author: Ethan Marcotte
  • Transfer

This year I was redesigning a website with lots of content . The design requirements were simple: the client asked to keep the existing company logo, improve print density and increase readability. So, at the very beginning of design development, I spent a considerable amount of time planning a well-structured grid for a library of information blocks.
Over the past few years, this way of thinking has become more common. Thanks to Mark Balton (Mark Boulton), Khoi Vinh (Khoi Vinh), and others, we see a renewed interest in printing the grid, and how to use it on the network. And frankly, the idea was a smash hit: millions of CSS frameworksflowered variety of complementing their tools , each designed to make grid-based design even more affordable for the average designer / coder. And why not? After a few minutes of thinking in the grid categories, the merits become apparent: designers get a rational, structured framework for building an information structure and users get well-structured, readable sites.
Meanwhile, our client put forward yet another, killer, requirement: the design should be stretched and resized along with the browser window. Usually it would make me noisy and embarrassed to rejoice. Rubber is an underestimated paradigm in web design. She givesdesign control in the hands of users and their web surfing habits. And its capabilities are absolutely not in line with the imagination of web designers.

Minimum screen resolution: a small innocent lie.

Instead of exploring the virtues of “rubber,” we rely on a petty, innocent lie: “minimum screen resolution.” These three words contain powerful magic, under the cover of which we create designs with a fixed width, one after the other, perhaps only increasing the width of the design every few years when it becomes safe. "Minimum screen resolution" allows a limited subset of users to see the site as intended by God and Photoshop. These users always browse sites with a full-screen browser window and a resolution of 1024x768, and never use, say, an OLPC laptop , or monitors older than four years of age. If the user does not meet the “minimum screen resolution” requirements, well, for them there is a scroll bar, right?
Of course, when I coded the site, I was not up to the luxury of writing harsh denunciatory speeches on the flaws of a fixed-width design. Instead, I was left alone with a sobering fact: while we were developing a sufficiently sophisticated grid to satisfy customer content requests, the client - and in addition to everything, users - wanted "rubber". Almost all of the grid-based designs that I can list had a fixed width, and I was left with a difficult question: how to make rubber?
As it turned out, this is just a matter of context.

Should I really be grateful to IE?

Faced with an insurmountable problem, I did what I do best: circumvented it. Temporarily putting aside the question “how” to make the grid behave like “rubber”, I did what I could: first, styles for the color and background, then determined the font.
You may already know about IE's well-documented font-resizing issue if the size is specified in pixels - or rather, resolutely refuses to do so. Set the font to 16 pixels in Georgia and no matter how the user tries to increase or decrease the size of the text, in IE it will remain at 16 pixels. IE7 and later allows the user to scale the entire page, but simply changing the font size, which is defined in pixels, in IE is still taboo. So, to give users more flexibility, we, the standard-thinking designers, prefer to completely dispense with pixels, and use relative units to determine the font size, be it keywords , percentages or my favorites, em .
If you have ever worked with relative units, such as em, you understand that the thing is context: in other words, the actual size of em is calculated relative to the font size of the parent element. For example, let's say we work with the following layout:

An example of a simple determination of the size of text using pixels.

Nothing funny: the paragraphs are defined as 16px Helvetica, the unsorted list is slightly reduced to 14px and h1 is increased to 24px Georgia. Sexually? Not?
And what’s doubly sexy is that one simple rule allows us to get it all at once :
  1. body {
  2.     font: normal 100% Helvetica, Arial, sans-serif;
  3. }

With a font size of 100%, the size of all elements on our page is determined relative to the default font size in the browser, which in most cases is 16px. Thanks to the browser-style table, h1 is big, bold, beautiful - but still Helvetica and too big. In order to solve the problem, it’s quite simple to remove Helvetica using font-family, but how to change the font size of the text to 24px? Or exactly reduce the font size of the list?
With em, this is easy. We take the target font-size value for each element and divide by the font size (font-size) of its container (this is its context). As a result, we get the desired font size (font-size) expressed in relative units (em). Or, in short:

target ÷ context = result

If we assume that the font size of the body tag is 16px by default, we can describe with this formula any font-size value we need. So, in order to get the required header size matching with our calculations, we divide the target value (24px) by the font size (font-size) of the container (16px): The

24 ÷ 16 = 1.5

header is 1.5 times the font size of the body, or 1.5em, and this we can add value to the stylesheet.
  1. h1 {
  2.     font-family: Georgia, serif;
  3.     font-size: 1.5em; / * 24px / 16px = 1.5em * /
  4. }

To convert the list size to em the equivalent of 14px, we can use the same formula. Assuming that the font size (font-size) is strictly 16px, we simply divide the target value by its context.

14 ÷ 16 = 0.875

And we get the value 0.875em, which, again, can be entered into CSS.
  1. ul {
  2.     font-size: 0.875em; / * 14px / 16px = 0.875em * /
  3. }

With these two rules , the example page looks much closer to the planned one and will be almost perfect after simple additions . And all this with the help of the formula target ÷ context = result.
So after several hours spent raking the dimensions, I realized that I was tripping over the answer. If we can consider the font size not as pixels, but as a proportion calculated relative to the container, then the same can be applied to other grid elements.

In the end-ends, this is not the "Golden Pixel"

As before, let's start with a clear, non-sexy simple layout:

Our basic layout

Of course, our “design” is rather modest. But simple styles are superimposed on a well-defined grid: more precisely, seven columns of 124px each, separated by 20px white space, and all together have a width of 988px. But let's forget about these nasty pixels. Proportions are our everything, right? Give me the rubber, baby!

Our basic layout with a grid over it.

To begin with, let's consider our layout as an arbitrary layout, fixed or stretched: before we start writing code, let's look at the design and define information blocks . Fortunately, there are not many of them.

We determine the information blocks.

At the highest level , we have a title at the top of the page, an information area that stretches over six columns and some context-sensitive information in the leftmost column. From this scheme, we can distinguish a markup skeleton that corresponds to our information set both in terms of structure and in terms of semantics:
  1. < div id = "page">
  2.     < h1 > The Ratio Revolution Will Not Be Televised h1>
  4.     < div class = "entry">
  5.         < h2 > Anyone else tired of Helvetica? h2>
  7.         < H3 class = "the info"> A < a the href = "#"> Blog a> Entry: h3>
  9.         < div class = "content">
  10.             < div class = "main">
  11.                 < p > Main content goes here. Lorem ipsum etc., etc. p>
  12.             div>
  14.             < div class = "meta">
  15.                 < p > Posted on etc., etc. p>
  16.             div>
  17.         div>
  18.     div>
  19. div>

And, applying some typography rules, we get a decent looking reference point . However, the container (#page) does not contain any restrictions, so our content will be formed in such a way as to correspond to the width of the browser window. Let's try to control the length of the lines:
  1. #page {
  2.     margin: 40px auto;
  3.     padding: 0 1em;
  4.     max-width: 61.75em; / * 988px / 16px = 61.75em * /
  5. }

We used margin and padding to limit and get whitespace.between the content and the borders of the window. But the last line of our rule uses a variation of our formula (for calculating font-size) to determine the maximum width of our design. Dividing the width of the layout (988px) by the base font size (16px), we can set the maximum size in em to determine the approximate pixel width of our layout, which will prevent the layout from expanding beyond the ideal 988px. But since we use em to determine the maximum size, the maximum width (max-width) will be scaled if the user increases the font size in the browser - a fashionable little trick that works even in older versions of IE, if you use a small CSS hack .
Now that our design is appropriately limited, let's work with each element of our design separately, starting with the page title. In the layout, it occupies five columns and four white space materials, with a total width of 700px. It is also separated from the left border of the page by one pair of column / white space material, which gives a cute indentation of 144px. And, if we were to work with a fixed-width design, our work would be fairly straightforward:
  1. h1 {
  2.     margin-left: 144px;
  3.     width: 700px;
  4. }

But, since we work with "rubber", fixed units are not quite suitable. And, since I was working with relative sizes, it dawned on me: each element of the grid - and the elements that are located on it - can be expressed as a proportion relative to their container . In other words, as in our task with changing the font size, we consider not only the element size we need, but also the ratio of this size to the size of the container. This will allow us to convert the pixel-based width of the elements to percentages and preserve the proportions of the grid even when changing its size.
In short, we will have "rubber".

Everything new - well forgotten old

So where to start then?

target ÷ context = result

That's right: back to our font size calculation formula. We can use the same proportion to convert the width of the column in pixels to certain percentages, flexible values. So we, starting from the target 700px, to get the size of the header in percent - but the header container is 988px;

Convert the value of the header size in pixels to percent.

As a result, we simply divide 700px (our target value) by 988 (its context (size of the header container)) like this:

700 ÷ 988 = 0.7085

And so: 0.7085 turns into 70.85%, the width that can be entered in the stylesheet:
  1. h1 {
  2.     width: 70.85%; / * 700px / 988px = 0.7085 * /
  3. }

Can you also indent 144px? I love leading questions:

144 ÷ 988 = 0.14575

And again, we take 0.14575, or 14.575%, and add margin-left for the heading to our stylesheet:
  1. h1 {
  2.     margin-left: 14.575%; / * 144px / 988px = 0.14575 * /
  3.     width: 70.85%; / * 700px / 988px = 0.7085 * /
  4. }

And voilà . By measuring the indentation of the header and the width relative to the container, we successfully translated the percentage of our grid in percent. The proportions of the header will always remain true, even if it is scaled to fit the size of the browser window.
We can apply an equally simple transformation to determine the relative sizes of a block containing the main content, it has a size of 844px and an indent on the left of 124px wide. That is:

844 ÷ 988 = 0.85425

And for the information column:

124 ÷ 988 = 0.12551

These two transformations give us the percentage values ​​that we can add to the stylesheet and make our layout even more flexible.
  1. .entry h2,
  2. .entry .content {
  3.     float: right;
  4.     width: 85.425%; / * 844px / 988px = 0.85425 * /
  5. }
  7. .entry .info {
  8.     float: left;
  9.     width: 12.551%; / * 124px / 988px = 0.12551 * /
  10. }

And so we are moving a step forward in obtaining "rubber" .

Change context

So far, we have positioned the main information blocks, but we did not touch their contents. Now the content elements of the blog occupy the entire width and are located one above the other. But we planned that the main content element occupies only five columns and additional information should be located in the rightmost column.
Attentive readers have noticed that the current width of the information container in the main block is the same as the width of the header (700px), and the shift is the same as the leftmost column, the styles for which we prepared earlier, (124px). So we continue to work with dimensions that have already been calculated, but we cannot use the same formulas: the context has changed.

Since we are working in a new container, we must use its width as context.

Whereas previously we calculated the percentage relative to the width of 988 px of the container #page, now we are working with the container .entry .content, which is much smaller. As a result, we need to change our context and use the width of .entry .content as a reference point. So, to determine the percentage-based width of the “main copy” element, we take its width (700px) and divide by the width of the parent container (844px)

700 ÷ 844 = 0.82938

And for our right column, 124 pixels wide, we can use the same reference point.

124 ÷ 844 = 0.14692

Now we can take the results of these calculations and embed them in CSS:
  1. .entry .main {
  2.     float: left;
  3.     width: 82.938%; / * 700px / 844px = 0.82938 * /
  4. }
  6. .entry .meta {
  7.     float: right;
  8.     width: 14.692%; / * 124px / 844px = 0.14692 * /
  9. }

Actually, the work is finished on this, the "rubber" is finished .


As can be assumed from the lack of hacks in CSS, I had almost no cross-browser issues. I highly recommend John Resig's article on sub-pixel issues in CSS . She explains how various browsers handle the percentage width and the mechanism by which sub-pixel measurements are matched.
As John explains in his article, if modern browsers work with four elements 25% wide in a 50px wide container, they cannot draw 12.5 pixels wide elements; instead, most browsers will round the column width to a larger or smaller integer to best match the markup. Internet Explorer, as always, simply rounds off to a larger whole, which breaks the markup.
If you work with fairly general indentation in your grid, this is not a problem. But if IE causes unwanted breaks in the markup by moving columns with a percentage width, a one-pixel reduction in the target width can help. So, if, for example, our left margin is too large for IE, you can change the calculation from:

124 ÷ 988 = 0.12551

to a smaller width of 123px:

123 ÷ 988 = 0.12449

Add a width of 12.449% to the IE-specific stylesheet and everything will be fine.

Grid for all occasions

All of the above, of course, is just the starting point: there are a myriad of problems that await the typesetter working with “rubber”, most of which arise when working with fixed-width content (Images, Flash, etc.) in the context of “rubber”. I experimented with possible solutions on my blog , but there are no perfect solutions yet.
And finally, I’m not saying that layout is simple, it doesn’t matter, fixed layout or “rubber”. But after examining what we have achieved over the past few years - abandoning tables, raising standards in our companies and the general professional field to the level of shrine, we are trying to achieve the best browser standardization and I would like for us to use some of our inventiveness to break the dependence on the “minimum screen resolution. " After all, our users' web surfing habits are not as predictable as we can guess. I hope the possibilities of “rubber” sparked your imagination, I will gladly look at your application of this technique. Just like our users.

additional literature

How can you

Also popular now: