2017-08-06 James Craig <jcraig@apple.com>
[WebKit-https.git] / Websites / webkit.org / blog-files / prefers-reduced-motion / prm.htm
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Demo: prefers-reduced-motion media query</title>
5 <meta name="viewport" content="width=device-width, initial-scale=1">
6 <style type="text/css">
7 html {
8         font: 100% sans-serif;
9         font: -apple-system-body;
10 }
11 body {
12         font-size: 0.8em;
13         line-height: 1.1;
14 }
15
16
17 button {
18         cursor: pointer;
19         font-size: 1em;
20         -webkit-appearance: none;
21         border: solid 1px black;
22         color: black;
23         background-color: white;
24         padding: 0;
25         position: relative;
26 }
27 button::before {
28         display: block;
29         position: absolute;
30         content: " ";
31         top: 50%;
32         left: 50%;
33         width: 1px;
34         height: 1px;
35         opacity: 0;
36         background-color: rgba(255,100,100,0.3);
37         transition-duration: 0.4s;
38         transition-timing-function: ease-in-out;
39
40         /* Example 1: This value will be modified when 'reduce motion' is enabled. */
41         transition-property: top left width height opacity;
42 }
43 @media (prefers-reduced-motion) {
44         button::before {
45                 /* Example 1: Now only animating the opacity... not size or position, which control the scale effect. */ 
46                 transition-property: opacity;
47         }
48 }
49 button:hover::before, button:focus::before {
50         top: 0;
51         left: 0;
52         width: 100%;
53         height: 100%;
54         opacity:1;
55 }
56 button > div {
57         margin: 1.5em 2em;
58 }
59
60 #twirl {
61     position: relative;
62     border: solid 1px black;
63     overflow: hidden;
64 }
65 #twirl > div {
66         margin: 1.5em 2em;
67 }
68
69 @keyframes animation-twirl {  
70         0% {
71                 transform: rotate(0deg);
72         }
73         100% {
74                 transform: rotate(360deg);
75         }
76 }
77
78 #twirl::after {
79     width: 2000px;
80     height: 2000px;
81     position: absolute;
82     top: 50%;
83     left: 50%;
84     margin-left: -1000px;
85     margin-top: -1000px;
86     background: repeating-linear-gradient(140deg, rgba(0,0,0,0), rgba(0,0,0,0) 10px, rgba(200,200,200,0.3) 10px, rgba(200,200,200,0.3) 20px);
87     background-size: cover;
88     content: '';
89     animation: animation-twirl 100s infinite;
90 }
91
92 /* Example 2: Disabling a ongoing, decorative background animation. */
93 @media (prefers-reduced-motion) {
94         #twirl::after {
95                 animation: none;
96         }
97 }
98
99
100 #indicator #prmValue {
101         display: inline-block;
102         padding: 0.2em 0.4em;
103         text-transform: uppercase;
104         border: solid 1px #666;
105         background-color: #eee;
106 }
107 #indicator a {
108         text-decoration: none;
109 }
110
111 </style>
112 </head>
113 <body>
114
115 <h1>Reduced Motion Demos for WebKit blog post: <a href="https://webkit.org/blog/7551/responsive-design-for-motion/">Responsive Design for Motion</a></h1>
116
117 <p>To test these, enable the "Reduce Motion" setting.</p>
118 <ul>
119         <li><strong>iOS:</strong> Settings > General > Accessibility > Reduce Motion</li>
120         <li><strong>macOS:</strong> System Preferences > Accessibility > Display > Reduce Motion</li>
121         <li><strong>Xcode Accessibility Inspector:</strong> Settings > Reduce Motion (<a href="./axi.htm">see video demo</a>)</li>
122 </ul>
123
124 <h2>Example 1: Using CSS to modify an interaction transition-property</h2>
125 <!-- Check the 'button::before' blocks in the CSS. -->
126 <button>
127         <div>
128                 On hover/focus (or tap on mobile), a zoom/scale trigger appears by default,
129                 but it uses a simple dissolve when 'reduce motion' is enabled.
130         </div>
131 </button>
132
133 <h2>Example 2: Using CSS to disable an ongoing, purely decorative animation</h2>
134 <!-- Check the '#twirl::after' blocks in the CSS. -->
135 <div id="twirl">
136         <div>
137                 The spinning background animation is stopped entirely if 'reduce motion' is enabled.
138         </div>
139 </div>
140
141
142 <h2>Example 3: Using JavaScript to access the current value</h2>
143 <div id="indicator">Prefers reduced motion: <span id="prmValue">unsupported</span> <a href="https://webkit.org/b/168491" title="Outstanding bug: 168491" aria-label="Outstanding bug: 168491"><sup>1</sup></a></div>
144
145 <script type="text/javascript">
146
147 var motionQuery = matchMedia('(prefers-reduced-motion)');
148 function handleReduceMotionChanged() {
149     document.getElementById('prmValue').innerText = motionQuery.matches ? 'on' : 'no-preference or unsupported';
150 }
151 handleReduceMotionChanged(); // trigger this once on load to set up the initial value
152 motionQuery.addListener(handleReduceMotionChanged); // Note: https://webkit.org/b/168491
153
154 </script>
155
156
157 <h2>Example 4: Only display animated version if prefers-reduced-motion is both supported *and* off.</h2>
158 <p>This example uses a more explicit match for <code>(prefers-reduced-motion: no-preference)</code> which excludes all browsers that don't yet support the new feature.</p>
159 <img id="jaws" src="jaws.jpg" alt="Brody realizing the shark is in the water" width="480" height="214">
160
161 <script type="text/javascript">
162
163 var motionQuery2 = matchMedia('(prefers-reduced-motion: no-preference)'); 
164 function handleReduceMotionChanged2() {
165     document.images['jaws'].src = motionQuery2.matches ? 'jaws.gif' : 'jaws.jpg';
166 }
167 handleReduceMotionChanged2(); // trigger this once on load to set up the initial value
168 motionQuery.addListener(handleReduceMotionChanged2); // Note: https://webkit.org/b/168491
169
170 </script>
171
172 <p>Return to WebKit blog post: <a href="https://webkit.org/blog/7551/responsive-design-for-motion/">Responsive Design for Motion</a></p>
173
174 </body>
175 </html>