Ionic Framework Guide — Hybrid Mobile Apps with Angular/React/Vue
Ionic Framework is an open-source UI toolkit for building performant, cross-platform mobile and desktop apps using web technologies (Angular, React, or Vue) with a library of native-style UI components and seamless access to device APIs through Capacitor or Cordova.
What You’ll Learn
You’ll use the Ionic CLI to scaffold apps, choose between Capacitor and Cordova for native access, build UIs with Ionic’s component library, customize themes with CSS variables, implement navigation with Angular Router or React Router, and deploy as both native apps and PWAs.
Why Ionic Matters
Ionic is the most popular hybrid mobile framework, powering over 5 million apps worldwide. It bridges the gap between web development and native mobile — one codebase deploys to iOS, Android, and the web as a Progressive Web App. DodaTech’s customer portal uses Ionic because it needs to reach users on every platform while maintaining a single development team that writes TypeScript, not platform-specific languages.
Ionic Learning Path
flowchart LR
A[Angular/React/Vue] --> B[Ionic CLI]
B --> C[Ionic Components]
C --> D[Theming & Styling]
D --> E[Navigation & Routing]
E --> F[Capacitor / Cordova]
F --> G[Native APIs]
G --> H[App Store / PWA]
B:::current
classDef current fill:#498AFF,color:#fff,stroke:#333,stroke-width:2px
Getting Started with Ionic CLI
# Install the Ionic CLI globally
npm install -g @ionic/cli
# Create a new Ionic app
ionic start dodatech-app tabs --type=angular
# Options: --type=angular | --type=react | --type=vue
cd dodatech-app
ionic serve # Opens in browser with live reloadThe CLI scaffolds a complete project with routing, theming, and a tab-based layout:
dodatech-app/
├── src/
│ ├── app/
│ │ ├── pages/ # Page components
│ │ ├── tabs/ # Tab navigation
│ │ └── app-routing.module.ts
│ ├── theme/
│ │ └── variables.css # CSS custom properties
│ ├── assets/
│ └── index.html
├── capacitor.config.ts
├── ionic.config.json
└── package.jsonUI Components
Ionic provides over 50 native-style UI components that adapt to each platform:
<!-- Angular component example -->
<ion-header>
<ion-toolbar color="primary">
<ion-title>DodaTech Scanner</ion-title>
<ion-buttons slot="end">
<ion-button (click)="showSettings()">
<ion-icon slot="icon-only" name="settings-outline"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<!-- Search bar -->
<ion-searchbar
[(ngModel)]="searchQuery"
(ionInput)="searchDevices($event)"
placeholder="Search devices..."
animated>
</ion-searchbar>
<!-- Device list with pull-to-refresh -->
<ion-refresher slot="fixed" (ionRefresh)="refreshList($event)">
<ion-refresher-content></ion-refresher-content>
</ion-refresher>
<ion-list>
<ion-item-sliding *ngFor="let device of filteredDevices">
<ion-item (click)="viewDevice(device)">
<ion-icon :name="device.icon" slot="start" color="medium"></ion-icon>
<ion-label>
<h2>{{ device.name }}</h2>
<p>{{ device.type }} · {{ device.signalStrength }} dBm</p>
</ion-label>
<ion-chip slot="end" [color]="device.isConnected ? 'success' : 'medium'">
{{ device.isConnected ? 'Online' : 'Offline' }}
</ion-chip>
</ion-item>
<ion-item-options side="end">
<ion-item-option color="primary" (click)="editDevice(device)">
<ion-icon slot="icon-only" name="create-outline"></ion-icon>
</ion-item-option>
<ion-item-option color="danger" (click)="deleteDevice(device)">
<ion-icon slot="icon-only" name="trash-outline"></ion-icon>
</ion-item-option>
</ion-item-options>
</ion-item-sliding>
</ion-list>
<!-- Floating action button -->
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button (click)="addDevice()">
<ion-icon name="add"></ion-icon>
</ion-fab-button>
</ion-fab>
</ion-content>Output: The page renders with a native-style header, search bar with animation, a pull-to-refresh list of devices with swipeable action buttons (edit/delete), and a floating action button. On iOS, the components mimic UIKit styling. On Android, they follow Material Design guidelines — automatically.
Theming with CSS Variables
Ionic uses CSS custom properties (variables) for complete theming control:
/* src/theme/variables.css */
/* Light theme */
:root {
--ion-color-primary: #2c3e50;
--ion-color-primary-rgb: 44, 62, 80;
--ion-color-primary-contrast: #ffffff;
--ion-color-secondary: #3498db;
--ion-color-secondary-rgb: 52, 152, 219;
--ion-color-secondary-contrast: #ffffff;
--ion-color-tertiary: #27ae60;
--ion-color-tertiary-rgb: 39, 174, 96;
--ion-color-tertiary-contrast: #ffffff;
--ion-background-color: #f8f9fa;
--ion-text-color: #2c3e50;
--ion-toolbar-background: #2c3e50;
--ion-toolbar-color: #ffffff;
}
/* Dark theme (auto-detected from system preference) */
@media (prefers-color-scheme: dark) {
:root {
--ion-color-primary: #4a6fa5;
--ion-color-secondary: #5dade2;
--ion-background-color: #1a1a2e;
--ion-text-color: #ecf0f1;
--ion-toolbar-background: #16213e;
--ion-toolbar-color: #ecf0f1;
--ion-item-background: #1a1a2e;
--ion-card-background: #16213e;
}
}Output: The entire app adopts the custom color scheme. Primary buttons, headers, and accents use the defined colors. The dark theme activates automatically when the user’s operating system is in dark mode. Every Ionic component respects these variables without additional CSS changes.
Navigation and Routing
Ionic integrates with the framework’s router. Here’s an Angular example:
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: '',
redirectTo: '/devices',
pathMatch: 'full'
},
{
path: 'devices',
loadChildren: () => import('./pages/devices/devices.module').then(m => m.DevicesPageModule)
},
{
path: 'devices/:id',
loadChildren: () => import('./pages/device-detail/device-detail.module').then(m => m.DeviceDetailPageModule)
},
{
path: 'settings',
loadChildren: () => import('./pages/settings/settings.module').then(m => m.SettingsPageModule)
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}<!-- Device detail page with Ionic navigation -->
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button defaultHref="/devices"></ion-back-button>
</ion-buttons>
<ion-title>{{ device.name }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-card>
<ion-card-header>
<ion-card-title>{{ device.name }}</ion-card-title>
<ion-card-subtitle>{{ device.type }}</ion-card-subtitle>
</ion-card-header>
<ion-card-content>
<ion-list>
<ion-item>
<ion-icon name="wifi-outline" slot="start"></ion-icon>
<ion-label>Signal Strength</ion-label>
<ion-note slot="end">{{ device.signalStrength }} dBm</ion-note>
</ion-item>
<ion-item>
<ion-icon name="location-outline" slot="start"></ion-icon>
<ion-label>Location</ion-label>
<ion-note slot="end">{{ device.location }}</ion-note>
</ion-item>
<ion-item>
<ion-icon name="calendar-outline" slot="start"></ion-icon>
<ion-label>Last Seen</ion-label>
<ion-note slot="end">{{ device.lastSeen | date }}</ion-note>
</ion-item>
</ion-list>
</ion-card-content>
</ion-card>
</ion-content>Output: Navigating to /devices/123 shows the device detail page with a native-style back button that returns to the device list. The page transition animation matches the platform (iOS slide-from-left or Android fade).
Capacitor vs Cordova
Ionic works with both native bridge technologies:
| Feature | Capacitor | Cordova |
|---|---|---|
| Architecture | Modern, plugin-based | Legacy, plugin-based |
| JavaScript → Native | Direct bridge | WebView injection |
| PWA support | Built-in | Manual |
| Plugin ecosystem | Growing fast | Mature, extensive |
| Modern tooling | Web-first, TypeScript | Node-based |
# Capacitor commands
ionic capacitor add ios
ionic capacitor add android
ionic capacitor copy # Copy web build to native project
ionic capacitor sync # Copy + update native dependencies
ionic capacitor open # Open native IDE
# Build and run
ionic build # Build web assets
ionic capacitor run ios --livereload # iOS with live reload
ionic capacitor run android # AndroidCapacitor Native API Example
// Using Capacitor plugins for native features
import { Plugins } from '@capacitor/core';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
import { Geolocation } from '@capacitor/geolocation';
import { Share } from '@capacitor/share';
import { LocalNotifications } from '@capacitor/local-notifications';
export class DeviceService {
async capturePhoto(): Promise<string> {
const image = await Camera.getPhoto({
quality: 90,
allowEditing: false,
resultType: CameraResultType.Uri,
source: CameraSource.Camera
});
return image.webPath!;
}
async getCurrentLocation() {
const position = await Geolocation.getCurrentPosition({
enableHighAccuracy: true,
timeout: 10000
});
return {
latitude: position.coords.latitude,
longitude: position.coords.longitude
};
}
async shareDevice(device: Device) {
await Share.share({
title: device.name,
text: `Check out ${device.name} — a ${device.type} with signal strength ${device.signalStrength} dBm`,
url: `https://dodatech.com/devices/${device.id}`,
dialogTitle: 'Share Device'
});
}
async notifyScanComplete(count: number) {
await LocalNotifications.schedule({
notifications: [{
title: 'Scan Complete',
body: `Found ${count} device(s) nearby`,
id: 1,
schedule: { at: new Date(Date.now() + 1000) },
sound: 'default'
}]
});
}
}Output: capturePhoto() opens the native camera, returns the image URI. getCurrentLocation() uses native GPS. shareDevice() triggers the OS share sheet. notifyScanComplete() posts a system notification. All APIs work identically on iOS and Android with no platform-specific code.
PWA Support
Ionic apps are PWAs by default. Deploy the same codebase as a web app:
# Build for web
ionic build --prod
# Deploy the www/ folder to any static host
npx cap syncPWAs built with Ionic include:
- Offline support via service workers
- Add-to-home-screen prompt
- Full-screen mode
- Push notifications (with Capacitor)
Common Mistakes Beginners Make
Using Cordova when Capacitor is better for new projects: Cordova is mature but Capacitor offers better performance, modern tooling, and PWA support. Use Cordova only if you need a specific legacy plugin.
Not using
ion-inputfor forms: Standard HTML inputs don’t get Ionic’s theming, touch-friendly sizing, or validation styling. Always use Ionic components (ion-input,ion-select,ion-textarea).Forgetting to handle hardware back button: Android’s hardware back button needs special handling in Ionic apps. Use
Platform.backButtonsubscription to manage custom back behavior.Overusing modals for simple interactions: Modals are heavyweight. Use
ion-popoveror inline content for simple forms and confirmations to keep navigation fluid.Not optimizing images for mobile: Large images cause slow scroll performance and high memory usage on mobile devices. Use lazy loading and compress images to appropriate resolutions.
Ignoring iOS safe areas: Notched iPhones have safe areas for the notch and home indicator. Use
ion-contentwith proper padding or CSSsafe-area-inset-*variables.
Practice Questions
- What is the difference between Capacitor and Cordova?
- How do you customize Ionic’s default colors?
- What is the purpose of
ion-back-button? - How do you deploy an Ionic app as a PWA?
- Why use Ionic components instead of standard HTML elements?
Answers:
- Capacitor is a modern native bridge with better PWA support, direct JavaScript→native communication, and a plugin system designed for TypeScript. Cordova is the older alternative with a larger but aging plugin ecosystem.
- Override CSS custom properties in
src/theme/variables.csslike--ion-color-primary,--ion-background-color, and--ion-text-color. - It provides a back button that returns to the previous page in the navigation stack, styled natively per platform.
- Run
ionic build --prodto generate thewww/folder with service worker and manifest. Deploy to any static web host. - Ionic components are touch-optimized, platform-adaptive (iOS/Material Design), accessible, and fully integrated with Ionic’s theming system.
Challenge
Build a complete inventory management app with Ionic: use tabs for navigation (Items, Scan, Settings), implement barcode scanning with Capacitor plugin, store data in local storage, support dark mode toggle, and add push notifications for low-stock alerts.
Real-World Task
Create a field service report app: capture photos with Capacitor Camera, record location with Geolocation, auto-generate PDF reports, provide offline storage with sync-on-connectivity, and deploy as both an Android app and a PWA.
FAQ
Try It Yourself
ionic start dodatech-app tabs --type=angular
cd dodatech-app
ionic serveAdd a new tab page for device scanning with ion-searchbar, display results in an ion-list with swipeable items, add a settings page with dark mode toggle that changes CSS variables, and test on a mobile device with ionic capacitor run android.
What’s Next
Related topics: Angular, JavaScript, TypeScript, Capacitor
What’s Next
Congratulations on completing this Ionic Framework tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro