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.