Package Exports
- force-portrait-mode
- force-portrait-mode/styles/force-portrait.min.css
Readme
force-portrait-mode
A lightweight, customizable library that enforces portrait orientation on mobile devices with smooth user experience and professional animations.
✨ Features
- 🎨 Fully Customizable - Colors, icons, messages, animations, and positioning
- 📱 Mobile-First - Optimized for all mobile browsers and devices
- ⚡ Ultra-Lightweight - < 1KB gzipped, zero dependencies
- 🔧 Framework Agnostic - Works with React, Vue, Angular, vanilla JS
- 🎯 TypeScript Ready - Full type definitions included
- ♿ Accessible - Respects user motion preferences and ARIA standards
- 🌐 CSS-Only Option - Pure CSS solution available (no JavaScript required)
- 📊 Smart Positioning - Automatic overlap prevention and responsive sizing
- 🎭 Built-in Themes - Dark, light, neon, and minimal themes included
🚀 Quick Start
Installation
npm install force-portrait-mode
yarn add force-portrait-mode
Basic Usage
import { enablePortraitMode } from 'force-portrait-mode'
// Enable with default settings (40% icon, 70% text positioning)
enablePortraitMode()
// Or with custom options
enablePortraitMode({
backgroundColor: '#1a1a1a',
icon: '📲',
message: 'Please rotate your device to portrait mode',
theme: 'dark'
})
CSS-Only Usage
<!-- Include the CSS file -->
<link rel="stylesheet" href="node_modules/force-portrait-mode/styles/force-portrait.min.css">
<!-- Or use a CDN -->
<link rel="stylesheet" href="https://unpkg.com/force-portrait-mode@1.2.0/styles/force-portrait.min.css">
📖 Usage Examples
Vanilla JavaScript
import { enablePortraitMode, disablePortraitMode } from 'force-portrait-mode'
// Basic usage
const cleanup = enablePortraitMode({
backgroundColor: '#000000',
textColor: '#ffffff',
icon: '📱',
message: 'Rotate your phone for better experience'
})
// Clean up when needed
// cleanup()
React Integration
import { enablePortraitMode } from 'force-portrait-mode'
import { useEffect } from 'react'
function App() {
useEffect(() => {
const cleanup = enablePortraitMode({
backgroundColor: '#2d3748',
textColor: '#e2e8f0',
icon: '📲',
theme: 'dark'
})
return cleanup
}, [])
return (
<div className="app">
<h1>My Mobile App</h1>
<p>Content optimized for portrait mode</p>
</div>
)
}
Vue 3 Integration
<script setup>
import { enablePortraitMode } from 'force-portrait-mode'
import { onMounted, onUnmounted } from 'vue'
let cleanup = null
onMounted(() => {
cleanup = enablePortraitMode({
backgroundColor: '#1a1a1a',
icon: '🎮',
message: 'Game works best in portrait mode',
animation: {
type: 'bounce',
duration: '1.5s'
}
})
})
onUnmounted(() => {
if (cleanup) cleanup()
})
</script>
<template>
<div class="game-app">
<h1>Mobile Game</h1>
<!-- Your game content -->
</div>
</template>
TypeScript
import {
enablePortraitMode,
PortraitModeOptions,
ThemePreset
} from 'force-portrait-mode'
const config: PortraitModeOptions = {
backgroundColor: '#1a1a1a',
textColor: '#ffffff',
icon: '📱',
iconSize: '4rem',
fontSize: '1.2rem',
iconPosition: { top: '35%' },
textPosition: { top: '65%' },
animation: {
enabled: true,
type: 'rotate',
duration: '2s'
},
onShow: () => console.log('Portrait mode activated'),
onHide: () => console.log('Portrait mode deactivated')
}
const result = enablePortraitMode(config)
console.log('Layout adjusted:', result.layout.adjusted)
🎨 Customization Options
Basic Configuration
enablePortraitMode({
// Visual customization
backgroundColor: '#000000', // Background color
textColor: '#ffffff', // Text color
icon: '📱', // Icon/emoji to display
iconColor: '#4CAF50', // Icon color (optional)
message: 'Custom message', // Text message
// Typography
fontFamily: 'Arial, sans-serif',
fontSize: '1.2rem', // Responsive: { min: '0.9rem', max: '1.2rem', viewport: '4vw' }
fontWeight: '600',
iconSize: '4rem', // Responsive sizing supported
// Positioning (default: icon 40%, text 70%)
iconPosition: { top: '40%', left: '50%' },
textPosition: { top: '70%', left: '50%' },
// Animation
animation: {
enabled: true,
type: 'rotate', // 'rotate', 'bounce', 'pulse', 'shake'
duration: '2s',
rotationAngle: 15
}
})
Advanced Configuration
enablePortraitMode({
// Layout control
layout: {
preventOverlap: true, // Automatic overlap prevention
responsive: true, // Responsive sizing
minSpacing: '2rem', // Minimum space between elements
fallbackLayout: 'vertical-stack'
},
// Text handling
textHandling: {
maxWidth: '90vw', // Prevent text overflow
truncate: true, // Add ellipsis for long text
multiLine: false, // Force single line
breakWords: false // Prevent word breaking
},
// Behavior
zIndex: 9999, // CSS z-index
overlay: true, // Show background overlay
blur: false, // Backdrop blur effect
hideScrollbar: true, // Hide scrollbars in landscape
preventScroll: true, // Prevent scrolling
// Accessibility
ariaLabel: 'Rotate device', // Screen reader label
respectPrefers: true, // Respect prefers-reduced-motion
// Callbacks
onShow: () => console.log('Landscape detected'),
onHide: () => console.log('Portrait restored')
})
🎭 Built-in Themes
Using Preset Themes
// Dark theme (default)
enablePortraitMode({ theme: 'dark' })
// Light theme
enablePortraitMode({ theme: 'light' })
// Neon theme
enablePortraitMode({ theme: 'neon' })
// Minimal theme
enablePortraitMode({ theme: 'minimal' })
Custom Themes
// Custom theme object
enablePortraitMode({
theme: {
backgroundColor: '#ff6b6b',
textColor: 'white',
icon: '⚡',
iconColor: '#ffd93d',
animation: 'bounce'
}
})
CSS-Only Themes
/* Apply theme class to body */
body.force-portrait-theme-neon {
--portrait-bg-color: rgba(0, 0, 0, 0.9);
--portrait-text-color: #00ff88;
--portrait-icon-color: #ff0080;
--portrait-icon: '📲';
}
🔧 API Reference
Functions
enablePortraitMode(options?)
Enables portrait mode enforcement with optional configuration.
Parameters:
options
(optional):PortraitModeOptions
- Configuration object
Returns:
PortraitModeResult
- Object with cleanup function and layout info
disablePortraitMode()
Disables portrait mode enforcement and cleans up resources.
updatePortraitMode(options)
Updates current portrait mode configuration dynamically.
getPortraitModeState()
Returns current state information.
CSS-Only Usage
Include the CSS file and optionally customize with CSS custom properties:
:root {
--portrait-bg-color: rgba(0, 0, 0, 0.9);
--portrait-text-color: #ffffff;
--portrait-icon: '📱';
--portrait-message: 'Please rotate your device';
--portrait-icon-top: 40%; /* Icon position */
--portrait-text-top: 70%; /* Text position */
}
🌍 Browser Compatibility
- ✅ iOS Safari - Full support
- ✅ Android Chrome - Full support
- ✅ Android Firefox - Full support
- ✅ WebView containers (Telegram WebApp, etc.)
- ✅ Progressive Web Apps (PWA)
- ✅ All modern mobile browsers
📱 Framework Integration
Installation
npm install force-portrait-mode
The library provides a framework-agnostic core that works with any JavaScript framework. Simply import the core functions and integrate them into your framework's lifecycle methods as shown in the examples above.
🎯 Default Positioning
The library uses optimized default positioning for mobile devices:
- Icon: 40% from top (optimal visibility)
- Text: 70% from top (comfortable reading position)
- Automatic adjustment for small screens to prevent overlap
⚡ Performance
- Ultra-Lightweight: < 1KB gzipped (21KB core)
- Zero dependencies: No external libraries required
- Optimized build: Tree-shaken with aggressive compression
- CSS-only option: Pure CSS solution available
- GPU accelerated: Smooth animations using transform
- Memory efficient: Automatic cleanup and resource management
🔒 Security
- No external dependencies
- No data collection or analytics
- No network requests
- CSP (Content Security Policy) friendly
- Open source and auditable
🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
git clone https://github.com/sai-na/force-portrait-mode.git
cd force-portrait-mode
npm install
npm run dev
Running Tests
npm test # Run tests
npm run test:watch # Watch mode
npm run test:coverage # With coverage
📄 License
MIT © SAI NATH
🔗 Links
Made with ❤️ for mobile-first web development