Reduce Motion — fungsi accessibility sistem operasi dan browser yang menonaktifkan atau mengurangi animasi antarmuka untuk mencegah ketidaknyamanan pada pengguna dengan gangguan vestibular. Di iOS pengaturan tersebut berada di Settings > Accessibility > Motion > Reduce Motion dan menonaktifkan paralaks, animasi transisi antar layar, dan efek ikon. Di Android opsi serupa "Hapus animasi" terletak di Pengaturan > Aksesibilitas. Menurut data W3C WCAG 2.2, animasi berlebihan dapat menyebabkan mual, pusing, dan migrain pada 15–35% orang dengan gangguan vestibular.
Poin utama
Reduce Motion — pengaturan sistem yang memerintahkan sistem operasi, browser, dan aplikasi untuk meminimalkan atau menonaktifkan sepenuhnya animasi, gerakan, penskalaan, dan efek paralaks. Fungsi ini ditujukan untuk orang dengan gangguan vestibular, di mana elemen antarmuka yang bergerak menyebabkan mual, pusing, disorientasi, dan migrain.
Sistem vestibular telinga bagian dalam bertanggung jawab atas rasa keseimbangan dan orientasi dalam ruang. Ketika mata melihat gerakan di layar, tetapi alat vestibular tidak merasakan pergerakan tubuh yang sesuai, terjadi konflik sensorik. Konflik ini memicu reaksi vegetatif: mual, keringat dingin, pusing. Menurut Vestibular Disorders Association, sekitar 35% orang berusia di atas 40 tahun mengalami ketidaknyamanan akibat efek gerakan dalam antarmuka.
Perbedaan utama Reduce Motion dari sekadar menonaktifkan animasi — tingkat sistem. Pengaturan yang diaktifkan diteruskan ke semua aplikasi dan situs web melalui API sistem operasi atau fungsi media CSS prefers-reduced-motion. Pengembang tidak perlu menebak apakah pengguna menginginkan animasi — sistem memberi tahu. Ini adalah bagian dari pendekatan progressive enhancement: animasi adalah peningkatan, bukan elemen wajib.
Reduce Motion memengaruhi efek paralaks (pergeseran latar belakang saat memiringkan perangkat), animasi transisi antar layar (push, slide, fade), penskalaan ikon saat ditekan, efek pesan (gelembung SMS), animasi pemuatan (spinner, skeleton, progress bar animation), paralaks dalam game, dan efek parallax scrolling web. Gambar statis dan video tidak terpengaruh.
| Jenis animasi | iOS Reduce Motion | Android Remove Animation | CSS prefers-reduced-motion |
|---|---|---|---|
| Paralaks wallpaper | Menonaktifkan | Menonaktifkan | T/A |
| Transisi antar layar | Mengganti dengan fade | Menonaktifkan | CSS transitions |
| Animasi ikon | Menonaktifkan | Tidak memengaruhi | CSS animations |
| Spinner pemuatan | Tidak memengaruhi | Menonaktifkan | CSS animations |
| Layar skeleton | Tidak memengaruhi | Mengganti dengan static | CSS animations |
Audien utama Reduce Motion — orang dengan gangguan vestibular (penyakit Meniere, labirintitis, BPPV), migrain (terutama dengan aura), kinetosis (mabuk perjalanan), dan beberapa bentuk epilepsi. Fungsi ini juga berguna untuk pengguna lanjut usia — perubahan terkait usia pada alat vestibular meningkatkan sensitivitas terhadap gerakan, dan untuk pengguna dengan ADHD — elemen bergerak mengganggu konsentrasi membaca.
Di iOS Reduce Motion berada di Settings > Accessibility > Motion dan mencakup tiga opsi: Reduce Motion (sakelar utama), Auto-Play Message Effects (pemutaran otomatis efek iMessage), dan Auto-Play Video Previews (pratinjau video otomatis di App Store). Reduce Motion adalah yang paling kuat: menonaktifkan paralaks wallpaper, animasi pembukaan aplikasi (zoom), transisi antar layar (push diganti dengan cross-fade), dan efek ikon di layar utama.
Secara teknis iOS mengimplementasikan Reduce Motion di tingkat UIKit melalui UIView animations dan UIViewControllerAnimatedTransitioning. Saat pengaturan aktif, UIView.animate dengan durasi > 0 dikurangi menjadi 0,01 detik, dan UIViewController.transitionDuration mengembalikan 0. Untuk paralaks, iOS menonaktifkan UIInterpolatingMotionEffect pada UIWindow. Pengembang dapat memeriksa status melalui UIAccessibility.isReduceMotionEnabled.
Pengembang dapat menyesuaikan animasi di iOS dengan Reduce Motion: mengganti transisi kompleks dengan efek fade, menonaktifkan paralaks di komponen UI kustom, dan memperpendek durasi animasi. SwiftUI menyediakan modifier khusus .animation(nil) saat reduceMotion aktif.
import UIKit
class MotionManager {
// Memeriksa status Reduce Motion
static var isReduceMotionEnabled: Bool {
return UIAccessibility.isReduceMotionEnabled
}
// Animasi aman dengan mempertimbangkan Reduce Motion
static func animate(
duration: TimeInterval,
delay: TimeInterval = 0,
options: UIView.AnimationOptions = [],
animations: @escaping () -> Void,
completion: ((Bool) -> Void)? = nil
) {
let adjustedDuration = isReduceMotionEnabled
? 0.01
: max(duration, 0.01)
UIView.animate(
withDuration: adjustedDuration,
delay: delay,
options: options,
animations: animations,
completion: completion
)
}
}
// SwiftUI — pengubah untuk Reduce Motion
import SwiftUI
struct MotionAwareView: View {
@Environment(\.accessibilityReduceMotion)
private var reduceMotion
@State private var isAnimating = false
var body: some View {
Circle()
.scaleEffect(isAnimating ? 1.2 : 1.0)
.animation(
reduceMotion
? nil
: .easeInOut(duration: 1.0).repeatForever(),
value: isAnimating
)
.onAppear { isAnimating = true }
}
}
// Berlangganan perubahan Reduce Motion
NotificationCenter.default.addObserver(
self,
selector: #selector(motionStatusChanged),
name: UIAccessibility.reduceMotionStatusDidChangeNotification,
object: nil
)Kelas MotionManager memeriksa isReduceMotionEnabled dan menyesuaikan durasi animasi: saat Reduce Motion aktif, durasi dikurangi menjadi 0,01 detik (praktis instan). Modifier SwiftUI .animation(nil) sepenuhnya menonaktifkan animasi saat reduceMotion == true. Berlangganan ke reduceMotionStatusDidChangeNotification memungkinkan peralihan animasi secara dinamis tanpa memuat ulang aplikasi.
Opsi terpisah iOS — Auto-Play Message Effects — mengontrol pemutaran efek di iMessage: animasi balon, konfeti, laser, dan kembang api. Saat Reduce Motion aktif, efek iMessage otomatis dinonaktifkan. Pengembang dapat memeriksa opsi ini melalui UIAccessibility.isReduceMotionEnabled — tidak ada API terpisah untuk Message Effects, mereka terikat pada pengaturan umum.
Di Android pengaturan "Hapus animasi" terletak di dua tempat: Pengaturan > Aksesibilitas > Hapus animasi (untuk pengaturan aksesibilitas) dan Opsi Pengembang > Skala animasi (untuk pengembang). Versi aksesibilitas menonaktifkan semua animasi sistem, termasuk transisi antar layar, animasi pembukaan aplikasi, dan efek pemuatan. Opsi Pengembang memungkinkan mengurangi skala menjadi 0,5x, 0,1x, atau menonaktifkan sepenuhnya.
Secara teknis Android mengimplementasikan penonaktifan animasi melalui properti sistem: window_animation_scale, transition_animation_scale, dan animator_duration_scale. Pada pengaturan aksesibilitas, ketiganya mendapat nilai 0. Peluncur sistem dan aplikasi sistem memeriksa nilai-nilai ini. Untuk aplikasi pihak ketiga, Android merekomendasikan penggunaan Jetpack Compose dan View system, yang secara otomatis membaca pengaturan sistem melalui AnimationScaleObserver.
Pengembang dapat memeriksa status animasi di Android melalui Settings.Global dan menyesuaikan UI. Jetpack Compose menyediakan AnimationScaleObserver untuk penyesuaian otomatis. Nilai kunci — animator_duration_scale: jika 0, animasi dinonaktifkan sepenuhnya.
import android.content.Context
import android.provider.Settings
import android.database.ContentObserver
import android.os.Handler
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.runtime.getValue
class AndroidMotionHelper {
// Memeriksa penonaktifan animasi
fun isAnimationDisabled(context: Context): Boolean {
return try {
Settings.Global.getFloat(
context.contentResolver,
Settings.Global.ANIMATOR_DURATION_SCALE
) == 0f
} catch (e: Settings.SettingNotFoundException) {
false
}
}
// Mengamati perubahan animasi (ContentObserver)
fun observeAnimationScale(
context: Context,
onChange: (Boolean) -> Unit
): ContentObserver {
val observer = object : ContentObserver(Handler()) {
override fun onChange(selfChange: Boolean) {
onChange(isAnimationDisabled(context))
}
}
context.contentResolver.registerContentObserver(
Settings.Global.getUriFor(
Settings.Global.ANIMATOR_DURATION_SCALE
),
false,
observer
)
return observer
}
}
// Jetpack Compose — animasi dengan mempertimbangkan pengaturan
@Composable
fun MotionAwareAnimation(enabled: Boolean) {
val context = androidx.compose.ui.platform.LocalContext.current
val noMotion = AndroidMotionHelper().isAnimationDisabled(context)
val scale by animateFloatAsState(
targetValue = if (enabled) 1f else 0f,
animationSpec = if (noMotion) {
androidx.compose.animation.core.tween(durationMillis = 0)
} else {
androidx.compose.animation.core.spring()
},
label = "scale"
)
// UI dengan animasi
}
Kelas AndroidMotionHelper memeriksa ANIMATOR_DURATION_SCALE melalui Settings.Global, menyediakan ContentObserver untuk melacak perubahan, dan memungkinkan animasi Jetpack Compose menyesuaikan: saat animasi dinonaktifkan, durationMillis = 0 (penerapan instan). Untuk View system, gunakan ViewPropertyAnimator.withLayer() dan periksa isAnimationDisabled() sebelum memulai animasi.
Pengaturan aksesibilitas "Hapus animasi" di Android — satu-satunya cara bagi pengguna biasa untuk menonaktifkan animasi. Opsi Pengembang hanya ditujukan untuk pengembang dan mungkin disembunyikan. Pengaturan aksesibilitas dijamin diteruskan ke semua aplikasi melalui API sistem. Pengembang harus mengacu pada AccessibilityManager, bukan Opsi Pengembang.
Fungsi media CSS prefers-reduced-motion memungkinkan pengembang web menonaktifkan atau mengganti animasi saat pengguna mengaktifkan Reduce Motion di sistem operasi. Browser meneruskan nilai reduce saat pengaturan sistem aktif, no-preference — jika pengaturan tidak diubah. Didukung oleh semua browser modern sejak 2020: Chrome 74+, Safari 10.3+, Firefox 64+, Edge 79+.
Rekomendasi MDN dan W3C — selalu atur prefers-reduced-motion: reduce bersama dengan animasi. Pengguna yang mengaktifkan Reduce Motion tidak boleh melihat pulsasi, paralaks, pemutaran otomatis karusel, dan pemuatan skeleton. Sebagai ganti animasi, konten statis dapat ditampilkan atau CSS transition dengan durasi minimal dapat digunakan. Di bawah ini adalah contoh adaptasi lengkap.
Pada prefers-reduced-motion: reduce halaman web harus: menonaktifkan animasi CSS (@keyframes), mengganti CSS transitions dengan perubahan instan, menghentikan animasi JavaScript (requestAnimationFrame), menonaktifkan parallax scrolling, menghentikan karusel dan penggeser, menonaktifkan efek skeleton, dan mengganti spinner dengan indikator statis.
/* Animasi dasar (no-preference) */
.spinner {
width: 32px;
height: 32px;
border: 3px solid #e0e0e0;
border-top-color: #0066CC;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
.skeleton {
background: linear-gradient(
90deg,
#f0f0f0 25%,
#e8e8e8 37%,
#f0f0f0 63%
);
background-size: 400% 100%;
animation: shimmer 1.4s ease infinite;
}
.parallax-bg {
transform: translateZ(-1px) scale(1.5);
transition: transform 0.3s ease-out;
}
/* Reduce Motion: menonaktifkan semuanya */
@media (prefers-reduced-motion: reduce) {
.spinner {
animation: none;
border-top-color: #0066CC;
}
.skeleton {
animation: none;
background: #f0f0f0;
}
.parallax-bg {
transform: none;
transition: none;
}
.carousel {
scroll-behavior: auto;
overflow-x: auto;
}
.fade-in {
opacity: 1;
transform: none;
}
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}Dalam contoh CSS digunakan pengaturan ulang animasi global pada prefers-reduced-motion: reduce: semua animasi dan transisi mendapatkan duration 0.01ms dan iteration-count 1. Secara terpisah, spinner (batas statis), skeleton (latar abu-abu tanpa kedipan), paralaks (dinonaktifkan), dan karusel (scroll-behavior: auto, bukan smooth) ditimpa. Selektor universal * — pengaman untuk semua elemen.
Untuk JavaScript tersedia matchMedia('(prefers-reduced-motion: reduce)').matches. Jika true — jangan jalankan animasi melalui requestAnimationFrame, setInterval, atau Web Animations API. Contoh: penggeser dengan reduceMotion tidak berputar otomatis, hanya melalui tombol. Pustaka GSAP, Framer Motion, dan Anime.js mendukung pemeriksaan ini melalui opsi aksesibilitas mereka.
WCAG 2.2 (2023) memperkenalkan kriteria baru 2.3.3 Animation from Interactions (tingkat AAA): jika animasi dipicu oleh interaksi pengguna (klik, gulir, hover), animasi harus dapat dinonaktifkan atau tidak melebihi 5 detik. Animasi yang tidak terkait dengan interaksi (spinner pemuatan, progress bar) tidak termasuk dalam kriteria ini. Untuk tingkat AA, cukup bahwa animasi bukan satu-satunya cara menyampaikan informasi.
Kriteria 2.3.3 ditambahkan setelah banyak keluhan tentang mabuk gerak akibat parallax scrolling dan animasi "tarik-segarkan". W3C merekomendasikan semua situs dan aplikasi: jangan animasikan elemen lebih dari 5 detik, sediakan sakelar penonaktifan animasi (melalui panel kontrol atau prefers-reduced-motion), jangan gunakan elemen berdenyut dan berkedip (berbahaya untuk epilepsi).
Untuk kepatuhan terhadap WCAG 2.2 pengembang harus: memeriksa prefers-reduced-motion dan menonaktifkan animasi saat pengaturan aktif, menetapkan durasi maksimum animasi 5 detik (jika animasi tidak dapat dinonaktifkan), menyediakan sakelar UI animasi di pengaturan aplikasi, tidak menggunakan efek paralaks sebagai satu-satunya metode navigasi, dan menguji dengan Reduce Motion aktif di semua browser dan perangkat.
Untuk menguji perilaku aplikasi dengan Reduce Motion gunakan: iOS Simulator (aktifkan Reduce Motion di Settings > Accessibility), Android Emulator (aktifkan "Hapus animasi"), Chrome DevTools (Rendering > Emulate CSS media feature prefers-reduced-motion), inspektur web Safari (aktifkan Reduce Motion di macOS System Preferences > Accessibility > Display). Periksa bahwa konten tetap dapat diakses dan terbaca tanpa animasi.
Pertanyaan yang sering diajukan
Reduce Motion — fungsi accessibility sistem operasi yang menonaktifkan animasi antarmuka (paralaks, transisi, penskalaan ikon) untuk orang dengan gangguan vestibular. Diaktifkan di Settings > Accessibility. Sistem mengirimkan sinyal ke aplikasi melalui UIAccessibility (iOS), Settings.Global (Android), atau prefers-reduced-motion (CSS), dan pengembang dapat menyesuaikan animasi.
Di iPhone Reduce Motion diaktifkan di Settings > Accessibility > Motion > Reduce Motion. Setelah diaktifkan, paralaks wallpaper, efek iMessage, animasi pembukaan aplikasi, dan transisi antar layar (diganti dengan cross-fade) dinonaktifkan. Animasi sistem UIKit tidak diputar. Pengaturan berlaku untuk semua aplikasi tanpa memulai ulang perangkat.
Di Android animasi dinonaktifkan dengan dua cara: Pengaturan > Aksesibilitas > Hapus animasi (direkomendasikan untuk pengguna) atau Opsi Pengembang > Skala animasi — nonaktifkan. Metode aksesibilitas memastikan semua aplikasi menerima sinyal. Opsi Pengembang hanya memengaruhi animasi sistem dan mungkin disembunyikan di beberapa perangkat.
Fungsi media CSS prefers-reduced-motion: reduce memungkinkan penonaktifan animasi di tingkat gaya. Disarankan untuk mengatur pengaturan ulang universal: animation-duration: 0.01ms, transition-duration: 0.01ms, animation-iteration-count: 1 untuk semua elemen. Timpa secara terpisah komponen tertentu (spinner, skeleton, paralaks). JavaScript diperiksa melalui matchMedia('(prefers-reduced-motion: reduce)').
WCAG 2.2 kriteria 2.3.3 (AAA) mensyaratkan animasi yang dipicu oleh interaksi pengguna harus dapat dinonaktifkan atau tidak melebihi 5 detik. Untuk AA, cukup bahwa animasi bukan satu-satunya cara menyampaikan informasi. Disarankan untuk selalu memeriksa prefers-reduced-motion dan menyediakan sakelar UI animasi di pengaturan aplikasi.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga