Ionic Layout Header

How to Create Complex Layouts in Ionic



·

Before switching to Ionic, I used Sencha Touch which has a completely different layout system. Layouts in Sencha Touch are built almost completely with Javascript, and I’ve previously written about how to create complex layouts in Sencha Touch.

Ionics layout system looks like something you would expect from a typical grid based CSS framework like Bootstrap or Foundation – but it’s not quite as complex. Unlike Sencha Touch, you will use HTML and CSS to build layouts in Ionic which might look something like this:


<div class = "row">

<div class = "col-20"></div>


<div class = "col-25"></div>


<div class = "col-20 col-offset-10"></div>

</div>

Each new row is added vertically and each column divides the row horizontally. Columns come with a range of available percentage based widths in the form of col- and you can also simply just specify col to space them evenly. The col-offset- classes allow you to offset where the column is placed, for example:

col-20 col-offset-10

Would create a column 20% wide and it would give it a margin to the left of 10%. Here’s a list of available classes for columns, each of these can also be used as offsets:

Class Width
col-10 10%
col-20 20%
col-25 25%
col-33 33.3333%
col-34 33.3333%
col-50 50%
col-66 66.6666%
col-67 66.6666%
col-75 75%
col-80 80%
col-90 90%

The post I linked above about creating a complex layout in Sencha Touch is a good example to follow – it walks through creating a reasonably common and useful interface that falls outside of the usual sliding menu or tabbed menu approach that is available by default in Ionic. So we will recreate that same layout again in Ionic, this is what we’re aiming for:

Complex Layout Example

This layout has a header area to place branding, and 6 icons beneath it that will serve as navigation to various parts of the application. In this example we will just be creating the layout itself, not the navigation as well.

1. Create a new Ionic project

Create a new blank Ionic project by running the following command:

ionic start IconHomeScreen blank

and also enable SASS in the project by first changing your directory into the project you just created:

cd IconHomeScreen

and running:

ionic setup sass

2. Understand how Ionic’s layout system works

To really understand Ionics layout system (which is a grid system), you need to understand the CSS Flexible Box Layout or “Flexbox“. Flexbox is a reasonably new W3C specification that creates a way to align and distribute elements within a container even when the size of the container is unknown. A flex container will expand and shrink items as necessary to best fill the available space and it can be used both horizontally and vertically. It is not yet widely used as it is not supported by all browsers, but since Ionic isn’t intended to run in all browsers it’s free to make use of this fancy new spec!

I recommend taking a look at this article for a more in depth explanation of the concepts of the flexbox layout, but I will talk through the basics as we go.

A flex container has a direction which is either row (left to right), row-reverse (right to left), column (top to bottom) or column-reverse (bottom to top). For example, in the layout we are aiming to create we are creating a series of rows stacked vertically, so we would define our flex container as follows:

.home-container {
  display: -webkit-flex;
  -webkit-flex-direction: column;
}

So each row we add to the container will go under the last. This is the default behaviour of rows added in Ionic anyway, but we will discuss why we’re creating this container class in just a little bit.

A flex item goes inside of a flex container and will follow the “rules” of its parent. In our case the flex items are our rows and cols that live inside of our container. We can specify the flex of individual items which is a ratio of how much space they should occupy compared to everything else. The following is an image from the Sencha Touch layout tutorial which demonstrates the concept of “flex”:

Complex Layout Example

Ignore the rest because some of it is irrelevant to this tutorial, but focus on the “flex” attributes in the diagram above. If you add the flex of the header area and the three icon areas you get 9. The header area has a flex of 3 so it takes up 3/9ths (or 1/3rd) of the total available space and each of the icon rows will take up 2/9ths of the total space. Alter the flex values and you alter the distribution of the space that gets taken up by each item.

3. Add the layouts HTML

To create the layout pictured above, we need to add some rows and columns to our HTML.

  • Open up your index.html file and make the following changes:
  <body ng-app="starter">

    <ion-pane>
      <ion-content scroll="false">

<div class = "row">

<div class = "col text-center">
              [LOGO / HEADER]
            </div>

          </div>


<div class = "row">

<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>


<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>

          </div>


<div class = "row">

<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>


<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>

          </div>


<div class = "row">

<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>


<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>

          </div>

      </ion-content>
    </ion-pane>

  </body>

If you run ionic serve now, the result will look like this:

Ionic Layout 1

Close, but not really what we want. Everything is all squished up the top, but we want it to expand to fit all the available space vertically too. To achieve this we’re going to have to add a container around our content and apply some CSS styling to it. We also want to change the flex values of the header and icon containers too so we will add some CSS classes to identify them.

  • Open up your index.html file and make the following changes:
  <body ng-app="starter">

    <ion-pane>
      <ion-content scroll="false">

<section class = "home-container">

<div class = "row header">

<div class = "col text-center">
              [LOGO / HEADER]
            </div>

          </div>


<div class = "row icon-row">

<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>


<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>

          </div>


<div class = "row icon-row">

<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>


<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>

          </div>


<div class = "row icon-row">

<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>


<div class = "col text-center">
              <button class = "button button-positive">Icon</button>
Title
            </div>

          </div>

        </section>

      </ion-content>
    </ion-pane>

  </body>

4. Add the CSS styles

Now we need to add the CSS styles to make our flexbox layout behave the way we want it to. First, we will define the behaviour of our container.

  • Open up scss/ionic.app.scss and add the following classes:
.home-container {
     display: -webkit-flex;
     -webkit-flex-direction: column;
     height: 100%;
}
.home-container > .row {
     -webkit-flex: 1;
}

Now our flex items that are added to this container will flow from top to bottom, and since we’ve given the container a height of 100% it will fill the whole screen (causing the items within the container to expand to fit as well).

We’ve also defined a default flex of ‘1’ for all rows inside of the home-container. If everything has a flex of ‘1’ then everything will be evenly spaced. If everything has a flex of ‘2’ everything will be evenly spaced as well, it is only when a different flex is supplied that it is noticeable. Now we’re going to do exactly that.

  • Add the following classes to your ionic.app.scss file:
.header {
     -webkit-flex: 1.5 !important;
     -webkit-align-items: center;
     background-color: #1abc9c;
}

.icon-row {
     -webkit-align-items: center;
}

Now we’ve given the header area a flex of 1.5, this means it will be slightly larger (50% larger) than an individual icon row which will only have a flex of 1. Play around with some different flex values on both classes to see the effect.

We are also aligning the contents of the header and icon rows to the center and changing the background colour of the header. The end result looks like this:

Ionic Layout 2

Which looks pretty much exactly like our diagram. The Flexbox layout is a tricky thing to get your head around, but even this reasonably simple example demonstrates how powerful it can be. If you want to learn more about Flexbox, again, I encourage you to read this article and I would also encourage you to poke around through the Ionic documentation to see what other CSS goodies Ionic provides.

What to watch next...

  • Pingback: 100 Ionic Framework Resources()

  • Owa

    cool.Just what i needed

  • Dominik Vogt

    Thats awesome! Didnt know that 🙂

  • Dominik Vogt

    So i tried your approach, but unfortunately it is not working for Safari(5.1.5) and iOS (only tried in ionic view though). Maybe you (or anyone else) can give me some feedback on this issue.

    • Hi Dominik, for Safari you need to add -webkit to all the flex attribute, ie: display: -webkit-flex; -webkit-flex-direction: row; -webkit-flex: 1; (I’ll update this post to reflect that)

      • Dominik Vogt

        Hey Josh, IE and Firefox are working fine. I’ll try to add -webkit and give you an update.

      • Dominik Vogt

        These are my changes, still no success

        .block-menu{
        display: flex;
        display: -webkit-flex; /* Safari */
        flex-direction: column;
        -webkit-flex-direction: column; /* Safari */
        height: 100%;
        background-color: yellow;
        }

        .block-menu > .row{
        flex: 1;
        -webkit-flex: 1; /* Safari */
        }

        .block-menu .header{
        flex: 0.5 !important;
        -webkit-flex: 0.5 !important; /* Safari */
        align-items: center;
        background-color: #1abc9c;
        }

      • You don’t need to include ‘display: flex’ etc. just use -webkit, i.e:

        .block-menu{
        display: -webkit-flex; /* Safari */
        -webkit-flex-direction: column; /* Safari */
        height: 100%;
        background-color: yellow;
        }

        .block-menu > .row{
        -webkit-flex: 1; /* Safari */
        }

        .block-menu .header{
        -webkit-flex: 0.5 !important; /* Safari */
        align-items: center;
        background-color: #1abc9c;
        }

      • Dominik Vogt

        Thanks for your help. One more thing i figured out by my self. You also should change align-items: center to -webkit-align-items: center

      • Ah yes, I missed that one – thanks.

  • Pingback: Creating an Attractive Login Screen in Ionic with Flexbox | HTML5 Mobile Tutorials | Ionic, Phaser, Sencha Touch & PhoneGap()

  • Pingback: How to Create Complex Layouts in Ionic | HTML5 Mobile Tutorials | Ionic, Phaser, Sencha Touch & PhoneGap | Aprender IONIC()

  • 7200rpm

    So I tried the above example and I can’t seem to get the rows to evenly vertically expand to fill the screen. I added all the classes above to the css file and did not use SAAS, but I believe it should still work. Any tips on why I’m getting this behavior? It seems to be ignoring the flex attribute…

    • From memory I’m pretty sure you need to set:

      I don’t think it works with scroll active.

      • 7200rpm

        Perfect! Yes, that’s what I was missing! Thanks a lot!

      • Asdrúbal Iván Suárez Rivera

        Great! That worked. However, I’m very curious, why is this attribute needed? Thanks in advance!

  • marco

    Thanks, that helped me a lot. Is it also possible to stretch the buttons to fit in a row, and keep them at a fixed aspect ratio?

  • Nathan Sturgess

    I am getting the text to the side of the icons placeholder? What am i doing wrong?

  • PERFECT! I’ve been looking for a tutorial that explained how to have flexible height for my ionic app (my home screen buttons kept falling off the bottom of the page) and this worked perfectly, thanks a lot bro!

  • Varshil Shah

    hi josh ..i want grid layout in ionic 2 so i used this same code in ionic 2 ??

    • Peter

      yeah I tried but didn’t succeed with Ionic 2. Please Josh, do you know?