Side by Side Divs

illustration of hanging lamps

How many ways are there to place a sidebar alongside the main content of the page, when it appears after the content in the HTML? I’m presuming here that you want a responsive design where the sidebar drops below the content at small sizes. Here are some ways to position content in a horizontal line. Possibilities 2 through 7 are illustrated on a demo page.

While working on this post I found a similar post by Karen Menezes that goes into more detail on certain points.

1. HTML tables. But don’t use these for large-scale layout. Why not? They exist separately on every page, making changing them a larger job, and responsiveness requires quashing the table’s natural (i.e. HTML) state of being. AND there are CSS tables (see below) that do the same thing more cleanly.

2. Absolute positioning. Easy to make responsive in and of itself – just don’t apply it until the screen is wide enough – but essentially impossible to get to play nicely with any elements underneath, unless either A) you use JavaScript, or B) the height of your content and sidebar is fixed, which is hard to imagine happening in a responsive context (and certainly not if you’re using this layout for multiple pages, as with a CMS). In the demo, I have pushed the footer below the content at 1000px-wide screens, which you will see leads to a gap at wider screens.

3. CSS columns. This is something of a faux answer. I really like these for columns of small elements – the widgetized area of this theme uses them – but they require your side-by-side regions be equal width (if you set a width on a div within a columnized wrapper it will be relative to one column), and they may break your content over two columns. It is unlikely this is what you want in the content-sidebar setting. They are good to know about, though I’ve learned they still need browser prefixes.

Edit 2/23: Since this writing I’ve learned about break-inside: avoid;, which you can set on the elements inside the columns to prevent them from breaking across columns (see CSS-Tricks for cross-browser syntax). On the other hand, I’ve also learned that the lovely slider function Flickity doesn’t work in CSS columns.

4. Inline-block display. If you set display: inline-block; on appropriate-width divs they will sit next to each other. By default they will be bottom-aligned, so you’ll probably want vertical-align: top; on both the sidebar and content divs. Note that display: inline; won’t work because width doesn’t apply to inline elements. Caveat: whitespace in markup translates to whitespace onscreen, so if you lack sufficient control over the HTML to eliminate whitespace your elements won’t touch onscreen (and hence can’t have widths summing to 100%). You can try it in the demo: go to your developer tools, turn off the sidebar and main content borders, and add 2% to the width of one of the pieces (currently widths and padding sum to 98%). The sidebar will pop down below the content.

5. Floats. This is a classic solution: float the content left and the sidebar right (or both left; the effect is different when the width sum is less than 100% but the idea is the same). This works well for just the content-sidebar setup, as long as you have a wrapper div with overflow: hidden; set on it to push your footer down. It does not lend itself well to more complicated layouts where taking elements out of the usual document flow introduces the need for a lot of clearfixes and other extra markup to maintain the layout.

6. CSS tables. This is the rule display: table; set on the wrapper and display: table-cell; set on the contents (there is also display: table-row; which could be put on an intermediate wrapper, but isn’t strictly necessary if you have only one row). It will line things up cleanly and is easily styled and made responsive. Every cell in a row will be made the same height and aligned together, which can be either overly rigid or just what you want. I think it makes the front page of this site look neater, and used it elsewhere to easily make a sidebar border into a full-height dividing line between content and sidebar. Caveats: if one side of your content is pushed down, the other will be also, unless you set vertical-align: top; on it – I’ve even seen an embedded Youtube video at the top of one side being interpreted as simply pushing the content down, and the other side pushing itself down to match (though not in all browsers). Also, if you want space between the borders of neighboring cells without space around the outside of the table, you’ll have to set a negative margin on the table wrapper.

7. Flexbox. If you don’t mind having to have a separate backup layout for (older if not all versions of) IE, flexbox is another option. [This simple layout should work in 10 and 11; more complex layouts may have issues even with those.] It will also make the divs equal height by default, though I believe you can change that. The two items will have to be in whole-integer proportions, but it doesn’t have to be that one is a multiple of the other. In the demo I commented out the widths of the divs, set the content to flex: 7; and the sidebar to flex: 3; with the wrapper set to display: flexbox;. I haven’t worked much with flexbox but this use-case has wonderfully simple syntax. CSS-Tricks has an article on mixing generations of flexbox syntax for strongest-possible browser support. I simply threw the most modern code into Autoprefixer and took what it gave me.

In the beautiful future we may also have a template layout module that looks really, really terrific.

Leave a Reply

Your email address will not be published. Required fields are marked *