-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.webc
289 lines (251 loc) · 14.5 KB
/
index.webc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
---
layout: layout.webc
---
<h1>Progressive Enhancement Recipes using Eleventy WebC Image Comparison Components</h1>
<p>Return to the <a href="https://github.com/11ty/demo-webc-image-compare">GitHub repository</a>.</p>
<p><a href="https://www.11ty.dev/docs/languages/webc/">Learn more about WebC</a>.</p>
<p>The examples below are in order of implementation complexity from least to most. All are using <a href="https://www.11ty.dev/docs/plugins/partial-hydration/"><code>is-land</code></a>, specifically <code><is-land on:idle on:visible></code>. The pre-JS experience is emulated using <code><is-land on:media="(max-width: 0px)"></code>.</p>
<h2>Summary</h2>
<ul>
<li>If you want to show both images pre-JS, this can be solved with an entirely clientside Image Comparison component but it will negatively impact your Content Layout Shift score. This use case is not shown below.</li>
<li>Do you want to show either the left or right image pre-JS? Use <code>@value="0"</code> or <code>@value="100"</code> respectively.</li>
<li>Do you want the form control to be interactive pre-JS? Go to the <a href="#enabled">Always Enabled</a> approach.</li>
<li>If you want an interactive form control pre-JS and have it be functional too? See the <a href="#has-radios"><code>:has()</code> and Radios</a> approach.</li>
<li>Does this form input need to be a successful form control and submit to the server? The <a href="#dsd">ShadowDOM</a> example is the only one that doesn’t work with forms. This *could* be fixed with JS but is it worth it?</li>
</ul>
<h2>Table of Contents</h2>
<ol>
<li><a href="#enabled">Always Enabled</a></li>
<li><a href="#disabled">Disabled until JavaScript</a></li>
<li><a href="#hidden-css">Hidden via <code>:not(:defined)</code> CSS</a></li>
<li><a href="#hidden-tmpl">Hidden via JS <code><template></code></a></li>
<li><a href="#dsd">Declarative Shadow DOM</a></li>
<li><a href="#has-radios"><code>:has()</code> and Radios</a></li>
<li><a href="#opacity">Bonus: <code>opacity</code> Slider</a></li>
</ol>
<h2 id="enabled">Always Enabled</h2>
<ul>
<li><strong>Complexity Level: Low</strong></li>
<li>The range control is always enabled and synchronized to the display when JS initializes.</li>
<li>This has the potential for an uncanny valley in which the control is movable but the view is not updated!</li>
<li><a href="https://github.com/11ty/demo-webc-image-compare/blob/main/_includes/webc/image-compare-enabled.webc">WebC source code</a></li>
</ul>
<syntax-highlight language="html" webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight">
<!-- WebC Component HTML -->
<image-compare-enabled @name="range-enabled" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-enabled>
</syntax-highlight>
<div class="columns">
<is-land on:media="(max-width: 0px)">
<form method="get">
<h3>Before JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-enabled @name="range-enabled" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-enabled>
</form>
</is-land>
<is-land on:visible on:idle>
<form method="get">
<h3>After JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-enabled @name="range-enabled" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-enabled>
</form>
</is-land>
</div>
<h2 id="disabled">Disabled until JavaScript</h2>
<ul>
<li><strong>Complexity Level: Low</strong></li>
<li>This version uses JS to toggle the range input from disabled to enabled.</li>
<li>Disabling the control avoids the uncanny valley (in comparison to keeping it enabled) by communicating to the user that the control is not yet initialized.</li>
<li><a href="https://github.com/11ty/demo-webc-image-compare/blob/main/_includes/webc/image-compare-disabled.webc">WebC source code</a></li>
</ul>
<syntax-highlight language="html" webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight">
<!-- WebC Component HTML -->
<image-compare-disabled @name="range-disabled" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-disabled>
</syntax-highlight>
<div class="columns">
<is-land on:media="(max-width: 0px)">
<form method="get">
<h3>Before JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-disabled @name="range-disabled" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-disabled>
</form>
</is-land>
<is-land on:visible on:idle>
<form method="get">
<h3>After JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-disabled @name="range-disabled" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-disabled>
</form>
</is-land>
</div>
<h2 id="hidden-css">Hidden via CSS</h2>
<ul>
<li><strong>Complexity Level: Low</strong></li>
<li>This version uses CSS <code>:not(:defined)</code> to hide the range input before JS.</li>
<li><a href="https://github.com/11ty/demo-webc-image-compare/blob/main/_includes/webc/image-compare-defined.webc">WebC source code</a></li>
</ul>
<syntax-highlight language="html" webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight">
<!-- WebC Component HTML -->
<image-compare-defined @name="range-hidden" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-defined>
</syntax-highlight>
<div class="columns">
<is-land on:media="(max-width: 0px)">
<form method="get">
<h3>Before JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-defined @name="range-hidden" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-defined>
</form>
</is-land>
<is-land on:visible on:idle>
<form method="get">
<h3>After JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-defined @name="range-hidden" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-defined>
</form>
</is-land>
</div>
<h2 id="hidden-tmpl">Hidden via JS Template</h2>
<ul>
<li><strong>Complexity Level: Low</strong></li>
<li>This version uses JS to swap in <code><template></code> content holding the range input.</li>
<li><a href="https://github.com/11ty/demo-webc-image-compare/blob/main/_includes/webc/image-compare-hidden.webc">WebC source code</a></li>
</ul>
<syntax-highlight language="html" webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight">
<!-- WebC Component HTML -->
<image-compare-hidden @name="range-hiddentmpl" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-hidden>
</syntax-highlight>
<div class="columns">
<is-land on:media="(max-width: 0px)">
<form method="get">
<h3>Before JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-hidden @name="range-hiddentmpl" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-hidden>
</form>
</is-land>
<is-land on:visible on:idle>
<form method="get">
<h3>After JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-hidden @name="range-hiddentmpl" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-hidden>
</form>
</is-land>
</div>
<h2 id="dsd">Declarative Shadow DOM</h2>
<ul>
<li><strong>Complexity Level: Moderate</strong></li>
<li>This version uses Declarative Shadow DOM for the range input. Before JS, the range input is always enabled and synchronized to the display when JS runs.</li>
<li>When Declarative Shadow DOM is not supported, the polyfill is applied inline (it’s a few lines of code). Before JS, the range input is hidden.</li>
<li><em>Benefit</em>: we can move some of the styles into Shadow DOM to scope those styles for free!</li>
<li><em>Drawback</em>: This version does not have a successful form control because it uses Shadow DOM. This can be fixed with JS (but requires JS).</li>
<li><em>Drawback</em>: Is there a way to de-duplicate the declarative shadow dom template without JavaScript? Does every instance of the component need the same nested markup?</li>
<li><a href="https://github.com/11ty/demo-webc-image-compare/blob/main/_includes/webc/image-compare-shadowdom.webc">WebC source code</a></li>
</ul>
<syntax-highlight language="html" webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight">
<!-- WebC Component HTML -->
<image-compare-shadowdom @name="range-shadowdom" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-shadowdom>
</syntax-highlight>
<div class="columns">
<is-land on:visible on:idle>
<form method="get">
<h3>Before JavaScript <button type="submit">Form Submit**</button></h3>
<!-- We use a one-off disabled attribute here to simulate pre-JS, is-land component renaming was messing with DSD -->
<image-compare-shadowdom disabled @name="range-shadowdom" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-shadowdom>
**Form submit is not successful.
</form>
</is-land>
<is-land on:visible on:idle>
<form method="get">
<h3>After JavaScript <button type="submit">Form Submit**</button></h3>
<image-compare-shadowdom @name="range-shadowdom" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-shadowdom>
**Form submit is not successful.
</form>
</is-land>
</div>
<h2 id="has-radios"><code>:has()</code> and Radios</h2>
<ul>
<li><strong>Complexity Level: Moderate</strong></li>
<li>This version uses <code>:has</code> and radios for a functional No-JS experience (and synchronizes the value pre-JS and post-JS). Of course, the number of radios shown can be customized.</li>
<li>If <code>:has()</code> is not supported (at time of writing, Firefox), the inputs are hidden (though you could modify this behavior to be Always Enabled and synchronized).</li>
<li><a href="https://github.com/11ty/demo-webc-image-compare/blob/main/_includes/webc/image-compare-nojs.webc">WebC source code</a></li>
</ul>
<syntax-highlight language="html" webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight">
<!-- WebC Component HTML -->
<image-compare-nojs @name="range-radios" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-nojs>
</syntax-highlight>
<div class="columns">
<is-land on:media="(max-width: 0px)">
<form method="get">
<h3>Before JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-nojs @name="range-radios" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-nojs>
</form>
</is-land>
<is-land on:visible on:idle>
<form method="get">
<h3>After JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-nojs @name="range-radios" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-nojs>
</form>
</is-land>
</div>
<h2 id="opacity">Bonus: Opacity Slider</h2>
<p>For fun you can change <code>clip-path: inset(0 0 0 var(--position));</code> to <code>opacity: var(--position);</code> on any of these components to have the slider vary opacity instead of clip amount.</p>
<syntax-highlight language="html" webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight">
<!-- WebC Component HTML -->
<image-compare-defined @name="range-opacity" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy" style="clip-path: none; opacity: var(--position);">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-defined>
</syntax-highlight>
<is-land on:visible on:idle>
<form method="get">
<h3>After JavaScript <button type="submit">Form Submit</button></h3>
<image-compare-defined @name="range-opacity" @value="50">
<img src="/javaskipped-a.png" alt="JavaSkipped logo left" width="800" height="800" loading="lazy" style="clip-path: none; opacity: var(--position);">
<img src="/javaskipped-b.png" alt="JavaSkipped logo right" width="800" height="800" loading="lazy">
</image-compare-defined>
</form>
</is-land>