[Ionic Tutorial] Beautiful Custom Tabs with Custom Icons

Hello Guys.
Today I wanna show you my new created custom Tabs for Ionic and how to recreate and modify them.

com-video-to-gif

Its very simple first copy this into your tabs.html like you normally would do.
Nothing special here:

<ion-tabs>
  <ion-tab tabIcon="md-flame" [root]="tab1"></ion-tab>
  <ion-tab tabIcon="md-search" [root]="tab2"></ion-tab>
  <ion-tab tabIcon="md-add" [root]="tab3" class="custom-tab"></ion-tab>
  <ion-tab tabIcon="md-notifications-outline" [root]="tab4" tabBadge="3"></ion-tab>
  <ion-tab tabIcon="custom-profile" [root]="tab5"></ion-tab>
</ion-tabs>

As you can see Tab 1 and Tab 2 are just normal Ionic Tabs. Tab 3 is the custom-tab. and Tab 5 is a normal Ionic Tab but with a custom tab icon like a profile picture for example.

Now comes the interesting part. The CSS. Because I needed to modify alot so this tabs behave the same on ios, android and web.

Now paste this into your tabs.css file:

page-tabs {
    .tabs .tabbar {
        background: #121212;
        width: 90% !important;
        max-width: 400px !important;
        border-radius: 30px;
        margin: 0px 0px 20px 5% !important;
        max-height: 56px;
        height: 56px;
    }

    .tabs .tab-button[aria-selected="true"] .tab-button-icon {
      color: white;
      -webkit-transform: translate3d(0, -5px, 0);
      transform: translate3d(0, -5px, 0);
    }

    .tabs .tab-button-icon {
        color: #f2f2f2;
        padding-bottom: 3px;
    }

    .tabs-md, .tabs-wp {
        a[aria-selected=false]{
            .tab-button-icon[ng-reflect-name=custom-profile], .tab-button-icon[aria-label=custom-profile] {
                background-image: url(../assets/imgs/profilepicture.jpg);
            }
        }

        a[aria-selected=true] {
            .tab-button-icon[ng-reflect-name=custom-profile], .tab-button-icon[aria-label=custom-profile] {
                background-image: url(../assets/imgs/profilepicture.jpg);
            }
        }
    }

    .tabs-ios {
        a[aria-selected=false]{
            .tab-button-icon[ng-reflect-name=custom-profile], .tab-button-icon[aria-label="custom-profile outline"] {
                background-image: url(../assets/imgs/profilepicture.jpg);
            }
        }

        a[aria-selected=true] {
            .tab-button-icon[ng-reflect-name=custom-profile], .tab-button-icon[aria-label=custom-profile] {
                background-image: url(../assets/imgs/profilepicture.jpg);
            }
        }
    }

    #tab-t0-0:after,
    #tab-t0-1:after,
    #tab-t0-3:after,
    #tab-t0-4:after {
      background: none repeat scroll 0 0 transparent;
      bottom: 0;
      content: "";
      display: block;
      height: 7px;
      position: absolute;
      transition: width 0.4s ease 0s, background-color .4s ease;
      width: 0;
      margin-bottom: 12px;
      border-radius: 5px;
    }

    #tab-t0-0[aria-selected=true]:after,
    #tab-t0-1[aria-selected=true]:after,
    #tab-t0-3[aria-selected=true]:after,
    #tab-t0-4[aria-selected=true]:after {
      width: 24px;
      background: purple;
    }

    #tab-t0-0,
    #tab-t0-1,
    #tab-t0-2,
    #tab-t0-3,
    #tab-t0-4 {
        background: #23272a;
        -webkit-box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
        -moz-box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
        box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
    }

    #tab-t0-0 {
        border-top-left-radius: 30px;
        border-bottom-left-radius: 30px;
    }

    #tab-t0-1 {
      border-top-right-radius: 15px;
    }

    #tab-t0-3 {
      border-top-left-radius: 15px;
    }

    #tab-t0-2 {
        overflow: visible !important;

        ion-icon {
            -webkit-transform: translate3d(0, 0px, 0);
            transform: translate3d(0, 0px, 0);
            background: purple;
            padding: 16px !important;
            border-radius: 50% !important;
            width: 60px !important;
            height: 60px !important;
            margin-top: -50px !important;
            box-shadow: 0 0 0 11px #121212;
        }
    }

    #tab-t0-4 {
        border-top-right-radius: 30px;
        border-bottom-right-radius: 30px;

        .tab-button-icon {
            background-repeat:no-repeat;
            background-position:center;
            height:24px;
            width:24px;
            background-size:contain;
            border-radius: 50%;
            -webkit-background-size: contain;
            -moz-background-size: contain;
            -o-background-size: contain;
            &:before {
                display:none;
            }
        }
    }

    .badge {
        background-color: purple;
    }

    .footer::before, .tabs[tabsPlacement="bottom"] > .tabbar::before {
        height: 0px !important;
    }

    .ion-md-add::before {
      content: "\f273";
      margin-top: 1px;
    }
}

Nice now you got the exacte same tabs as I showed above.


How to modify the tabs now?

Here are some tips you need to know if you want to modify them.
This snippet here is needed to create custom tab icons. Ios is seperated from the others because you need to add “outline” to the css ng-reflectname. With this sippet you can specify your icon name and image for either active or inactive tab.

    .tabs-md, .tabs-wp {
        a[aria-selected=false]{
            .tab-button-icon[ng-reflect-name=custom-profile], .tab-button-icon[aria-label=custom-profile] {
                background-image: url(../assets/imgs/profilepicture.jpg);
            }
        }

        a[aria-selected=true] {
            .tab-button-icon[ng-reflect-name=custom-profile], .tab-button-icon[aria-label=custom-profile] {
                background-image: url(../assets/imgs/profilepicture.jpg);
            }
        }
    }

    .tabs-ios {
        a[aria-selected=false]{
            .tab-button-icon[ng-reflect-name=custom-profile], .tab-button-icon[aria-label="custom-profile outline"] {
                background-image: url(../assets/imgs/profilepicture.jpg);
            }
        }

        a[aria-selected=true] {
            .tab-button-icon[ng-reflect-name=custom-profile], .tab-button-icon[aria-label=custom-profile] {
                background-image: url(../assets/imgs/profilepicture.jpg);
            }
        }
    }

Good now with this snipped you add the underline Animation for you specified Tabs. You may wonder where those #tab-t0-x css tags came from. These are from Ionic itself once your tabs get rendered in your browser. With those you can change every tab button individually.

    #tab-t0-0:after,
    #tab-t0-1:after,
    #tab-t0-3:after,
    #tab-t0-4:after {
      background: none repeat scroll 0 0 transparent;
      bottom: 0;
      content: "";
      display: block;
      height: 7px;
      position: absolute;
      transition: width 0.4s ease 0s, background-color .4s ease;
      width: 0;
      margin-bottom: 12px;
      border-radius: 5px;
    }

    #tab-t0-0[aria-selected=true]:after,
    #tab-t0-1[aria-selected=true]:after,
    #tab-t0-3[aria-selected=true]:after,
    #tab-t0-4[aria-selected=true]:after {
      width: 24px;
      background: purple;
    }

This code snippet is just to add those round corners on your tabs:

 #tab-t0-0 {
        border-top-left-radius: 30px;
        border-bottom-left-radius: 30px;
    }

    #tab-t0-1 {
      border-top-right-radius: 15px;
    }

    #tab-t0-3 {
      border-top-left-radius: 15px;
    }

This Code snippet is importand for your round circle button in the middle. Remember to change the Box shadow here to the same color as your Main Scroll Content of you page so you can create the illusion of a “cut out button”:

    #tab-t0-2 {
        overflow: visible !important;

        ion-icon {
            -webkit-transform: translate3d(0, 0px, 0);
            transform: translate3d(0, 0px, 0);
            background: purple;
            padding: 16px !important;
            border-radius: 50% !important;
            width: 60px !important;
            height: 60px !important;
            margin-top: -50px !important;
            box-shadow: 0 0 0 11px #121212;
        }
    }

And this is the last Important css here. With this css you can change the height and width and shape of your new custom tab icon. In my case its the last tab thats why i added the border radius.

   #tab-t0-4 {
        border-top-right-radius: 30px;
        border-bottom-right-radius: 30px;

        .tab-button-icon {
            background-repeat:no-repeat;
            background-position:center;
            height:24px;
            width:24px;
            background-size:contain;
            border-radius: 50%;
            -webkit-background-size: contain;
            -moz-background-size: contain;
            -o-background-size: contain;
            &:before {
                display:none;
            }
        }
    }

I hope you guys like my custom tabs and have fun with them. Cheers :slight_smile:

PS: For all the lazy people out there here is the github link to find the files ready to copy paste them :smiley:

18 Likes

awesome work, thnx for the custom tabs I was looking for something like this

1 Like

Hi no problem man! Glad you like it :slight_smile:

1 Like

It’s really nice… Good job…

1 Like

Thanks! although this doesn’t seem to work on ionic4 since ion-tab is not used anymore, have you give it a thought to adapt it to ionic 4?

3 Likes

I will look into this to create a Ionic 4 version of it. If someone is faster, feel free to create a pull request into my repo :slight_smile:

2 Likes

Hi @reinerluke97!
Congratulations for the job! :smiley: :clap:t5: :clap:t5: :clap:t5:
I would like to convert it to the Ionic 4.x version.
Let me see, if I have time soon.

4 Likes

Great work… :clap: @reinerluke97

1 Like

Hi, this would be great! I would love to see that :slight_smile:

2 Likes

Excellent Work. :+1: :+1: :clap: :clap:

1 Like

Hi, did you tried to convert it to ionic 4.x yet? I was also trying but transition isn’t working as expected.

Don’t have it called Ionic 3/4 - it’s only for Ionic 3?..

It’s not working on Ionic 4.x, it’s fair enough that you might make a version for ionic 4.
But don’t advertise it, if you haven’t made it. :smirk: :joy:

OMG! Sorry, I forgot it…
I get involved in so many projects, that I couldn’t remind me of this one.
I return back soon. Just give me a little bit more time. :smiley:

I’m look forward to that bro :heart_eyes:
Sorry for tripping also :smiley:

1 Like

if you are refering to my github description: I have 3/4 in it because I have planned to add Ionic 4 Components in this repository too. Sorry if it was confusing. But yes I have planned to convert it to Ionic 4 and maybe someone here is faster then me :smiley:

Hey, guys,
I started doing it on IONIC 4/5, but I still can’t finish it.
Some minor adjustments are missing. anyone who can contribute would help everyone. because we are all using Ionic 4/5

image

image

@TomCosta ajuda ai… @reinerluke97 Let’s make it work on ionic 4/5

My html

<ion-tabs>
  <ion-tab-bar slot="bottom">
    <ion-tab-button tab="tab1">
      <ion-icon name="flame"></ion-icon>
      <ion-label >&nbsp;</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="tab2">
      <ion-icon name="search" ></ion-icon>
      <ion-label>&nbsp;</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="tab3">
      <ion-icon name="add" class="custom-tab" ></ion-icon>
    </ion-tab-button>

    <ion-tab-button tab="tab4">
      <ion-icon name="notifications"  ></ion-icon>
      <ion-badge >4</ion-badge>
      <ion-label>&nbsp;</ion-label>
    </ion-tab-button>
    

    <ion-tab-button tab="tab5" >
      <ion-icon name="person"></ion-icon>
      <ion-label>&nbsp;</ion-label>
    </ion-tab-button>
  </ion-tab-bar>
</ion-tabs>

My Css

ion-tabs{
    background: #121212;
}
ion-tab-bar  {
    background: #121212;
    width: 90% !important;
    max-width: 400px !important;
    border-radius: 30px;
    margin: 5px 0px 5px 5% !important;
    max-height: 56px;
    height: 56px;
}
.tab-selected ion-icon{
    color: white;
}
.tab-selected ion-label{
    width: 20px;
    height: 6px;
    border-radius: 4px;
    background: purple;
}

.tab-selected, ion-tab-button{
    background: #2c2c2c;
}


#tab-button-tab1,
#tab-button-tab2,
#tab-button-tab3,
#tab-button-tab4,
#tab-button-tab5 {
    background: #23272a;
        -webkit-box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
        -moz-box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
        box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
}
#tab-button-tab1 {
    border-top-left-radius: 30px;
    border-bottom-left-radius: 30px;
}

#tab-button-tab2 {
  border-top-right-radius: 15px;
}

#tab-button-tab4 {
  border-top-left-radius: 15px;
}
#tab-button-tab3 {
    overflow: visible !important;

    ion-icon {
        -webkit-transform: translate3d(0, 0px, 0);
        transform: translate3d(0, 0px, 0);
        background: purple;
        padding: 16px !important;
        border-radius: 50% !important;
        width: 40px !important;
        height: 40px !important;
        margin-top: -50px !important;
        box-shadow: 0 0 0 11px #121212;
    }
}
#tab-button-tab5 {
    border-top-right-radius: 30px;
    border-bottom-right-radius: 30px;

    .tab-button-icon {
        background-repeat:no-repeat;
        background-position:center;
        height:24px;
        width:24px;
        background-size:contain;
        border-radius: 50%;
        -webkit-background-size: contain;
        -moz-background-size: contain;
        -o-background-size: contain;
        &:before {
            display:none;
        }
    }
}
ion-badge {
    --background: purple;
    --color: white;
    width: 23px;
    height: 21px;
    font-size: .8rem;
}
1 Like

@FlavianoRedressa I used your code posted here for a starting point and tried a few things

I basically removed the functionality of the middle tab and added a div to affect the visual styling, and added a FAB Button instead. it navigates with the router in the ts instead of a tab property.

Let me know if this covers all the bases!

HTML:

<ion-tabs>
  <ion-tab-bar slot="bottom">
    <ion-tab-button tab="tab1">
      <ion-icon name="flame"></ion-icon>
      <ion-label >&nbsp;</ion-label>
    </ion-tab-button>

    <ion-tab-button tab="tab2">
      <ion-icon name="search"></ion-icon>
      <ion-label>&nbsp;</ion-label>
    </ion-tab-button>

    <ion-tab-button class="tab-3">
      <div></div>
    </ion-tab-button>

    <ion-tab-button tab="tab4">
      <ion-icon name="notifications"></ion-icon>
      <ion-badge >4</ion-badge>
      <ion-label>&nbsp;</ion-label>
    </ion-tab-button>
    

    <ion-tab-button tab="tab5" >
      <ion-icon name="person"></ion-icon>
      <ion-label>&nbsp;</ion-label>
    </ion-tab-button>
  </ion-tab-bar>
</ion-tabs>
<ion-fab horizontal="center" vertical="bottom">
  <ion-fab-button 
    [ngClass]="selectedTab?.includes('tab3') ? 'active-middle' : ''"
    class="custom-tab" 
    (click)="middleTabHandler($event)">
    <ion-icon name="add"></ion-icon>
  </ion-fab-button>
</ion-fab>

CSS:

ion-tabs{
    background: #121212;
    --height: 76px;
    min-width: 420px;
}

ion-tab-bar {
    background: #121212;
    border-radius: 30px;
    margin: 0px 15% !important;
}

.tab-selected ion-icon {
    color: white;
    transform: scale(.85) ;
    transition: all .25s;
}
.tab-selected ion-label {
    display: block;
    width: 20px;
    height: 4px !important;
    border-radius: 5px;
    background: purple;
}

ion-tab-button:not(.tab-selected) {
    ion-icon {
        transform: translateY(6px) scale(1);
        transition: all .1s;
    }
}


#tab-button-tab1,
#tab-button-tab2,
#tab-button-tab3,
#tab-button-tab4,
#tab-button-tab5 {
    --background: #23272a;
    -webkit-box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
    -moz-box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
    box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
}
#tab-button-tab1 {
    border-top-left-radius: 30px;
    border-bottom-left-radius: 30px;
}

#tab-button-tab2 {
  border-top-right-radius: 12px;
}

.tab-3 {
    padding: 0 !important;
    margin: 0 !important;
    max-width: 72px !important;
    background: #23272a !important;
    margin-top: -30px !important;
    height: 86px;
    --ripple-color: transparent !important;
    cursor:  default !important;
    div {
        position: absolute;
        background:#121212 !important;
        height: 72px;
        width: 72px !important;
        border-bottom-left-radius: 50%;
        border-bottom-right-radius: 50%;
    }
}

#tab-button-tab4 {
  border-top-left-radius: 12px;
}

#tab-button-tab5 {
    border-top-right-radius: 30px;
    border-bottom-right-radius: 30px;
}
ion-badge {
    --background: purple;
    --color: white;
    width: 23px;
    height: 21px;
    font-size: .8rem;
}

@media screen and (max-width: 420px) {
    ion-fab {
        left: 210px;
        transform: translateX(calc(240px* -50%));
    }
}

ion-fab {
    overflow: visible !important;
    bottom: 16px !important;
    position: absolute;
    bottom: 12px !important;

    ion-fab-button {
        --background: var(--ion-color-light);
        --background-hover: purple;
        --background-activated: purple;
        --background-focused: purple;
        --color: purple;
        --ripple-color: purple;
        border-color: purple !important;
        border-width: 6px !important;
        border-radius: 50% !important;
        border-style: solid !important;
        
    }
    .active-middle {
        --background: purple !important;
        --color: var(--ion-color-light) !important;
        border-color: transparent !important;
        border-width: 0 !important;
    }
}

TS:

...
ionViewDidEnter() {
    this.updateSelectedTab();
}

middleTabHandler(event: any) {
    this.updateSelectedTab();
    this.router.navigateByUrl('/tabs/tab3');
}

updateSelectedTab() {
    this.selectedTab = this.tabs.getSelected();
}
2 Likes

@jjdev thanks for contributing!

I did some tests and I believe that you will have problems with IOS platform.

But always keep us informed …

Sorry I’m using google translator

let me know if theres anything i can do to help fix!

the custom tab width/ fab alignment was based on a min-width of 420px for the whole app

@jjdev @FlavianoRedressa @Malthe @TomCosta @TaimoorMughal @valdeca

Hi guys sorry it took so long but I was very bussy.
But now I finally had time to convert them to ionic 4 and 5.
They look almost the same:

ionic5tabs
(Note: didnt tested them on devices. ATM only on browser)

Here is the tabspage.html:

<ion-tabs>

  <ion-tab-bar slot="bottom" color="purple">
    <ion-tab-button tab="tab1">
      <ion-icon name="flame"></ion-icon>
    </ion-tab-button>

    <ion-tab-button tab="tab2">
      <ion-icon name="search"></ion-icon>
    </ion-tab-button>

    <ion-tab-button tab="tab3" class="custom-tab">
      <ion-icon name="add"></ion-icon>
    </ion-tab-button>

    <ion-tab-button tab="tab4">
      <ion-icon  name="notifications"></ion-icon>
      <ion-badge>9</ion-badge>
    </ion-tab-button>

    <ion-tab-button tab="tab5" class="custom-profile">
      <ion-icon></ion-icon>
    </ion-tab-button>
  </ion-tab-bar>

</ion-tabs>

Here is the tabs.page.ts snippet you need for an element in the shadow dom:

ionViewDidEnter() {
    document.querySelector('#tab-button-tab3').shadowRoot.querySelector('.button-native').setAttribute('style', 'margin-top: -2px');
}

And here is the tabs.page.scss file:


ion-tabs{
    background: #121212;
}

ion-tab-bar  {
    background: #121212;
    width: 90% !important;
    max-width: 400px !important;
    border-radius: 30px;
    margin: 5px 0px 5px 5% !important;
    max-height: 56px;
    height: 95px;
    max-height: 95px;
    border: unset;
}

.tab-selected ion-icon{
    color: white;
    padding-bottom: 9px;
}

.tab-selected, ion-tab-button{
    background: #2c2c2c;
}

#tab-button-tab1,
#tab-button-tab2,
#tab-button-tab3,
#tab-button-tab4,
#tab-button-tab5 {
    background: #23272a;
    -webkit-box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
    -moz-box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
    box-shadow: 5px 5px 15px -15px  rgba(0,0,0,0.4);
    --border: none;
    max-height: 56px;
    margin-top: 39px;
}

ion-tab-button:hover {
    ion-icon, ion-label {
        color: white !important;
        --ion-color-base: white !important;
    }
}

ion-tabs {
    //not selected custom image
    ion-tab-button.custom-profile > ion-icon {
        background-image: url(https://blog.photofeeler.com/wp-content/uploads/2017/09/instagram-profile-picture-maker.jpg);
    }

    //selected custom image
    ion-tab-button.tab-selected.custom-profile > ion-icon {
        background-image: url(https://blog.photofeeler.com/wp-content/uploads/2017/09/instagram-profile-picture-maker.jpg);
    }
}

#tab-button-tab1 {
    border-top-left-radius: 30px;
    border-bottom-left-radius: 30px;
}

#tab-button-tab2 {
  border-top-right-radius: 15px;
}

#tab-button-tab4 {
  border-top-left-radius: 15px;
}

#tab-button-tab3 {
    overflow: visible !important;
    max-height: 120px !important;
    height: 120px !important;
    border-top-left-radius: 20px;
    border-top-right-radius: 20px;

    ion-icon {
        transform: translate3d(0, 0px, 0);
        background: purple;
        padding: 10px !important;
        border-radius: 50% !important;
        width: 40px !important;
        height: 40px !important;
        margin-top: -60px !important;
        box-shadow: 0 0 0 15px #121212;
        border: unset;
    }
}

#tab-button-tab3::part(a) {
    --margin-top: -2px !important;
}
#tab-button-tab3 > a {
    --margin-top: -2px !important;
}

#tab-button-tab5 {
    border-top-right-radius: 30px;
    border-bottom-right-radius: 30px;

    ion-icon {
        background-repeat:no-repeat;
        background-position:center;
        height:24px;
        width:24px;
        background-size:contain;
        border-radius: 50%;
        -webkit-background-size: contain;
        -moz-background-size: contain;
        -o-background-size: contain;
        &:before {
            display:none;
        }
    }
}

#tab-button-tab5.tab-selected ion-icon{
    padding-bottom: 0px;
}

ion-badge {
    --background: purple;
    --color: white;
    width: 23px;
    height: 21px;
    font-size: 0.8rem;
    margin-top: -8px;
    padding-top: 5px;
}

#tab-button-tab1 > ion-icon:after,
#tab-button-tab2 > ion-icon:after,
#tab-button-tab4 > ion-icon:after {
    background: none repeat scroll 0 0 transparent;
    bottom: 0;
    content: "";
    display: block;
    height: 7px;
    position: absolute;
    transition: width 0.4s ease 0s, background-color .4s ease;
    width: 0;
    border-radius: 5px;
}

#tab-button-tab1.tab-selected > ion-icon:after,
#tab-button-tab2.tab-selected > ion-icon:after,
#tab-button-tab4.tab-selected > ion-icon:after {
    width: 24px;
    background: purple;
}

Hope you like it! I also extended my GitHub Repo of the tabs with the new ones. Please Hit a Star if you like it and if you have some nice changes fee free to commit to my repo :slight_smile: Cheers :beers:

3 Likes