Welcome to my blog, if there’s something I didn’t cover, feel free to leave me a comment below and I will respond as soon as humanly possible. The topic of today’s article is an in-depth review of Onsen UI Framework.

Note: If this tutorial was helpful, need further clarification, something is not working or do you have a request for another Ionic post? Furthermore, if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here, again leave me a comment below. I'm here to help you, I expect the same from you. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com, or follow and mention me on twitter (@gajotres). Thanks and have a nice day!

PS. If you want my help, if possible (even if it takes you some time to do that), create a working example I can play with. Use Plunker for AngularJS based questions or jsFiddle for jQuery/jQuery Mobile based questions.

Link Getting Started GitHub Repo
In recent months, I have written a series of tutorials covering OnsenUI, find them below:


This is Part 5 in a multipart series called: “Best HTML5 Mobile App Frameworks”
Note: I have no intention of stopping writing after I review Kendo UI. If you want me to review a framework you like or know about just write me a comment below.

What Is Onsen UI?

Onsen UI is relatively new addition to mobile framework market. It was released almost one year ago which puts it around the same timeline like Ionic and Famo.us frameworks. It name was taken from the Japanese language (温泉) and it is a term for hot springs or spa.
Just like Ionic and Famo.us, it was built around AnguarJS framework (for the future reference we will call it Angular), but latest changes made it possible to work with other frameworks (like jQuery).
For those of you who are not familiar, AngularJS, commonly referred to as Angular, is an open-source web application framework maintained by Google and a community of individual developers and corporations to address many of the challenges encountered in developing single-page applications.
Unlike Ionic, Onsen UI CSS framework is built around Topcoat. It is an open source CSS library designed with speed in mind. Because it doesn’t contain any JavaScript, Topcoat was choosen as a perfect UI building block.
Onsen UI helps you develop both hybrid and web apps. If developing hybrid apps, you can use it with the Cordova / PhoneGap command line, or with Monaca IDE – cloud-based IDE for Cordova. Monaca IDE is a cloud HTML5 development platform that offers programmers the option to develop hybrid mobile applications and deploy them across multiple platforms.

What Onsen UI is not?

Onsen UI suffers from the same problem like jQuery Mobile. It can be used for classic web development but, it looks out of the place when viewed on larger screens. This is somewhat solved with multi-screen support, but you will need to decide if this is good enough for you.
If you like HTML5 markup based frameworks then this is not a framework for you. It’s somewhere between Sencha Touch and jQuery Mobile.
Onsen UI is not a replacement for Ionic framework. While both frameworks can be used for mobile app development, Onsen UI went even further with classic web app support.

Main features

  • Free and Open Source
  • Simple to Use
  • Built around AngularJS, Topcoat, and HammerJS
  • Lates changes makes it possible to work with jQuery
  • Built-in Theme Roller
  • Supports Cordova, PhoneGap, or native app packaging with Monaca IDE
  • Usable for mobile and classic web development
  • Multi-screen Support
  • Font Awesome support

Code example




  <script src="https://code.angularjs.org/1.3.0/angular.js"></script>
  <script src="http://onsenui.io/OnsenUI/build/js/onsenui.js"></script>
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/onsenui.css" />
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/onsen-css-components.css" />

<body ng-controller="ListCtrl">

  <ons-navigator animation="slide" var="app.navi">
      <ons-toolbar class="toolbar-black">
        <div class="center">Search the Movie Database</div>
      <input type="search" class="search-input search-movies-input" placeholder="Search..." style="width: 100%;height: 45px;" ng-model="movie.name" ng-change="searchMovieDB()">
        <ons-list-item modifier="chevron" class="list-item-container" ng-repeat="movie in movies" ng-click="showDetail(movie.id)">
            <ons-col width="95px">
              <img ng-src="https://image.tmdb.org/t/p/w92{{movie.poster_path}}" onerror="this.src = 'https://www.ginesisnatural.com/images/no_image.jpg';" class="thumbnail">
              <div class="name">{{movie.original_title}}</div>
              <div class="desc">{{movie.release_date}}</div>
            <ons-col width="40px"></ons-col>

  <ons-template id="view.html">
    <ons-page ng-controller="ViewCtrl">
        <div class="left" style="line-height: 44px">
        <div class="center">Second Page</div>
      <div class="columns">
          <div class="pin">
              <div class="pin-header">
                <img src="https://cdn0.iconfinder.com/data/icons/iconsweets2/40/movie_film.png">
              <img ng-src="https://image.tmdb.org/t/p/w92{{movie.poster_path}}" width="200px" />
                Average Vote: <strong>{{movie.vote_average}}</strong> (Votes: {{movie.vote_count}})


var module = ons.bootstrap('my-app', ['onsen']);

module.factory('Movies', function($http) {
  var cachedData;
  function getData(moviename, callback) {
    var url = 'http://api.themoviedb.org/3/',
      mode = 'search/movie?query=',
      name = '&query=' + encodeURI(moviename),
      key = '&api_key=470fd2ec8853e25d2f8d86f685d2270e';
    $http.get(url + mode + key + name).success(function(data) {
      cachedData = data.results;
  return {
    list: getData,
    find: function(name, callback) {
      var movie = cachedData.filter(function(entry) {
        return entry.id == name;

module.controller('ListCtrl', function($scope, Movies) {
  $scope.movie = {
    name: 'Batman'
  $scope.searchMovieDB = function() {
    Movies.list($scope.movie.name, function(movies) {
      $scope.movies = movies;
  $scope.showDetail = function(id){ // 3
    app.navi.pushPage("view.html", { animation: "lift", movieid: id });

module.controller('ViewCtrl', function($scope, Movies) {
  var page = app.navi.getCurrentPage();
  Movies.find(page.options.movieid, function(movie) {
    $scope.movie = movie;


.toolbar-black {
  border-color: #111 !important;
  background-color: #444444 !important;

.toolbar-black .center {
  color: #fff !important;  
.search-movies-input {
  border-width: 0px !important;
  background-color: #fff !important;

.list-item-container {
  line-height: 1;
  padding: 15px 0px 0 15px !important;

.thumbnail {
  width: 80px;
  height: 120px;

.name {
  font-weight: 700;
  line-height: 16px;
  font-size: 15px;
  margin-bottom: 6px;

.desc {
  line-height: 1.2;
  font-size: 11px;

.columns {
  -webkit-column-count: 1;
  -webkit-column-gap: 10px;
  -webkit-column-fill: auto;
  -moz-column-count: 1;
  -moz-column-gap: 10px;
  -moz-column-fill: auto;
  column-count: 1;
  column-gap: 15px;
  column-fill: auto;

.pin {
  width: 96%;
  margin: 1%;
  display: inline-block;
  background: #FEFEFE;
  border: 2px solid #FAFAFA;
  box-shadow: 0 1px 2px rgba(34, 25, 25, 0.4);
  -webkit-column-break-inside: avoid;
  -moz-column-break-inside: avoid;
  column-break-inside: avoid;
  padding: 15px;
  padding-bottom: 5px;
  background: -webkit-linear-gradient(45deg, #FFF, #F9F9F9);
  opacity: 1;	
  -webkit-transition: all .2s ease;
  -moz-transition: all .2s ease;
  -o-transition: all .2s ease;
   transition: all .2s ease;

.pin img {
  width: 100%;
  border-bottom: 1px solid #ccc;
  padding-bottom: 15px;
  margin-bottom: 5px;

.pin-header {
  padding-left: 72px;
  min-height: 72px;
  border-color: #ddd;
  background-color: #fff;
  color: #444;
  position: relative;
  z-index: 2;
  display: block;
  margin: -1px;
  padding: 16px;
  border-width: 1px;
  border-style: solid;
  font-size: 16px;  

.pin-header img {
position: absolute;
  top: 16px;
  left: 16px;
  max-width: 40px;
  max-height: 40px;
  width: 100%;
  height: 100%;
  border-radius: 50%;  
  margin: 0;
  padding: 0;
  border: 0;
  vertical-align: baseline;
  font: inherit;
  font-size: 100%;  

.pin-header h2, .pin-header p {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin: 0 0 2px 80px !important;
  font-size: 16px;
  font-weight: normal;
  color: #000;
  font-weight: 500;
  font-family: "Helvetica Neue", "Roboto", sans-serif;
  line-height: 1.2;
  display: block;
  font-size: 1em;

.pin p {
  font: 12px/18px Arial, sans-serif;
  color: #333;
  margin: 0;

#columns:hover .pin:not(:hover) {
  opacity: 0.4;

Working example:

Embedded working example:
OnsenUI Navigation Pattern
Continue Reading

  • very nice i loved phonegap and this framework but this not support rtl right to left
    and from where can i get thems for it ?
    thank you

    • I don’t understand you, it’s not supporting what?

      You need ti create your own themes, just like with Ionic Framework.

  • Mac

    The previous commenter was saying that the framework does not support right-to-left (needed for middle eastern languages like Arabic, Persian, Hebrew) and some others.

    I am not sure whether it’s true or not though.