In diesem Tutorial beginnen wir mit einer neuen Angular App und wechseln in die Welt der nativen Mobile-Apps mit Capacitor. Du kannst auch Capgo Native Navigation and Transitions für ein natives Mobile-Feeling hinzufügen und tailwind-capacitor für Safe Areas nutzen.
Capacitor ermöglicht es dir, deine Angular-Webanwendung einfach in eine native Mobile-App umzuwandeln, ohne große Änderungen vornehmen oder neue Skills wie React Native lernen zu müssen.
Mit nur wenigen einfachen Schritten lassen sich die meisten Angular-Anwendungen in mobile Apps verwandeln.
Dieses Tutorial führt dich durch den Prozess: Wir starten mit einer neuen Angular-App und integrieren dann Capacitor, um in die Welt der nativen mobilen Apps einzutauchen. Du kannst außerdem Capgo Native Navigation, Transitions und tailwind-capacitor für Safe Areas nutzen.
Über Capacitor
CapacitorJS ist ein echter Game-Changer! Du kannst es mühelos in jedes Web-Projekt integrieren; es verpackt deine Anwendung in eine native WebView und erstellt die nativen Xcode- und Android Studio-Projekte für dich. Außerdem bieten die Plugins über eine JS-Bridge Zugriff auf native Gerätefunktionen wie die Kamera.
Mit Capacitor erhältst du eine fantastische native mobile App, ganz ohne kompliziertes Setup oder steile Lernkurve. Die schlanke API und die optimierte Funktionalität machen die Integration in dein Projekt zum Kinderspiel. Glaub mir, du wirst staunen, wie einfach es ist, mit Capacitor eine voll funktionsfähige native App zu bauen!
Deine Angular-App vorbereiten
Um eine neue Angular-App zu erstellen, führe diesen Befehl aus:
ng new my-app
cd my-app
Wähle „Angular“, wenn du nach der Angular-Version gefragt wirst.
Um eine native mobile App zu erstellen, benötigen wir einen Export unseres Projekts. Also fügen wir ein einfaches Script in unsere package.json- mit denen sich das Angular-Projekt bauen und kopieren lässt:
{
"scripts": {
// ...
"build": "ng build --prod"
}
}
Nachdem du den Befehl ausgeführt hast build, sollten Sie eine frische dist Ordner im Projektstamm finden.
Dieser Ordner wird später von Capacitor verwendet, aber fürs Erste müssen wir ihn korrekt einrichten.
Capacitor in deine Angular App einbinden
Um eine Web-App in einen nativen Mobile-Container zu verpacken, sind ein paar erste Schritte nötig, danach reicht ein einziger sync Befehl.
Zunächst können wir das installieren Capacitor CLI als Dev-Dependency installieren und dann in unserem Projekt einrichten. Während des Setups kannst du „Enter“ drücken, um die Standardwerte für Name und Bundle ID zu übernehmen.
Als Nächstes müssen wir das Core-Package und die relevanten Packages für iOS und Android installieren.
Schließlich können wir die Plattformen hinzufügen, und Capacitor erstellt für jede Plattform einen Ordner im Wurzelverzeichnis unseres Projekts:
# Install the Capacitor CLI locally
npm install -D @capacitor/cli
# Initialize Capacitor in your Angular project
npx cap init
# Install the required packages
npm install @capacitor/core @capacitor/ios @capacitor/android
# Add the native platforms
npx cap add ios
npx cap add android
An diesem Punkt solltest du in der Lage sein, neue iOS und Android Ordner in deinem Angular-Projekt sehen können.
Das sind echte native Projekte!
Um später auf das Android-Projekt zuzugreifen, musst du Android Studioinstallieren. Für iOS brauchst du einen Mac und solltest Xcode.
installieren. Außerdem solltest du einen capacitor.config.ts Datei in deinem Projekt, die einige grundlegende Capacitor-Einstellungen enthält, die während des Syncs verwendet werden. Das Einzige, worauf du achten musst, ist die webDir, das auf das Ergebnis deines Build-Befehls zeigen muss. Aktuell ist es nicht korrekt.
Um das zu korrigieren, öffne die capacitor.config.json -Datei und aktualisiere das webDir:
{
"appId": "com.example.app",
"appName": "my-app",
"webDir": "dist"
}
Du kannst es ausprobieren, indem du die folgenden Befehle ausführst:
npm run build
npx cap sync
Der erste Befehl npm run build baut lediglich dein Angular-Projekt und kopiert den statischen Build, während der zweite Befehl npx cap sync alle Web-code an die richtigen Stellen der nativen Plattformen synchronisiert, damit sie in einer App angezeigt werden können.
Außerdem kann der sync-Befehl die nativen Plattformen aktualisieren und Plugins installieren, daher, wenn du eine neue Capacitor Plugins Es ist Zeit zu starten npx cap sync erneut aus.
Ohne es zu merken, bist du nun fertig – schauen wir uns die App also mal auf einem Gerät an!
Native Apps bauen und deployen
Um iOS-Apps zu entwickeln, musst du Xcode installiert haben, und für Android-Apps benötigst du Android Studio installiert. Außerdem musst du dich, wenn du deine App im App Store verteilen willst, für das Apple Developer Program für iOS und die Google Play Console für Android anmelden.
Wenn du neu in der nativen Mobile-Entwicklung bist, kannst du das Capacitor CLI nutzen, um beide nativen Projekte ganz einfach zu öffnen:
npx cap open ios
npx cap open android
Sobald deine nativen Projekte eingerichtet sind, ist das Deployment auf ein verbundenes Gerät kinderleicht. In Android Studio musst du nur warten, bis alles bereit ist, und kannst deine App ohne weitere Einstellungen auf ein verbundenes Gerät deployen. Hier ein Beispiel:

In Xcode musst du deinen Signing-Account einrichten, um deine App auf einem echten Gerät statt nur im Simulator zu deployen. Falls du das noch nie gemacht hast, führt dich Xcode durch den Prozess (aber auch hier musst du im Developer Program registriert sein). Danach kannst du einfach auf Play klicken, um die App auf deinem verbundenen Gerät auszuführen, das du oben auswählen kannst. Hier ein Beispiel:

Glückwunsch! Du hast deine Angular-Web-App erfolgreich auf einem mobilen Gerät deployed. Hier ein Beispiel:
Aber Moment, es gibt während der Entwicklung auch einen noch schnelleren Weg…
Capacitor Live Reload
Mittlerweile bist du wahrscheinlich an Hot Reload bei allen modernen Frameworks gewöhnt, und die gute Nachricht ist: Du kannst dieselbe Funktionalität auf einem mobilen Gerät mit minimalem Aufwand nutzen!
Aktiviere den Zugriff auf deine lokal gehostete App mit Live Reload in deinem Netzwerk indem die Capacitor App den Inhalt von der spezifischen URL lädt.
Der erste Schritt ist es, deine lokale IP-Adresse herauszufinden. Wenn du einen Mac nutzt, kannst du dies mit folgendem Befehl im Terminal ermitteln:
ipconfig getifaddr en0
Unter Windows führe aus:
ipconfig
Suche dann nach der IPv4-Adresse.
Wir können Capacitor anweisen, die App direkt vom Server zu laden, indem wir einen weiteren Eintrag in unsere capacitor.config.ts Datei:
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'my-app',
webDir: 'dist',
bundledWebRuntime: false,
server: {
url: 'http://192.168.x.xx:4200',
cleartext: true
}
};
export default config;
Achte darauf, die richtige IP und den Port zu verwenden, in diesem Beispiel habe ich den Standard-Angular-Port genutzt.
Jetzt können wir diese Änderungen anwenden, indem wir sie in unser natives Projekt kopieren:
npx cap copy
Der copy Der Befehl ähnelt sync, aber es wird nur Änderungen im Web-Ordner übernehmen und die Konfiguration, ohne das native Projekt zu aktualisieren.
Du kannst deine App jetzt noch einmal über Android Studio oder Xcode deployen. Wenn du danach etwas in deiner Angular-App änderst, lädt die App automatisch neu und die Änderungen anzeigen!
Zu beachten dass die Installation neuer Plugins wie der Kamera weiterhin einen Rebuild deines nativen Projekts erfordert. Das liegt daran, dass native Dateien geändert werden und dies nicht auf dem Fly möglich ist.
Achte darauf, in deiner Konfiguration die korrekte IP und den richtigen Port zu verwenden. Der code-Block oben zeigt den Standard-Port von Angular zu Demonstrationszwecken.
Capacitor Plugins verwenden
Schauen wir uns an, wie man ein Capacitor-Plugin in Aktion verwendet, auf das wir bereits mehrfach eingegangen sind. Dazu können wir ein ziemlich einfaches Plugin installieren, indem wir ausführen:
npm i @capacitor/share
Es gibt nichts Besonderes am Share-Plugin, aber es öffnet trotzdem den nativen Share-Dialog! Dafür müssen wir jetzt nur noch das Package importieren und die entsprechende Funktion aufrufen: share() Funktion aus unserer App aufrufen, also ändern wir die src/app/app.component.ts wie folgt:
import { Component } from '@angular/core';
import { Share } from '@capacitor/share';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'my-app';
async share() {
await Share.share({
title: 'Open Youtube',
text: 'Check new video on youtube',
url: 'https://www.youtube.com',
dialogTitle: 'Share with friends'
});
}
}
Wie bereits erwähnt, müssen wir nach der Installation neuer Plugins einen Sync durchführen und die App anschließend neu auf das Gerät deployen. Nutze dazu diesen Befehl:
npx cap sync
Nach dem Klick auf den Button siehst du den nativen Share-Dialog in Aktion!
Als Nächstes kannst du die App auf iOS und Android mit Capgo Navigation und Transitions nativer wirken lassen und typische iOS-Layoutprobleme beheben, die horizontalen Overflow oder abgeschnittene Safe Areas verursachen.
Native-Feeling-UI mit Capgo Native Navigation und Transitions
Ich arbeite schon seit Jahren mit Ionic um plattformübergreifende Apps zu bauen, aber die Integration mit Angular ist hacky und selten die Mühe wert, wenn man bereits Tailwind CSS.
Für ein natives Mobile-Feeling in einer Angular + Capacitor App solltest du Capgo Plugins statt reiner Web-UI-Kits wie Konsta UI nutzen:
- @capgo/capacitor-native-navigation — native Navbar, Liquid Glass Tab Bar auf iOS und ein Blur-Effekt für die Tab Bar auf Android. Dein Angular Router verwaltet den Route-State; das Plugin übernimmt das native Chrome.
- @capgo/capacitor-transitions — Page Transitions im Ionic-Stil und iOS Edge Swipe-Back in der WebView-Ebene, ohne das Ionic UI zu übernehmen.
Beides installieren:
bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync
Konfiguriere die native Navigation mit dem CSS Inset Mode, damit Web-Content die nativen Bars berücksichtigt:
import { NativeNavigation } from '@capgo/capacitor-native-navigation';
await NativeNavigation.configure({
contentInsetMode: 'css',
animationDuration: 360,
glass: {
effect: 'liquidGlass',
},
});
Rendere eine Liquid Glass Tab Bar (iOS nutzt systemeigenes Rendering; Android nutzt einen geblurrten WebView-Hintergrund):
import { inject } from '@angular/core';
import { Router } from '@angular/router';
const router = inject(Router);
await NativeNavigation.setTabbar({
selectedId: 'home',
labelVisibilityMode: 'labeled',
icons: true,
colors: { dynamic: true },
tabs: [
{ id: 'home', title: 'Home', icon: { svg: '...' } },
{ id: 'settings', title: 'Settings', icon: { svg: '...' } },
],
});
await NativeNavigation.addListener('tabSelect', ({ id }) => {
router.navigate([`/${id}`]);
});
Add native page transitions in your app shell:
```typescript
// app.component.ts
import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { Router } from '@angular/router';
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions';
initTransitions({ platform: 'auto' });
@Component({
selector: 'app-root',
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<cap-router-outlet #outlet platform="auto" swipe-gesture="auto">
<router-outlet></router-outlet>
</cap-router-outlet>
`,
})
export class AppComponent implements AfterViewInit {
@ViewChild('outlet') outlet?: ElementRef<HTMLElement>;
constructor(private router: Router) {}
ngAfterViewInit() {
if (this.outlet?.nativeElement) {
setupRouterOutlet(this.outlet.nativeElement, { platform: 'auto', swipeGesture: 'auto' });
}
}
openSettings() {
setDirection('forward');
this.router.navigate(['/settings']);
}
}
Umschließe geroutete Seiten mit cap-router-outlet, cap-page, und cap-content, und rufe setDirection('forward') oder setDirection('back') bevor du navigierst. Dupliziere keine Web-Header oder -Footer, wenn die native Navigation diese Bereiche bereits übernimmt.
Hier findest du die vollständigen Guides: Verwendung von @capgo/capacitor-native-navigation und Verwendung von @capgo/capacitor-transitions.
Safe Areas mit Tailwind
Für Safe Areas von Geräten in Tailwind CSS verwende @capgo/tailwind-capacitor (veröffentlicht als tailwind-capacitor auf npm). Es bietet safe-areas Utilities und andere Capacitor-freundliche Tailwind-Plugins:
bun add -D tailwind-capacitor
Unter src/styles.css:
@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";
Nutze Utilities wie pt-safe, pb-safe, und px-safe anstatt alles manuell env(safe-area-inset-*) einzufügen. Das Projekt wird aktiv entwickelt – falls etwas für dein Angular-Setup fehlt, eröffne einen PR auf GitHub.
iOS-Layoutprobleme beheben (Viewport, Safe Area und horizontaler Overflow)
Wenn Inhalte auf iOS abgeschnitten, verschoben oder horizontal scrollbar wirken, hilft es meist nicht, mehr overflow-x: hidden hinzuzufügen oder nur das Viewport-Tag zu ändern. Gehe diese Checks der Reihe nach durch.
Stelle sicher, dass das Viewport-Meta-Tag korrekt angewendet wird
Unter src/index.html, setze das Viewport-Meta-Tag in <head>:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
iOS Safe Area nur von einem Root-Wrapper aus handhaben
Erstelle eine einzige App-Shell und wende dort das Safe-Area-Padding an – nicht in mehreren verschachtelten Komponenten:
html,
body,
app-root {
width: 100%;
min-height: 100%;
margin: 0;
padding: 0;
overflow-x: hidden;
}
* {
box-sizing: border-box;
}
.app-shell {
min-height: 100dvh;
width: 100%;
padding-top: env(safe-area-inset-top);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
}
Umschließe den gesamten Seiteninhalt mit .app-shellDoppeltes Safe-Area-Padding in Headern, Modals und Layout-Wrappern lässt das UI oft abgeschnitten oder zu groß wirken.
Mit @capgo/tailwind-capacitor, kannst du dasselbe Padding mit Utilities wie pt-safe pb-safe px-safe in dieser einen Shell ausdrücken.
Setze Capacitor iOS contentInset zu never zuerst
Unter capacitor.config.ts, deaktiviere lieber native Insets und überlasse CSS (oder der Native Navigation contentInsetMode: 'css') die Safe Area:
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'www',
ios: {
contentInset: 'never',
},
};
Kombination von Capacitor’s automatischen Content Insets mit CSS env(safe-area-inset-*) Padding ist eine häufige Ursache für doppelte Abstände.
Das tatsächlich überlaufende Element finden
Der übliche Übeltäter ist ein Element mit 100vw, Tailwind w-screen, einer festen Pixelbreite oder einem großen min-width.
Im Safari Web Inspector ausführen:
[...document.querySelectorAll('*')]
.filter(el => el.scrollWidth > document.documentElement.clientWidth)
.map(el => ({
el,
tag: el.tagName,
class: el.className,
scrollWidth: el.scrollWidth,
clientWidth: document.documentElement.clientWidth,
}));
Mit Tailwind ersetzen w-screen mit w-full wann immer möglich. Viele Probleme mit horizontalem Overflow entstehen durch 100vw / w-screen, doppeltes Safe-Area-Padding oder einen Container mit fester Breite – nicht durch das Viewport-Meta-Tag selbst.
Fazit
Capacitor ist eine hervorragende Option, um native Apps auf Basis eines bestehenden Webprojekts zu bauen, da es einen einfachen Weg bietet, code zu teilen und ein konsistentes UI zu pflegen.
Und mit der Ergänzung von Capgo, wird es noch einfacher, Live Updates in deine App einzubinden, damit deine Nutzer immer Zugriff auf die neuesten Features und Bugfixes haben.
Wenn du lernen möchtest, wie du Capgo in deine Angular-App einbindest, schau dir den nächsten Artikel an:
Weiterlesen: Mobile Apps mit Angular und Capacitor bauen
Wenn du es nutzt Mobile Apps mit Angular und Capacitor bauen , um natives Media- und Interface-Verhalten zu planen, verbinde es mit @capgo/capacitor-live-activities verwenden für die native Funktion in „@capgo/capacitor-live-activities verwenden“, @capgo/capacitor-live-activities für die Implementierungsdetails in @capgo/capacitor-live-activities, Verwendung von @capgo/capacitor-video-player für die native Funktion bei Verwendung von @capgo/capacitor-video-player, @capgo/capacitor-video-player für die Implementierungsdetails in @capgo/capacitor-video-player und Verwendung von @capgo/capacitor-native-navigation für die native Funktion bei Verwendung von @capgo/capacitor-native-navigation.