Using CSS Grid to build a page layout with a sticky header and footer

Adri De La Cuadra by Adri De La Cuadra

Using CSS Grid to build a page layout with a sticky header and footer

Adri De La Cuadra A practical guide for using CSS grid for build a page layout, including a sticky header and footer, a panel with scrollable areas and a tabs module.

posted in Design on October 2, 2017 by Adri De La Cuadra

Iโ€™m super exited about CSS grid, because finally there will be a way to layout pages and achieve more interesting and dynamic results, without a ton of code! So since I fell in love with Atom IDE recently (I know, Iโ€™m late to the party, but really I like it ๐Ÿ˜บ), then itโ€™s no surprise that I will be using it for this example on using CSS grid for layout.

Diving into CSS Grid

CSS grid is so thrilling and has so much going on that I feel like a little kid in a candy store: I donโ€™t know where to even start and can get overwhelmed too quickly. So this article is going to be a warm-up exercise on using CSS grid in the most straightforward way, while building a semi-complex layout.

This is what the end result will be:

See the Pen Using CSS Grid to build a page layout (Atom IDE like) by adriana (@adrifolio) on CodePen.

Note that I will be using LESS, but will refer to it as CSS. Also there is some little jQuery in the codepen, bit this is only used to add and remove a CSS class.

 

And the steps that we'll follow:

  1. Define the Page Layout
  2. Define the Panel Module
  3. Define that Tabs Module
  4. Define the Editor Windows
  5. Define the Footer

Step 1: Define the Page Layout

The HTML structure of the editor will be very simple. There will be a wrapper called .page, and inside a .sidebar, an .editor and a .footer:

<div class="page">
  <div class="sidebar">...</div>
  <div class="editor">...</div>
  <div class="footer">...</div>
</div>

 

Then with CSS grid we can define how the structure should be laid out:

.page {
	display: grid;
	grid-template-rows: auto 30px;
	grid-template-columns: 300px 1fr;
	height: 100vh;
}

 

And ๐ŸŽ‰!

The layout of the page is set. Here's how that structure looks visually:

gridcss-atom-editor-structure

 

This is great and super straight forward. You basically say: โ€œhey, here is this grid, and I want it to have so many rows (in this case 2) and I want each want to be this wide: auto and 30pxโ€. If you want more rows, you can just keep adding more widths. The same thing goes for the columns. There are two set to 300px and 1fr.

Now, you may be wondering why 1fr instead of auto? (By the way: fr stands for โ€œfractionโ€. For more info about it, head to this post on CSS Tricks.) In this case 1fr works well because the .editor area will be split into multiple fractions, for the editor windows, which weโ€™ll cover in step 4.

Now, something else to note is that we want the footer to take the entire second row. To accomplish this we will apply more CSS grid magic:

.footer {
	grid-column-start: 1;
	grid-column-end:   3;
}

 

Here we are using grid-column-start to tell the grid,โ€œhey, I want this element .footer to start on the first columnโ€ and then we use grid-column-end to tell it: โ€œthis element should end on column 3โ€. This may seem a bit confusing because there are only two columns in our grid, but it basically means it should stop at the end of the 2nd column, which I guess is technically the beginning of the 3rd, right?

via GIPHY

 

So far your CSS should look like this:

/** Scafolding **/
.page {
	display: grid;
	grid-template-rows: auto 30px;
	grid-template-columns: 300px 1fr;
	height: 100vh;
}

/** Footer **/
.footer {
	grid-column-start: 1;
	grid-column-end:   3;
}

Step 2: Define the Panel Module

Looking at the contents of the .sidebar and the .editor I see a pattern (let's call it a .panel) that we can abstract so it can be used in both cases. Basically this .panel is a container with a fixed header and a body that takes the available space of the screen. This body also needs to be scrollable so the entire content can be accessed. With these requirements in mind, let's write the CSS.

First let's define a height for our โ€œbarsโ€. This height will be used to set the height of the footer and of the header of the panel: @bar-height: 30px.

Then, we define the .panel to be displayed as a grid and create two rows: one with the height of the panel header, and one as tall as the available space, which will be the panel body.

.panel {
	display: grid;
	grid-template-rows: @bar-height auto;
}

 

So far it's pretty straight forward. However, I discovered that the footer was pushed down below the fold if the content of the body in the panels took the available space in the screen:

grid-footer-2

 

I feel like CSS grid failed me here ๐Ÿ˜ž  as I was expecting the footer to stay docked to the bottom of the screen. Maybe I'm missing something? If you know what is going on here be sure to post in the comments! Anyway, this is how I coped with it: I used  calc  and subtracted the height of the footer from the height of the screen .

.panel {
	...
	height: calc(~"100vh -" @bar-height);
}

 

via GIPHY

 

Here's how this translates visually:

Screen Shot 2017-09-20 at 1.50.13 PM

 

And to top this with a ๐Ÿ’  let's make the panel body scrollable when needed.

.panel-body {
	overflow: auto; 
}

 

With this .panel solution we will be able to quickly build both the .sidebar and the .editor. Let's look at the CSS we have so far:

/** Scafolding **/
.page {
	display: grid;
	grid-template-rows: auto 30px;
	grid-template-columns: 300px 1fr;
	height: 100vh;
}

/** Panel Module **/
.panel {
	display: grid;
	grid-template-rows: @bar-height auto;
	height: calc(~"100vh -" @bar-height);
}
.panel-body {
	overflow: auto;
}

/** Footer **/
.footer {
	grid-column-start: 1;
	grid-column-end:   3;
}

Step 3: Define the Tabs Module

Another pattern that I thought could use CSS grid is the tabs in the editor because they are a grid of boxes in a single row, so the CSS is pretty simple:

.tabs {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	height: 100%;
}

 

Here we are telling the grid that we want to โ€œrepeatโ€ 3 columns, each one as wide as 1 fraction. But you could also give the tabs a fixed width for a more standard look. I can't think of a simpler way to define a UI for tabs!

layout-grid-tabs.png
 
Then we can add CSS ellipsis to the .tab-item to account for very narrow tabs and prevent the text from overflowing. Since we will use ellipses as well in the footer, we will go ahead and make it a separate class that we can use as a โ€œmixinโ€:
 
.ellipsis {
    overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.tab-item {
	.ellipsis;
	text-align: center;
    padding: 6px;
}

 

At this point your CSS should look like this:

/** Variables & Mixins **/
@bar-height: 30px;

.ellipsis {
    overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/** Scafolding **/
.page {
	display: grid;
	grid-template-rows: auto 30px;
	grid-template-columns: 300px 1fr;
	height: 100vh;
}

/** Panel Module **/
.panel {
	display: grid;
	grid-template-rows: @bar-height auto;
	height: calc(~"100vh -" @bar-height);
}
.panel-body {
	overflow: auto;
}

/** Tabs Module **/
.tabs {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	height: 100%;
}
.tab-item {
	.ellipsis;
	text-align: center;
    padding: 6px;
}

/** Footer **/
.footer {
	grid-column-start: 1;
	grid-column-end:   3;
}

 

Step 4: Define the Editor Windows

A neat thing about using CSS grid for the layout of the editor is that with one line of CSS the layout can be changed to accommodate multiple windows.

layout-windows.gif

 

To accomplish this we set the .editor to display as a grid, and then apply the additional CSS class .editor--2-windows-layout  when clicking on the button. This class will set the grid to display to two columns, each one taking 1 frame of the screen:

.editor {
	display: grid;
  	.window-2  {
    	display: none;
  	}
	&.editor--2-windows-layout {
		grid-template-columns: 1fr 1fr;
		.window-2 { 
    		display: grid;
  		}
	}
}

 

I said one line of CSS, and there are more lines here ๐Ÿ˜ , hehe! But, really the one line that you want to pay attention to is .grid-template-columns: 1fr 1fr; which is the one changing the layout so we can fit two windows in the editor without having to do any CSS acrobatics!

via GIPHY

 

Here's a recap of what we have done so far:

/** Variables & Mixins **/
.ellipsis {
  overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/** Scafolding **/
.page {
	display: grid;
	grid-template-rows: auto 30px;
	grid-template-columns: 300px 1fr;
	height: 100vh;
}

/** Panel Module **/
.panel {
	display: grid;
	grid-template-rows: @bar-height auto;
	height: calc(~"100vh -" @bar-height);
}
.panel-body {
	overflow: auto;
}

/** Tabs Module **/
.tabs {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	height: 100%;
}
.tab-item {
	.ellipsis;
	text-align: center;
    padding: 6px;
}

/** Editor **/
.editor {
	display: grid;
  	.window-2  {
    	display: none;
  	}
	&.editor--2-windows-layout {
		grid-template-columns: 1fr 1fr;
		.window-2 { 
    		display: grid;
  		}
	}
}

/** Footer **/
.footer {
	grid-column-start: 1;
	grid-column-end:   3;
}

Step 5: Define the Footer

We will do one last application of CSS grid in this layout for the footer. The footer has two areas. The first one shows the source of the file (let's call it footer-file-info) and the second one aligns to the left to display a series of controls (let's call this one footer-controls). When the editor is scaled, the controls on the right should maintain their position and the content on the left should flex to accommodate that:

grid-footer

 

To accomplish that, all we need to do is set the columns of the footer grid as follows:

.footer {
    display: grid;
    grid-template-columns: 1fr auto;
	...
}
Screen Shot 2017-09-20 at 2.48.59 PM

 

This will make the footer-controls as wide as its content, so more controls can be added without having to change the width. 1fr then allows the footer-file-info to flex. By default, the content of this area will wrap, so you can add CSS ellipsis class that we created earlier for the tabs module to cope with that:

.footer-file-info {
    .ellipsis;
}

 Lastly we will use flexbox to layout the .footer-controls:

.footer-controls {
	display: flex;
	height: 100%;
 	justify-content: flex-end;
 	a {
		height: 100%;
		display: flex;
		align-items: center;
    }
}

 

Here's the CSS end result for the layout:

/** Variables & Mixins **/
.ellipsis {
  overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/** Scafolding **/
.page {
	display: grid;
	grid-template-rows: auto 30px;
	grid-template-columns: 300px 1fr;
	height: 100vh;
}

/** Panel Module **/
.panel {
	display: grid;
	grid-template-rows: @bar-height auto;
	height: calc(~"100vh -" @bar-height);
}
.panel-body {
	overflow: auto;
}

/** Tabs Module **/
.tabs {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	height: 100%;
}
.tab-item {
	.ellipsis;
	text-align: center;
    padding: 6px;
}

/** Editor **/
.editor {
	display: grid;
  	.window-2  {
    	display: none;
  	}
	&.editor--2-windows-layout {
		grid-template-columns: 1fr 1fr;
		.window-2 { 
    		display: grid;
  		}
	}
}

/** Footer **/
.footer {
	display: grid;
    grid-template-columns: 1fr auto;
	grid-column-start: 1;
	grid-column-end:   3;
}
.footer-file-info {
  .ellipsis;
}
.footer-controls {
	display: flex;
	height: 100%;
 	justify-content: flex-end;
 	a {
		height: 100%;
		display: flex;
		align-items: center;
    }
}

 

And that's all there is to this CSS grid trickery ๐Ÿ˜€ ! What's left is just to style the theme of the editor using color, alignment, and spacing.

via GIPHY

 

So check out the codepen, clone it, slice it, dice it or come up with other themes and let me know what you think! I'm sure there's a ton that can be improved. Thanks for reading!

 

See the Pen Using CSS Grid to build a page layout (Atom IDE like) by adriana (@adrifolio) on CodePen.

 
Create better web applications. Weโ€™ll help. Letโ€™s work together.