Ionic bootstrap like responsive Grid scss

this code is a simple snippet which give you a bootstrap like responsive grid
Create a grid.scss file in in your theme folder then paste the following code

// A Mixin created from Grid.scss
@mixin custom-grid-break($selector, $max-width) {
  @media screen and (max-width: $max-width) {
    ion-col {
      &[#{$selector}-offset-10] {
        margin-left: 10%;
      }
      &[#{$selector}-offset-20] {
        margin-left: 20%;
      }
      &[#{$selector}-offset-25] {
        margin-left: 25%;
      }
      &[#{$selector}-offset-33],
      &[#{$selector}-offset-34] {
        margin-left: 33.3333%;
      }
      &[#{$selector}-offset-50] {
        margin-left: 50%;
      }
      &[#{$selector}-offset-66],
      &[#{$selector}-offset-67] {
        margin-left: 66.6666%;
      }
      &[#{$selector}-offset-75] {
        margin-left: 75%;
      }
      &[#{$selector}-offset-80] {
        margin-left: 80%;
      }
      &[#{$selector}-offset-90] {
        margin-left: 90%;
      }
      // Explicit Column Percent Sizes
      // By default each grid column will evenly distribute
      // across the grid. However, you can specify individual
      // columns to take up a certain size of the available area
      &[#{$selector}-width-10] {
        flex: 0 0 10%;
        max-width: 10%;
      }
      &[#{$selector}-width-20] {
        flex: 0 0 20%;
        max-width: 20%;
      }
      &[#{$selector}-width-25] {
        flex: 0 0 25%;
        max-width: 25%;
      }
      &[#{$selector}-width-33],
      &[#{$selector}-width-34] {
        flex: 0 0 33.3333%;
        max-width: 33.3333%;
      }
      &[#{$selector}-width-50] {
        flex: 0 0 50%;
        max-width: 50%;
      }
      &[#{$selector}-width-66],
      &[#{$selector}-width-67] {
        flex: 0 0 66.6666%;
        max-width: 66.6666%;
      }
      &[#{$selector}-width-75] {
        flex: 0 0 75%;
        max-width: 75%;
      }
      &[#{$selector}-width-80] {
        flex: 0 0 80%;
        max-width: 80%;
      }
      &[#{$selector}-width-90] {
        flex: 0 0 90%;
        max-width: 90%;
      }
      &[#{$selector}-width-100] {
        flex: 0 0 100%;
        max-width: 100%;
      }
    }
  }
}

// use this mixin
@include custom-grid-break('md', $grid-responsive-md-break);
@include custom-grid-break('sm', $grid-responsive-sm-break);

Now import this in app.core.scss
please import this scss as the first one(i.e) let it be the first line

now you can use it ass follows

  <ion-grid radio-group [(ngModel)]="selectedvalue">
    <ion-row wrap *ngFor="let row of foptions">
      <ion-col sm-width-100 md-width-20 width-10 *ngFor="let option of row.values">
        <ion-item>
          <ion-label>{{option.text}}</ion-label>
          <ion-radio value="{{option.value}}"></ion-radio>
        </ion-item>
      </ion-col>
    </ion-row>
  </ion-grid>

i am just use the two breakpoints only you can add more
donā€™t forget to add the wrap

2 Likes

Cool, I also missed ā€œresponsivenessā€ in the Ionic grid (Bootstrap-like sm/md/lg classes), so I looked for a solution.

I ended up using a variation of Responsive Grid layout (credits to @ndudenhoeffer ), the code looks like this:

// CSS Media breakpoint values copied from Ionic SASS file: _grid.css
$grid-responsive-sm-break:        567px !default;  // smaller than landscape phone
$grid-responsive-md-break:        767px !default;  // smaller than portrait tablet
$grid-responsive-lg-break:        1023px !default; // smaller than landscape tablet

$screen-sm: $grid-responsive-sm-break;
$screen-md: $grid-responsive-md-break;
$screen-lg: $grid-responsive-lg-break;

$col-widths: 10 20 25 30 33 40 50 66 70 75 80 90;

// Container with flex settings, without this the grid will not work correctly!
.responsive-grid-container {
    display: -webkit-flex;
    -webkit-flex-direction: row;

    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}

@mixin col-class-maker($size, $width){
    .col-#{$size}-#{$width} {
        @include flex(0, 0, percentage($width/100));
        max-width: percentage($width/100);
    }
}

// Create the small columns
@each $width in $col-widths {
    @include col-class-maker(sm, $width);
}

// Create the md columns
@each $width in $col-widths {
    @media ( min-width: ($screen-sm + 1) ){
        @include col-class-maker(md, $width);
    }
}

// Create the lg columns
@each $width in $col-widths {
    @media ( min-width: ($screen-md + 1) ){
        @include col-class-maker(lg, $width);
    }
}

To make it work, I added the container element and the definition of the breakpoints. Now you can put this on your ā€œion-itemā€ element to make a grid with 2, 3 and 4 columns respectively on small, medium and large screens:

class="col-sm-50 col-md-33 col-lg-25"

Something like that.

Using this for Ionic 1 but it should work equally well for Ionic 2.

1 Like

sounds good, include the offset to bro

Ah I see it, you have offset classes too, nice ā€¦ yeah no flex needed for that, just margins. And whatā€™s best is if you can use it as SASS mixins so you can just add it to your ā€œsemanticā€ CSS classes instead of having to add ā€œcolā€ classes to your markup.

Shouldnā€™t they make this part of ā€œstandardā€ Ionic?

yes it is there in standard but, not for responsive

what if i want to position an element in different areas for different views

<ion-col sm-offset-10 md-offset-50 offset-80>

well i plan to add the alignment too

someone will need that too

Yes exactly, thatā€™s what I meant, this kind of thing is not in standard Ionic.

The grid system of Ionic is touted as ā€œsimple and easyā€ but IMO it is a bit too simple, thereā€™s no real support for responsive/adaptive apart from hand-coding your media queries, thatā€™s also why I started looking for something better.

yes, humbly accept it, i am new to this arena let some body will provide some light on this

Hi, @Thavarajan and @leob, great work! And thanx for your work!

We are building a heavy app and are trying to make a responsive ionic2 app which works on mobile and also on desktop. So make it responsive is a thing we need and also a thing we donā€™t understand why the ionic team is only working on mobile and not try to push it more for desktop.

We have tried to integrate @Thavarajan example, but it doesnā€™t work. We are using ionic2 and integrated the css in app.scss file. It works only width-XX but sm-width-XX and md-width-XX never work!! Can you help us?

@Thavarajan did you add alignment too?

sure @mburger81
may i know how did you implement it?

add the break boint in the following order

medium
small

the above scss only work with ion-col

what do you intend with break point?

in my app.scss I put the same thing as you

// A Mixin created from Grid.scss
@mixin custom-grid-break($selector, $max-width) {
@media screen and (max-width: $max-width) {
ion-col {
&[#{$selector}-offset-10] {
margin-left: 10%;
}
&[#{$selector}-offset-20] {
margin-left: 20%;
}
&[#{$selector}-offset-25] {
margin-left: 25%;
}
&[#{$selector}-offset-33],
&[#{$selector}-offset-34] {
margin-left: 33.3333%;
}
&[#{$selector}-offset-50] {
margin-left: 50%;
}
&[#{$selector}-offset-66],
&[#{$selector}-offset-67] {
margin-left: 66.6666%;
}
&[#{$selector}-offset-75] {
margin-left: 75%;
}
&[#{$selector}-offset-80] {
margin-left: 80%;
}
&[#{$selector}-offset-90] {
margin-left: 90%;
}
// Explicit Column Percent Sizes
// By default each grid column will evenly distribute
// across the grid. However, you can specify individual
// columns to take up a certain size of the available area
&[#{$selector}-width-10] {
flex: 0 0 10%;
max-width: 10%;
}
&[#{$selector}-width-20] {
flex: 0 0 20%;
max-width: 20%;
}
&[#{$selector}-width-25] {
flex: 0 0 25%;
max-width: 25%;
}
&[#{$selector}-width-33],
&[#{$selector}-width-34] {
flex: 0 0 33.3333%;
max-width: 33.3333%;
}
&[#{$selector}-width-50] {
flex: 0 0 50%;
max-width: 50%;
}
&[#{$selector}-width-66],
&[#{$selector}-width-67] {
flex: 0 0 66.6666%;
max-width: 66.6666%;
}
&[#{$selector}-width-75] {
flex: 0 0 75%;
max-width: 75%;
}
&[#{$selector}-width-80] {
flex: 0 0 80%;
max-width: 80%;
}
&[#{$selector}-width-90] {
flex: 0 0 90%;
max-width: 90%;
}
&[#{$selector}-width-100] {
flex: 0 0 100%;
max-width: 100%;
}
}
}
}

// use this mixin
@include custom-grid-break(ā€˜mdā€™, $grid-responsive-md-break);
@include custom-grid-break(ā€˜smā€™, $grid-responsive-sm-break);

seems every thing fine, review your main.css in the www/build/ folder
confirm the order of breakpoint generation
and
may i know how did you use it in youur code
can you share your code

Thanks for sharing your scss. It was a big help in making my ionic 2 app responsive.

I tweaked a few things to integrate it more seamless into ionic 2 and wanted to share it here for others to use:

  • Uses attributes instead of classes (like the standard grid does with width-XX)
  • made responsive-grid-container into attribute responsive (note: not needed in grid)
  • Added offset definitions
  • Added a few widths for more flexibility
  • Updated media queries to be more specific. This way the standard ionic 2 width-XX attribute can take over whenever the viewport doesnā€™t fit these definitions
  • added width-XX for any element, for responsiveness not just in grid
// Adding responsiveness to ionic grid based on:
// https://forum.ionicframework.com/t/ionic-bootstrap-like-responsive-grid-scss/63653/2
// SirTori: Changed classes to attributes to reflect ionic 2 conventions
// and added offset

// CSS Media breakpoint values copied from Ionic SASS file: _grid.css
$grid-responsive-sm-break:        567px !default;  // smaller than landscape phone
$grid-responsive-md-break:        767px !default;  // smaller than portrait tablet
$grid-responsive-lg-break:        1023px !default; // smaller than landscape tablet

$screen-sm: $grid-responsive-sm-break;
$screen-md: $grid-responsive-md-break;
$screen-lg: $grid-responsive-lg-break;

$col-widths: 10 15 20 25 30 33 40 50 60 66 70 75 80 90 100;

[responsive] {
    display: -webkit-flex;
    -webkit-flex-direction: row;

    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}

@mixin col-class-maker($size, $width){
    ion-col[width-#{$width}-#{$size}],
    [width-#{$width}-#{$size}] {
        flex: 0 0 percentage($width/100);
        max-width: percentage($width/100);
    }
    ion-col[offset-#{$width}-#{$size}],
    [offset-#{$width}-#{$size}] {
        margin-left: percentage($width/100);
    }
}

// Create the small columns
@each $width in $col-widths {
    @media (min-width: 0) and (max-width: $screen-sm){
        @include col-class-maker(sm, $width);
    }
}

// Create the md columns
@each $width in $col-widths {
    @media (min-width: ($screen-sm + 1)) and (max-width: $screen-md){
        @include col-class-maker(md, $width);
    }
}

// Create the lg columns
@each $width in $col-widths {
    @media (min-width: ($screen-md + 1)) and (max-width: $screen-lg){
        @include col-class-maker(lg, $width);
    }
}

@each $width in $col-widths {
    @media (min-width: ($screen-lg + 1)){
        [width-#{$width}] {
            flex: 0 0 percentage($width/100);
            max-width: percentage($width/100);
        }
        [offset-#{$width}] {
            margin-left: percentage($width/100);
        }
    }
}

with this you can built a grid like that:

<ion-grid>
  <ion-row wrap>
    <ion-col width-25 width-33-lg width-50-md width-100-sm *ngFor="let x of elements" >
      <div>X</div>
    </ion-col>
  </ion-row>
</ion-grid>

With this the grid has following behavour:

  • On screens up to $grid-responsive-sm-break width the col will take the full width (1 per row)
  • On screens up to $grid-responsive-md-break width the col will take 50% of the width (2 per row)
  • On screens up to $grid-responsive-lg-break width the col will take 33% of the width (3 per row)
  • On any bigger screen the col will take 25% of the width (4 per row)

And without grid:

<ion-content padding responsive>
  <div offset-25 width-50 offset-15-lg width-70-lg offset-10-md width-80-md offset-0-sm width-100-sm>
    <!-- rest of page -->
  </div>
</ion-content>

Here the layout of the whole content would be

  • On screens up to $grid-responsive-sm-break full width
  • On screens up to $grid-responsive-md-break 80% width with 10% margin on either side
  • On screens up to $grid-responsive-lg-break 70% width with 15% margin on either side
  • On any bigger screen 50% width with 25% margin on either side

edit Added example and a bit of scss for responsiveness outside of ion-grid

Wow cool ā€¦ Iā€™m not completely up to speed yet with Ionic 2, so I am somewhat surprised that it is possible to just substitute attributes for CSS classes (I created the grid for an Ionic 1 app). Very powerful, I suppose this capability comes with Angular 2.

How are your experiences with Ionic 2, is it a big step forward compared to Ionic 1 ?

I never worked with ionic 1 and only started with ionic 2 a few weeks ago, so I couldnā€™t really compare those two.

But I got the feeling ionic 2 in general is still pretty hard to get into right now. Many problems I stumble upon (maybe partially because I never worked with ionic before at all) have answers that are no longer valid because ionics or angular 2 api changed since the answer was given. Then you have to find what the answer translates to in the new api. I often have up to 15 Tabs open looking for answers and trying to put a working one together.
But this is something I guess will get better over time.

Interesting to hear that, because I have a lot of experience with Ionic 1, but very little with Ionic 2.

However I see that the great majority of the questions/answers on the Ionic forum are now about Ionic 2 so probably the knowledge you look for will come.

Also of course Ionic 2 is based on Angular 2, so I suppose it will help to also study Angular 2 (although it seems the goal of the Ionic team is really to take Angular 2 and make it much easier to use, they are hiding quite a lot of complexity).

And yes indeed, Angular 2 (and Ionic 2) are very, very different from Angular 1 and Ionic 1, if you wnt to use ā€œoldā€ answers from e.g. Stackoverflow you will have a lot ā€œtranslatingā€ to do.

with ā€œoldā€ answers i didnā€™t mean answers that used ionic 1 or angular 1, but answers that were written for an earlier build (Beta or RC) of ionic 2 and/or angular 2.

For example I had a problem with using ionic 2 components in custom angular2 components. All the answers said I should import {IONIC_DIRECTIVES} from ā€˜ionic-angularā€™ and declare them as directives: [IONIC_DIRECTIVES] on the angular @component. But the ā€˜directivesā€™ attribute does no longer exist for components. It took me some time to figure out that I can simple import { IonicModule } from ā€˜ionic-angularā€™; and declare it as an import on the angular @NgModule.

So even if there are already many questions and answers for ionic 2, some of them just donā€™t work anymore

Thatā€™s the general complaint with both Ionic 2 and especially Angular 2, everything changes all the time which drives people crazy ā€¦ this should get better now that Angular 2 is final, and Ionic 2 is almost final.

I think Iā€™m happy that I ā€œskippedā€ the bleeding edge phase ā€¦ anyway I was too busy (building an Ionic 1 app for my client) to spend much time with Ionic 2. I must say Ionic 1 works very nice at least for the projects Iā€™ve done, but Iā€™m looking forward to trying out Ionic 2.

By the way Iā€™m also interested in trying out React, which I hear a lot of good things about, itā€™s less heavy and complex than Angular 2 and itā€™s become very popular. Maybe the Ionic team should research if it would be possible to create an Ionic 2 version based on React.

Thank you so much, you made my day! I was missing this feature a lot from ionic 2.