CSS Variables & Defaults
SDK-injected CSS resets, variables for safe areas, screen dimensions, and color scheme.
SDK Defaults#
The SDK automatically applies sensible defaults to every flow so you can focus on your design instead of boilerplate.
Viewport
The SDK ensures viewport-fit=cover is present on your viewport meta tag. This enables edge-to-edge rendering on iOS so your backgrounds extend behind the notch and home indicator. You don't need to add it yourself — if it's missing, the SDK appends it automatically.
CSS Resets
Base CSS resets are injected before your flow CSS. You do not need to include a CSS reset — it's already applied.
/* SDK base resets (auto-injected BEFORE your flow CSS) */
/* You do NOT need to include these — they are already applied */
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
body {
-webkit-font-smoothing: antialiased;
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
overflow: hidden;
}| What it does | Why |
|---|---|
margin: 0; padding: 0 on * | Removes all browser-default spacing for consistent rendering across devices |
box-sizing: border-box on * | Padding and borders are included in element dimensions |
-webkit-tap-highlight-color: transparent | Removes the blue/gray flash on tap in iOS and Android WebViews |
-webkit-font-smoothing: antialiased | Crisp text rendering on WebKit-based browsers |
user-select: none | Prevents text selection for a native-app feel |
-webkit-touch-callout: none | Prevents long-press context menus on links and images |
overflow: hidden on body | Prevents body scroll — use scroll containers for scrollable content |
Since the resets are injected before your flow CSS, you can override any of them. For example, use user-select: text on a specific element to allow text selection, or overflow-y: auto on a scroll container.
Overriding Defaults#
All SDK defaults can be overridden in your flow CSS since it loads after the reset stylesheet.
/* Allow text selection in a specific area */
.article-body {
-webkit-user-select: text;
user-select: text;
}
/* Enable scrolling in a content container */
.scrollable-content {
overflow-y: auto;
height: 100vh;
-webkit-overflow-scrolling: touch;
}
/* Re-enable touch callout for links */
.external-links a {
-webkit-touch-callout: default;
}Available Variables#
/* CSS Variables injected by the bridge (AFTER your flow CSS) */
:root {
/* Safe area insets (for notches, home indicators) */
--safe-area-top: 47px;
--safe-area-right: 0px;
--safe-area-bottom: 34px;
--safe-area-left: 0px;
/* Screen dimensions */
--screen-width: 393px;
--screen-height: 852px;
/* Color scheme */
--color-scheme: light; /* or 'dark' */
color-scheme: light; /* enables light-dark() CSS function */
}| Variable | Description | Example Value |
|---|---|---|
--safe-area-top | Top inset (status bar, notch, Dynamic Island) | 47px |
--safe-area-bottom | Bottom inset (home indicator) | 34px |
--safe-area-left | Left inset (usually 0) | 0px |
--safe-area-right | Right inset (usually 0) | 0px |
--screen-width | Full screen width in points | 393px |
--screen-height | Full screen height in points | 852px |
--color-scheme | Device color scheme | light / dark |
Safe Area Usage#
Use safe area variables to ensure your content doesn't get hidden behind notches, Dynamic Island, or home indicators.
/* Apply safe area padding to container */
.flow-container {
padding-top: var(--safe-area-top);
padding-bottom: var(--safe-area-bottom);
padding-left: var(--safe-area-left);
padding-right: var(--safe-area-right);
min-height: 100vh;
}
/* Fixed header that respects notch */
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
padding-top: calc(var(--safe-area-top) + 16px);
padding-left: calc(var(--safe-area-left) + 16px);
padding-right: calc(var(--safe-area-right) + 16px);
}
/* Fixed bottom button that respects home indicator */
.bottom-button {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 16px;
padding-bottom: calc(var(--safe-area-bottom) + 16px);
}Use calc() to add extra padding beyond the safe area. For example, calc(var(--safe-area-bottom) + 16px).
Color Scheme / Dark Mode#
Support light and dark mode in your flows using the color scheme variables.
/* Method 1: Use CSS color-scheme property */
body {
color-scheme: var(--color-scheme);
}
/* Method 2: Use media query */
@media (prefers-color-scheme: dark) {
body {
background: #1a1a1a;
color: #ffffff;
}
}
/* Method 3: Use light-dark() function (modern browsers) */
body {
background: light-dark(#ffffff, #1a1a1a);
color: light-dark(#1a1a1a, #ffffff);
}
/* Method 4: Use CSS variable for manual control */
body {
--bg-color: #ffffff;
--text-color: #1a1a1a;
background: var(--bg-color);
color: var(--text-color);
}
body[data-theme="dark"] {
--bg-color: #1a1a1a;
--text-color: #ffffff;
}The color-scheme property is set on :root, which enables the CSS light-dark() function and proper form control styling.
Responsive Layouts#
Use screen dimension variables for responsive layouts based on actual device size.
/* Use screen dimensions for responsive layouts */
.hero-image {
width: 100%;
max-width: var(--screen-width);
height: calc(var(--screen-height) * 0.4);
object-fit: cover;
}
/* Full-screen background */
.full-screen {
width: var(--screen-width);
height: var(--screen-height);
position: fixed;
top: 0;
left: 0;
}Complete Example#
A complete flow HTML with proper safe area handling and dark mode support:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* No CSS reset or viewport-fit needed — the SDK applies them automatically */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: light-dark(#ffffff, #1a1a1a);
color: light-dark(#1a1a1a, #ffffff);
min-height: 100vh;
display: flex;
flex-direction: column;
}
.container {
flex: 1;
display: flex;
flex-direction: column;
padding: 24px;
padding-top: calc(24px + var(--safe-area-top));
padding-bottom: calc(24px + var(--safe-area-bottom));
padding-left: max(var(--safe-area-left), 20px);
padding-right: max(var(--safe-area-right), 20px);
}
.content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.bottom-actions {
padding-bottom: 20px;
}
.button {
width: 100%;
padding: 16px;
border-radius: 12px;
border: none;
font-size: 16px;
font-weight: 600;
cursor: pointer;
}
.button-primary {
background: light-dark(#007AFF, #0A84FF);
color: white;
}
</style>
</head>
<body>
<div class="container">
<div class="content">
<h1>Welcome!</h1>
<p>Your content here</p>
</div>
<div class="bottom-actions">
<button class="button button-primary" id="continue">
Continue
</button>
</div>
</div>
<script>
document.getElementById('continue').addEventListener('click', () => {
Mobana.haptic('success');
Mobana.complete();
});
</script>
</body>
</html>CSS vs JavaScript#
While you can also access these values via JavaScript (getSafeArea(), getColorScheme()), CSS variables are preferred for layout:
- No JavaScript needed: Layout works immediately without waiting for JS to run.
- Declarative: CSS is designed for layout; use it.
- Performance: CSS variables are optimized by the browser.
Use JavaScript APIs when you need the values for logic (e.g., conditionals, calculations for canvas drawing).