Chapter 1. Where We Came From

Sometimes, in front of rooms filled with developers who have never had to turn their hand to a font tag or a nested style sheet, I remark that my career on the web predates Cascading Style Sheets (CSS). As CSS celebrates its twentieth birthday, when I look back over my own history of learning and teaching CSS, I marvel at the fact that it has taken until 2017 to come close to cracking how to do layout on the web.

Before we start looking at the methods for creating layout on the web that have landed in the past few years, I want to revisit where we came from. Doing this historical groundwork is important, because many of today’s assumptions about layout stand on the shoulders of what has come before.

Hacking Around the Limitations

Early CSS layouts were a mixture of floats and positioned elements. A common pattern was to give the main content of the page a wide left or right margin, and then use absolute positioning to place the sidebar into that gap. This worked—until you wanted a footer on the layout and couldn’t be sure the positioned item would not be taller than the main content. A lot of websites attempted to fix the heights of elements to cope with this; it wasn’t unusual to discover a page with elements overflowing one another, especially if you adjusted the text size to make fonts larger than the designer expected.

Over time, we became better at layout. Online community-created resources like the Noodle Incident (http://bkaprt.com/ncl/01-01/) still exist, with examples of CSS layouts to copy and paste. These relics of our past remind me how far we’ve come in terms of the complexity of the designs we build—and yet how much we still lean on the techniques we developed back then.

As we became better at building floated layouts, we continued to be frustrated by the lack of full-height columns. Having floated a sidebar left and the main content right, there was no way to put a background color or image behind that sidebar. It would sit just under the content.

But web designers have always been incredibly resourceful at finding creative ways to use a limited toolset. A solution to the full-height column conundrum came when Dan Cederholm documented his “faux columns” technique on A List Apart (http://bkaprt.com/ncl/01-02/). By tiling an image behind the entire layout, we could create the effect of a full-height column.

That was just one of the many ways we learned to fake the appearance of layouts. The main debate—aside from a few outliers stubbornly insisting we should continue to use HTML tables for layout—revolved around whether we should build designs that had a fixed pixel width, or designs that stretched to fill the available screen space (sometimes referred to as liquid designs). Those of us who developed and taught these techniques got pretty adept at them, and knew how to identify most of the tricky browser bugs we had to work around.

Then came a curveball: the iPhone. As the web community discussed the best way to provide a separate mobile site, Ethan Marcotte set forth his ideas on responsive design (http://bkaprt.com/ncl/01-03/). A whole new challenge for CSS layout materialized.

By the time Marcotte detailed his responsive design ideas on A List Apart, many websites had already opted for a fixed-width approach. Larger screens meant that liquid websites stretched too wide, and reliance on methods such as faux columns made it very hard to create flexible grids. Responsive design threw everything up in the air again—not only did we need to create designs that used fluid percentage-based grids, but we had to do so for a multitude of screen sizes. The techniques we had developed fell apart, and we had to revisit how we used floats and other parts of CSS to make layout easier.

The Trouble with Floats

Floats have served as the main method for achieving multiple-column layouts since the early days of CSS. When you float an element, it will, as its name suggests, float up to the left or right as far as it can go. It stops when another element blocks it. Floats were initially designed to achieve a common design pattern where text wraps around an image or other element (Fig 1.1).

If you float two items, then, the second element will float up alongside the first, assuming the parent container is wide enough (Fig 1.2).

This is the behavior we’ve been using to create our multiple-column layouts with floats. If we precisely calculate the widths of our floats inside a container, we can float columns up alongside each other. This works quite nicely if all our content is the same height (Fig 1.3). The code looks like this:

.cards {
  margin: 0 -10px;
}
.cards li {
  float: left;
  width: calc(33.333333333% - 20px);
  margin: 0 10px 20px 10px;
}

Figure

Fig 1.1: A single floated element with wrapped text.

Code example: http://bkaprt.com/ncl/01-04/

Figure

Fig 1.2: Two floated elements.

Code example: http://bkaprt.com/ncl/01-05/

Figure

Fig 1.3: A tidy set of cards.

Code example: http://bkaprt.com/ncl/01-06/

As soon as we add some additional content to one of our blocks, though, we have a problem. The first three items, including the taller Card 2, lay out nicely. But Card 4 can no longer float past, creating some undesirable white space (Fig 1.4).

Figure

Fig 1.4: A messy set of cards.

Fixing the Float Problem

The pragmatic solution many layout frameworks propose is to put each row of the grid in a wrapper, with a clearfix applied. This contains the floats and prevents any inhabitants of the second row from hopping up into the first row’s space.

This works, but we then require additional markup to create our rows. An alternate solution is to use display: inline-block instead of floating the elements.

.cards li {
  display: inline-block;
  vertical-align: top;
  width: calc(33.333333333% - 20px);
  margin: 0 10px 20px 10px;
}

Code example: http://bkaprt.com/ncl/01-07/

Alas, this method comes with its own issues. If you set something to inline-block, it remains an inline element, but enables some additional block-like behavior. One aspect of being inline is that inline elements preserve white space; if they didn’t, every word in a sentence would run together, since the spaces between words would not be maintained. If we use the same method to calculate the size of the item widths as we did for floats, we find that we only get two items on each row. The additional white space means our cards now add up to more than 100%.

The solution is to completely remove white space between our cards—which works, but can make for a slightly fragile layout (Fig 1.5). If any white space gets into the document—perhaps due to a change in the CMS or just a forgetful web designer—we’ll end up with only two cards per line again.

Neither method enables the creation of a layout where the boxes take on equal height across the row. With our floated and our inline-block layouts, we can create neat rows with some compromises, but any background or border on items will only extend as far as the content does. This produces a ragged edge on our rows.

A legacy method for creating a multiple-column layout exists that can address this issue; it uses table layout on items that are not HTML tables.

display: table

Figure

Fig 1.5: The inline-block layout.

HTML tables have a related CSS specification—CSS Table Layout—that defines the properties and values available when styling this very specific type of structure. An HTML table has the CSS property display with a value of table. Inside an HTML table, we have tr elements (which have the display value of table-row in CSS) and td elements (which have the value table-cell). While these values were designed for styling HTML tables, they can be applied to things that are not, semantically speaking, tables—divs, lists, and so on.

To change the previous example to use Table Layout, we need to adjust both the CSS and the markup. I add a wrapper around the ul element and give it the display property with a value of table. This tells the browser that the contents of the wrapper will be laid out as if they were a table. Turning the ul element into a row causes the list items to lay out in one row. Therefore, I need to split the list into two lists and set the value of display on a ul element to table-row. The list items become table cells using the value table-cell.

.wrapper{
  display: table;
  border-spacing: 20px;
  margin: -20px;
}
.cards {
  display: table-row;
}
.cards li {
  display: table-cell; 
  vertical-align: center;  
}

Code example: http://bkaprt.com/ncl/01-08/

Note that margins on our table cells and rows do not apply. To space out the cells, use the border-spacing property on the element that is set to display: table.

Because our items are now table cells, the background color stretches down to the same height for each cell, rather than sitting up behind the content (Fig 1.6). You can also use the vertical-align property to control the alignment of the content inside each cell—just as you can with an HTML table.

In our example, we have added elements for each part of the table, just as if it were an HTML table, giving an element display: table, a direct child of that element display: table-row, and ending with our individual list items having display: table-cell. In reality, you can often simply apply display: table-cell to an item and the browser will create anonymous elements to provide the other wrappers. We’ll look at these anonymous elements in more detail in Chapter 7.

Table Layout works this way because items in a table have a relationship. This concept of creating relationships between items in the layout is important in our newer layout methods, and we will return to it later in this book.

Figure

Fig 1.6: The layout using display-table.

The techniques demonstrated in this chapter are our stock-in-trade as front-end developers. You will need to know these techniques for some time to come in order to deal with older browsers. Yet they are all essentially hacks that merely enable layout—not a designed-for-the-job layout system.

And that’s why CSS layout seems hard and fragile—we don’t have any layout tools! The fact that we’ve been coping with this situation for so long has led the community to create its own tools to ease the pain of layout. As we’ll see in the next chapter, these tools have redefined what it means to be a front-end developer in 2017.

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

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