forked from w3ctag/design-principles
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.bs
3659 lines (2896 loc) · 152 KB
/
index.bs
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
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class="metadata">
Title: Web Platform Design Principles
Group: tag
Shortname: design-principles
Repository: w3ctag/design-principles
Status: ED
Level: none
TR: https://www.w3.org/TR/design-principles/
ED: https://w3ctag.github.io/design-principles/
Issue Tracking: GitHub https://github.com/w3ctag/design-principles/issues/
Editor: Sangwhan Moon, w3cid 42399, Google https://www.google.com/, https://sangwhan.com
Editor: Lea Verou, Invited Expert, https://lea.verou.me, w3cid 52258
Former Editor: Domenic Denicola, Google https://www.google.com/, https://domenic.me/, [email protected]
Former Editor: Travis Leithead, Microsoft, [email protected]
Abstract: This document contains a set of design principles to be used when designing web platform technologies. These principles have been collected during the Technical Architecture Group's discussions in <a href="https://github.com/w3ctag/design-reviews/">reviewing</a> developing specifications, and build upon the Ethical Web Principles [[ETHICAL-WEB]]. We encourage specification designers to read this document and use it as a resource when making design decisions.
Default Biblio Status: current
Markup Shorthands: markdown on
Boilerplate: feedback-header off
!By: <a href="https://www.w3.org/2001/tag/">Members of the TAG</a>, past and present
!Participate: <a href="https://github.com/w3ctag/design-principles">GitHub w3ctag/design-principles</a> (<a href="https://github.com/w3ctag/design-principles/issues/new">file an issue</a>; <a href="https://github.com/w3ctag/design-principles/issues?state=open">open issues</a>)
Link Defaults: html (dfn) queue a task/in parallel/reflect
</pre>
<pre class="link-defaults">
spec:css-cascade-5; type:dfn; text:inherit
spec:dom
type:method; for:Document; text:getElementsByTagName(qualifiedName)
type:method; for:Document; text:createElement(qualifiedName)
spec:html; type:dfn; for:/
text:focus update steps
text:task queue
text:event loop
spec:html; type:element-attr; for:a
text:href
text:ping
spec:html; type:element
text:a
text:link
text:script
text:style
spec:html; type:event; text:resize
spec:selectors-4; type:selector; text::hover
spec:webidl; type:dfn; text:namespace
spec:webidl; type:interface; text:double
</pre>
<!-- Some of these 'anchors' entries are really routing around spec bugs.
https://github.com/w3c/remote-playback/issues/137
https://github.com/whatwg/html/issues/5515
https://github.com/whatwg/html/issues/6053
https://github.com/whatwg/url/issues/522
-->
<pre class="anchors">
urlPrefix: https://dom.spec.whatwg.org/; spec: DOM
url: #dom-document-getelementsbytagname; type: interface; for: Document; text: getElementsByTagName
url: #dom-document-createelement; type: interface; for: Document; text: createElement
urlPrefix: https://w3c.github.io/DOM-Parsing/; spec: DOM-Parsing
url: #dom-innerhtml-innerhtml; type: attribute; for: Element; text: innerHTML
urlPrefix: https://tc39.github.io/ecma262/; spec: ECMA262
url: #sec-bigint-objects; type: interface; text: BigInt
url: #sec-date-objects; type: interface; text: Date
url: #sec-error-objects; type: interface; text: Error
url: #sec-finalization-registry-objects; type: interface; text: FinalizationRegistry
url: #sec-number-objects; type: interface; text: Number
url: #sec-weak-ref-objects; type: interface; text: WeakRef
urlPrefix: https://w3c.github.io/gamepad/; spec: gamepad
url:#event-gamepadconnected; type: event; text:gamepadconnected
urlPrefix: https://w3c.github.io/geolocation-api/; spec: geolocation
url:#dom-geolocation-watchposition; type:method; for:Geolocation; text:watchPosition()
urlPrefix: https://html.spec.whatwg.org/multipage/; spec: HTML
url: system-state.html#dom-navigator-online; type: attribute; for: NavigatorOnline; text: onLine;
urlPrefix: https://w3c.github.io/remote-playback/; spec: REMOTE-PLAYBACK
url: #remoteplayback-interface; type:interface; text: RemotePlayback
url: #dfn-remote-playback-devices; type:dfn; text: remote playback device
urlPrefix: https://url.spec.whatwg.org/; spec: URL
url: #percent-encode; type: abstract-op; text: percent-encode
urlPrefix: https://www.w3.org/TR/payment-request/; spec: payment-request
url: #dfn-state; type: dfn; text: [[state]];
</pre>
<style>
table.data {
text-align: left;
font-size: small;
}
</style>
<h2 id="basic-principles">Principles behind design of Web APIs</h2>
The Design Principles are directly informed by the ethical framework
set out in the Ethical Web Principles [[ETHICAL-WEB]].
These principles provide concrete practical advice
in response to the higher level ethical responsibilities
that come with developing the web platform.
<h3 id="priority-of-constituencies">Put user needs first (Priority of Constituencies)</h3>
If a trade-off needs to be made,
always put user needs above all.
Similarly, when beginning to design an API,
be sure to understand and document the user need that the API aims to address.
[The internet is for end users](https://tools.ietf.org/html/rfc8890):
any change made to the web platform has the potential to
[affect vast numbers of people](https://www.w3.org/2001/tag/doc/ethical-web-principles/#allpeople),
and may have a profound impact on any person's life. [[RFC8890]]
User needs come before the needs of web page authors,
which come before the needs of user agent implementors,
which come before the needs of specification writers,
which come before theoretical purity.
Like all principles,
this isn't absolute.
Ease of authoring affects how content reaches users.
User agents have to prioritize finite engineering resources,
which affects how features reach authors.
Specification writers also have finite resources,
and theoretical concerns reflect underlying needs of all of these groups.
See also:
* [The web should not cause harm to society](https://www.w3.org/2001/tag/doc/ethical-web-principles/#noharm)
* [The web must enhance individuals' control and power](https://www.w3.org/2001/tag/doc/ethical-web-principles/#control)
* [[RFC8890]]
<h3 id="safe-to-browse">It should be safe to visit a web page</h3>
When adding new features,
design them to preserve the user expectation
that visiting a web page is generally safe.
The Web is named for its hyperlinked structure.
In order for the web to remain vibrant,
users need to be able to expect that merely visiting any given link
won't have implications for the security of their computer,
or for any essential aspects of their [privacy](https://www.w3.org/2001/tag/doc/ethical-web-principles/#privacy).
For example, an API which allows any website to
[detect the use of assistive technologies](#do-not-expose-use-of-assistive-tech)
may make users of these technologies feel unsafe visiting unknown web pages,
since any web page may detect this private information.
If users have a realistic expectation of safety,
they can make informed decisions
between Web-based technologies and other technologies.
For example, users may choose to use a web-based food ordering page,
rather than installing an app,
since installing a native app is riskier than visiting a web page.
To work towards making sure the reality of safety on the web matches users' expectations,
we can take complementary approaches when adding new features:
* We can improve the user interfaces through which the Web is used
to make it clearer what users of the Web should (and should not) expect;
* We can change the technical foundations of the Web
so that they match user expectations of privacy;
* We can consider the cases where users would be better off
if expectations were higher,
and in those cases
try to change both technical foundations and expectations.
A new feature which introduces safety risks may still improve user safety overall,
if it allows users to perform a task more safely on a web page
than it would be for them to install a native app to do the same thing.
However, this benefit needs to be weighed against the common goal
of users having a reasonable expectation of safety on web pages.
See also:
* [Security and Privacy Self-Review](https://www.w3.org/TR/security-privacy-questionnaire/)
<h3 id="trusted-ui">Trusted user interface should be trustworthy</h3>
Consider whether new features impact trusted user interfaces.
Users depend on trusted user interfaces
such as the address bar, security indicators and permission prompts,
to understand who they are interacting with and how.
These trusted user interfaces must be able to be designed in a way
that enables users to trust [and verify](https://www.w3.org/2001/tag/doc/ethical-web-principles/#verify)
that the information they provide is genuine,
and hasn't been spoofed or hijacked by the website.
If a new feature allows untrusted user interfaces
to resemble trusted user interfaces,
this makes it more difficult for users to understand what information is trustworthy.
<p class="example">
For example, JavaScript {{alert()}} allows a page to show a modal dialog which looks like part of the browser.
This is often used to attempt to trick users into visiting scam websites.
If this feature was proposed today, it would probably not proceed.
</p>
<h3 id="consent">Ask users for meaningful consent</h3>
If a useful feature has the potential to cause harm to users,
make sure that the user can give [meaningful consent](https://www.w3.org/2001/tag/doc/ethical-web-principles/#control) for that feature to be used,
and that they can refuse consent effectively.
In order to give *meaningful consent*, the user must:
- **understand** what permission they may choose whether to grant the web page
- be able to choose to give or refuse that permission **effectively**.
If a feature is powerful enough to require user consent,
but it's impossible to explain to a typical user what they are consenting to,
that's a signal that you may need to reconsider the design of the feature.
If a permission prompt is shown,
and the user doesn't grant permission,
the Web page should not be able to do anything
that the user believes they have refused consent for.
By asking for consent,
we can inform the user of what capabilities the web page does or doesn't have,
reinforcing their confidence that <a href="#safe-to-browse">the web is safe</a>.
However, the <a href="#priority-of-constituencies">user benefit</a>
of a new feature must justify the additional burden on users
to decide whether to grant permission for each feature
whenever it's requested by a Web page.
Refusal is most effective if the site cannot
distinguish refusal from other, common situations.
This can make it more difficult for a site to
pressure users to grant consent.
<p class="example">
For example,
the [Geolocation API](https://www.w3.org/TR/geolocation-API/)
grants access to a user's location.
This can help users in some contexts,
like a mapping application,
but may be dangerous to some users in other contexts -
especially if used without the user's knowledge.
So that the user may decide whether their location may be used by a Web page,
a permission prompt should be shown to the user asking whether to grant location access.
If the user refuses permission,
no location information is available to the Web page.
</p>
See also:
* [Security and privacy are essential](https://www.w3.org/2001/tag/doc/ethical-web-principles/#privacy)
<h3 id="identity">Use identity appropriately in context</h3>
Give people [control](https://www.w3.org/TR/ethical-web-principles/#control)
over the identifying information about themselves
they are presenting in different contexts on the web,
and be transparent about it.
"Identity" is a complex concept that can be understood in many different ways.
It can refer to how someone presents or sees themselves, how they relate to other
people, groups, or institutions, and can determine how they behave
or how they are treated by others.
In web architecture, "identity" is often used as a shortcut
to refer to identifiers, and the information attached to them.
Features that use or depend on
identifiers and the attachment of data about a person
to that identifier carry privacy risks which
often reach beyond a single API or system.
This includes data that has been passively generated (for example,
about their behaviour on the web) as well as that which has been
actively collected (for example, they have filled in a form).
For such features, you should [understand the context](https://www.w3.org/TR/privacy-principles/#identity)
in which it will be used,
including how it will be used alongside other features of the web.
Make sure the user can [give appropriate consent](#consent).
Design APIs to collect
[the smallest amount of data](https://www.w3.org/TR/privacy-principles/#data-minimization)
necessary.
Use short-lived, temporary identifiers
unless a persistent identifier is absolutely necessary.
<h3 id="devices-platforms">Support the full range of devices and platforms (Media Independence)</h3>
<!-- was "Media Independence" in the HTML Design Principles -->
As much as possible,
ensure that features on the web work across different input and output [devices,
screen sizes, interaction modes, platforms, and media](https://www.w3.org/TR/ethical-web-principles/#multi).
One of the main values of the Web is that it's extremely flexible:
a Web page may be viewed on virtually any consumer computing device
at a very wide range of screen sizes,
may be used to generate printed media,
and may be interacted with in a large number of different ways.
New features should match the [existing flexibility](https://www.w3.org/2001/tag/doc/ethical-web-principles/#render)
of the web platform.
<div class="note">
This doesn't imply that features which don't work in *every* possible context should be excluded.
For example, hyperlinks can't be visited when printed on paper,
and the ''click'' event doesn't translate perfectly to touch input devices
where positioning and clicking the pointer occur in the same gesture (a "tap").
These features still work across a wide variety of contexts,
and can be adapted to devices that don't support their original intent -
for example, a tap on a mobile device will fire a ''click'' event as a fallback.
</div>
Features should also be designed so that the easiest way to use them
maintains flexibility.
<div class="example">
The 'display: block',
'display: flex',
and 'display: grid' layout models in CSS
all default to placing content within the available space and without overlap,
so that it works across screen sizes,
and allows users to choose their own font and font size without causing text to overflow.
</div>
Sometimes features aren't yet available on some implementations or platforms
despite working on others.
In these cases, features should be designed such that it is possible for
code to gracefully fail or be polyfilled.
See [[#feature-detect]].
<h3 id=new-features>Add new capabilities with care</h3>
Add new capabilities to the web with consideration of existing functionality and content.
The Web includes many extension points that allow for additions;
see for example [[HTML#extensibility]].
Before adding items, consider integration with existing, similar capabilities.
If this leads to a preferred design approach that cannot be implemented by only adding items,
it might still be possible; see [[#removing-features]].
Do not assume that a change or removal is impossible without first checking.
<h3 id=removing-features>Remove or change capabilities only once you understand existing usage</h3>
Prioritize compatibility with existing content when removing or changing functionality.
Once a significant amount of content has come to depend on a particular behavior,
removing or changing that behavior is discouraged.
Removing or changing features and capabilities is possible,
but it first requires that the nature and scope of the impact on existing content
is well understood.
This might require research into how features are used by existing content.
The obligation to understand existing usage also applies to any features that content relies upon.
This includes vendor-proprietary features and
behavior that might be considered implementation bugs.
Web features are not solely defined in specifications;
they are also defined by how content uses those features.
<h3 id="leave-the-web-better">Leave the web better than you found it</h3>
As you add new capabilities to the web platform, do so in a way that improves
the overall platform, for example its security or privacy vulnerabilities, or accessibility characteristics.
The existence of a defect in one part of the platform must not be used as a license
for adding or extending such defect into new capabilities and thereby further decreasing
the overall platform quality. Where possible, build new web capabilities that
improve the overall platform quality.
Parts of the web platform evolve independently.
Issues that are present with a certain web technology now may be fixed in a subsequent iteration.
Duplicating these issues makes fixing them more difficult.
By adhering to this principle we can make sure overall platform quality improves over time.
<h3 id="data-minimization">Minimize user data</h3>
Design features to work with the minimum amount of data necessary to carry out their
users' goals.
<a href="https://www.w3.org/TR/privacy-principles/#data-minimization">Data minimization</a>
limits the risks of data being inappropriately disclosed or misused.
Design Web APIs to make it easier for sites to request, collect, and/or transmit
a small amount of data, or more granular or specific data, than it is to work with
more generic or bulk data.
APIs should also provide granularity and user controls,
in particular over <a href="https://www.w3.org/TR/privacy-principles/#dfn-data">personal data</a>,
that is communicated to sites.
When additional functionality requires additional data, APIs can enable this
subject to user consent (e.g., a permission prompt or user activation).
<div class=example>
A <a href="#font-enumeration">Font Enumeration API</a> API was once proposed, but the tradeoff of user data exposed was not justified by the use cases. Instead, an alternative solution was proposed, which only exposed the font the user actually selected.
</div>
<h2 id="api-across-languages">API Design Across Languages</h2>
<h3 id="simplicity">Prefer simple solutions</h3>
<!-- was "Avoid Needless Complexity" in the HTML Design Principles -->
Look hard for simple solutions to the
<a href="#priority-of-constituencies">user needs</a>
you intend to address.
Simple solutions are generally better than complex solutions,
although they may be harder to find.
Simpler features are easier for user agents to implement and test,
more likely to be interoperable,
and easier for authors to understand.
It is especially important to design your feature so that
the most common use cases are easy to accomplish.
Make sure that your <a href="#priority-of-constituencies">user needs</a>
are well-defined.
This allows you to avoid scope creep,
and make sure that your API does actually meet the needs of all users.
Of course,
complex or rare use cases are also worth solving,
though their solutions may be more complicated to use.
As Alan Kay said,
"simple things should be simple, complex things should be possible."
Do note however that while common cases are often simple,
commonality and complexity are not always correlated.
<div class=example>
Sanitizing HTML to prevent XSS attacks is a complex process
that requires extensive security knowledge,
however the [Sanitizer API](https://wicg.github.io/sanitizer-api/) provides a shortcut for this common use case.
It also permits simpler types of filtering, but with more configuration.
</div>
See also:
* [[LEAST-POWER]]
<h3 id="high-level-low-level">Consider tradeoffs between high level and low level APIs</h3>
<!--
See "High level or low-level APIs?"
https://github.com/w3ctag/design-principles/issues/117
-->
High-level APIs allow user agents more ability to
intervene in various ways [on behalf of the user](#priority-of-constituencies),
such as to ensure accessibility, privacy, or usability.
<div class=example id=font-enumeration>
A font picker (high level API)
[was recommended by the TAG](https://github.com/w3ctag/design-reviews/issues/399)
over a Font Enumeration API (low level API)
as it addresses the bulk of use cases,
while preserving user privacy,
as it is free from the the fingerprinting concerns that accompany
a general Font Enumeration API.
A native font picker also comes with accessibility built-in,
and provides consistency for end users.
</div>
Low-level APIs afford authors room for experimentation
so that high level APIs can organically emerge
from usage patterns over time.
They also provide an escape hatch when the higher-level API
is not adequate for the use case at hand.
Lower level building blocks cannot always be exposed as Web APIs.
A few possible reasons for this are
to preserve the user's security and privacy,
or to avoid tying Web APIs to specific hardware implementations.
However, high level APIs should be designed in terms of
building blocks over lower level APIs
whenever possible.
This may guide decisions on how high level the API needs to be.
A well-layered solution should ensure continuity
of the ease-of-use vs power tradeoff curve
and avoid sharp cliffs
where a small amount of incremental use case complexity
results in a large increase of code complexity.
<h3 id="name-thoughtfully">Name things thoughtfully</h3>
Name APIs with care.
Naming APIs well makes it much easier for authors to use them correctly.
See the more detailed <a href="#naming-is-hard">Naming principles</a> section
for specific guidance on naming.
<h3 id="consistency">Be consistent</h3>
It is good practice to consider precedent in the design of your API
and to try to be consistent with it.
There is often a tension between API ergonomics and consistency,
when existing precedent is of poor usability.
In some cases it makes sense to break consistency to improve usability,
but the improvement should be very significant to justify this.
<!-- TODO: example? -->
Since the web platform has gradually evolved over time,
there are often multiple conflicting precedents
which are mutually exclusive.
You can weigh which precedent to follow by taking into account
prevalence (all else being equal, follow the more popular precedent),
API ergonomics (all else being equal, follow the more usable precedent),
and API age (all else being equal, follow the newer precedent).
<!-- TODO: example? -->
There is often a tension between internal and external consistency.
<em>Internal consistency</em> is consistency with the rest of the system,
whereas <em>external consistency</em> is consistency with the rest of the world.
In the web platform, that might materialize in three layers:
consistency within the technology the API belongs to (e.g. CSS),
consistency with the rest of the web platform,
and in some cases external precedent,
when the API relates to a particular specialized outside domain.
In those cases, it is useful to consider what the majority of users will be.
Since for most APIs the target user is someone who is familiar with the
technology they are defined in,
err on the side of favoring consistency with that.
<div class="example">
One example is
<a href="https://www.w3.org/TR/css-color-4/#funcdef-lab">CIE L\*a\*b\* colors</a>:
It would be more consistent with the rest of CSS to use percentages for L (0%-100%),
but more consistent with the rest of Color Science to use a unitless number (0-100).
There was a lot of heated debate,
which resolved in favor of percentages,
i.e. consistency within CSS.
</div>
There is also a separate section on <a href="#naming-consistency">naming consistency</a>.
<h3 id="feature-detect">New features should be detectable</h3>
Provide a way for authors to programmatically detect
whether your feature is available,
so that web content may gracefully handle the feature not being present.
An existing feature may not be available on a page for a number of reasons.
Two of the more common reasons are
because it hasn't been implemented yet, or
because it's only available in <a href="#secure-context">secure contexts</a>.
Authors shouldn't need to write different code to handle each scenario.
That way, even if an author only knows or cares about one scenario,
the code will handle all of them.
<p class="note">
When a feature is available but isn't feasible to use
because a required device isn't present,
it's better to expose that the feature is available
and have a separate way to detect that the device isn't.
This allows authors to handle a device not being available differently
from the feature not being available,
for example by suggesting the user connect or enable the device.
See [[#device-enumeration]].
</p>
Authors should always be able to detect a feature from JavaScript,
and in some cases the feature should also be detectable
in the language where it's used
(such as ''@supports'' in CSS).
In some cases, it may **not** be appropriate to allow feature detection.
Whether the feature should be detectable or not
should be based on the <a href="#priority-of-constituencies">user need</a>
for the feature.
If there is a user need or design principle which would fail
if feature detection were available for the feature,
then you should not support feature detection.
Detecting the availability of a feature does not imply
detecting whether <a href="#consent">consent</a> to use the feature
has been granted.
Generally, detecting whether the feature is implemented
can be done separately from determining whether use of the feature has been authorized.
In some cases, it might be necessary to disable feature detection
in order to enable denying requests to use the feature.
Also, if a feature is generally not exposed to developers,
it is not appropriate to support feature detection.
For example, private browsing mode is a concept
which is recognised in web specifications,
but not exposed to authors.
For private browsing mode to support the user's needs,
it must not be feature detected.
See also:
* [[#do-not-expose-use-of-private-browsing-mode]]
* [[#do-not-expose-use-of-assistive-tech]]
* [[#secure-context]]
* [[#consent]]
<h3 id="secure-context">Consider limiting new features to secure contexts</h3>
Always limit your feature to secure contexts
if it would pose a risk to the user
without the authentication, integrity, or confidentiality
that's present only in secure contexts.
<div class="example">
One example of a feature that should be limited to secure contexts
is [Geolocation](https://www.w3.org/TR/geolocation-API/),
since it would be a risk to users' privacy to transmit their location in an insecure way.
</div>
For other features, TAG members past and present
haven't reached consensus on general advice.
Some believe that all new features
(other than features which are additions to existing features)
should be limited to secure contexts.
This would help encourage the use of HTTPS,
helping users be more secure in general.
Others believe that features should only be limited to secure contexts
if they have a known security or privacy impact.
This lowers the barrier to entry for creating web pages
that take advantage of new features which don't impact user security or privacy.
<div class="note">
Specification authors can limit most features defined in
Web IDL [[WEBIDL]],
to secure contexts
by using the
[{{SecureContext}}] extended attribute
on interfaces, namespaces, or their members (such as methods and attributes).
However, for some types of API (e.g., dispatching an event),
limitation to secure contexts should just
be defined in normative prose in the specification.
If this is the case,
consider whether there might be scope for adding a similar mechanism
to [{{SecureContext}}]
to make this process easier for future API developers.
</div>
<div class="note">
As described in [[#feature-detect]],
you should provide a way to programmatically detect whether a feature is available,
including cases where the feature is unavailable because the context isn't secure.
However, if, for some reason
there is no way for code to gracefully handle the feature not being present,
limiting the feature to secure contexts might cause problems
for code (such as libraries) that may be used in either secure or non-secure contexts.
</div>
<h3 id="do-not-expose-use-of-private-browsing-mode">Don't reveal that private browsing mode is engaged</h3>
Make sure that your feature doesn't give authors a way to detect private browsing mode.
Some people use [private browsing mode](https://www.w3.org/2001/tag/doc/private-browsing-modes/)
to protect their own personal safety.
Because of this, the fact that someone is using private browsing mode
may be [sensitive information](https://www.w3.org/TR/security-privacy-questionnaire/#sensitive-data) about them.
This information may [harm](https://www.w3.org/2001/tag/doc/ethical-web-principles/#noharm) people
if it is revealed to a web site controlled by others who have power over them
(such as employers, parents, partners,
or [state actors](https://www.w3.org/2001/tag/doc/ethical-web-principles/#expression)).
Given such dangers,
websites should not be able to detect that private browsing mode is engaged.
<div class="example">
User Agents which support [IndexedDB](https://www.w3.org/TR/IndexedDB/)
should not disable it in private browsing mode,
because that would reveal that private browsing mode is engaged
</div>
<div class="example">
The [Payment Request API](https://www.w3.org/TR/payment-request/)'s
[show() method](https://www.w3.org/TR/payment-request/#show-method),
when called,
allows User Agents <q cite="https://www.w3.org/TR/payment-request/#show-method">to act
as if the user had immediately
[aborted the payment request](https://www.w3.org/TR/payment-request/#dfn-user-aborts-the-payment-request)</q>.
This enables User Agents to automatically abort payment requests
in private browsing mode
(thus protecting [sensitive information](https://www.w3.org/TR/security-privacy-questionnaire/#sensitive-data)
such as the user's shipping or billing address)
without revealing that private browsing mode is engaged.
</div>
See also:
* [Security and privacy are essential](https://www.w3.org/2001/tag/doc/ethical-web-principles/#privacy)
* [What data does this specification expose to an origin?](https://www.w3.org/TR/security-privacy-questionnaire/#underlying-platform-data)
* [[#private-browsing-mode]]
<h3 id="private-browsing-mode">Consider how your API should behave in private browsing mode</h3>
If necessary, specify how your API should behave differently
in private browsing mode.
For example, if your API would reveal information
that would allow someone to correlate
a single user’s activity
both in and out of private browsing mode,
consider possible [mitigations](https://www.w3.org/TR/security-privacy-questionnaire/#mitigations)
such as introducing noise,
or using permission prompts to give the user extra information
to help them meaningfully consent to this tracking (see [[#consent]]).
Private browsing modes enable users to browse the web
without leaving any trace of their private browsing on their device.
Therefore, APIs which provide client-side storage
should not persist data stored
while private browsing mode is engaged
after it's disengaged.
This can and should be done
without revealing any detectable API differences to the site.
<div class="example">
User Agents which support
[localStorage](https://html.spec.whatwg.org/multipage/webstorage.html#dom-localstorage)
should not persist storage area changes
made while private browsing mode is engaged.
If the User Agent has two simultaneous sessions with a site,
one in private browsing mode and one not,
storage area changes made in the private browsing mode session
should not be revealed to the other browsing session,
and vice versa.
(The [storage event](https://html.spec.whatwg.org/multipage/indices.html#event-storage) should not be fired
at the other session's [window object](https://html.spec.whatwg.org/multipage/window-object.html#window).)
</div>
See also:
* [[#do-not-expose-use-of-private-browsing-mode]]
* [Does this specification introduce new state for an origin that persists across browsing sessions?](https://www.w3.org/TR/security-privacy-questionnaire/#persistent-origin-specific-state)
* [Security and privacy self review: Private Browsing](https://www.w3.org/TR/security-privacy-questionnaire/#private-browsing)
<h3 id="do-not-expose-use-of-assistive-tech">Don't reveal that assistive technologies are being used</h3>
Make sure that your API doesn't provide a way
for authors to detect that a user is using assistive technology
without the user's consent.
[The web platform must be accessible to people with disabilities.](https://www.w3.org/2001/tag/doc/ethical-web-principles/#allpeople)
If a site can detect that a user is using an assistive technology,
that site can deny or restrict the user's access to the services it provides.
People who make use of assistive technologies
are often [vulnerable members of society](https://www.w3.org/2001/tag/doc/ethical-web-principles/#noharm);
their use of assistive technologies is [sensitive information](https://www.w3.org/TR/security-privacy-questionnaire/#sensitive-data) about them.
If an API provides access to this information
without the user's [consent](#consent),
this sensitive information may be revealed to others
(including [state actors](https://www.w3.org/2001/tag/doc/ethical-web-principles/#expression))
who may wish them harm.
Sometimes people propose features which aim to improve the user experience
for users of assistive technology,
but which would reveal the user's use of assistive technology as a side effect.
While these are well intentioned,
they violate [[#safe-to-browse]],
so alternative solutions must be found.
<div class="example">
The [Accessibility Object Model](https://wicg.github.io/aom/) (AOM)
used to define a set of events which, when fired,
[revealed the use of assistive technology](https://github.com/WICG/aom/issues/81).
AOM has since removed these events and
[replaced them](https://github.com/WICG/aom/blob/gh-pages/explainer.md#user-action-events-from-assistive-technology) with synthetic DOM events
which don't reveal the use of assistive technology.
</div>
See also:
* [Web Technology Accessibility Guidelines](https://w3c.github.io/apa/fast/)
* [Security and privacy are essential](https://www.w3.org/2001/tag/doc/ethical-web-principles/#privacy)
* [What data does this specification expose to an origin?](https://www.w3.org/TR/security-privacy-questionnaire/#underlying-platform-data)
<h3 id="require-user-activation">Require user activation for powerful APIs</h3>
Some powerful APIs can produce intrusive UI (eg. auto-playing audio),
expose user data (eg. interacting with the clipboard),
perform a background activity without an obvious indicator to the user (eg. accessing local storage),
or prompt the user to interact with [trusted UI](#trusted-ui)
(eg. permission prompts, device hardware features).
These APIs should be designed to require some indication of user intention (such as **user activation**) in order to function.
This indicates that the user is intentionally interacting with the web page in question.
User activation is defined in detail
[in the HTML standard](https://html.spec.whatwg.org/#tracking-user-activation).
You should think about the effect your API has on the user experience,
as well as any risks presented to the user,
when deciding whether user activation needs to only occur
once overall ([sticky](https://html.spec.whatwg.org/#sticky-activation-gated-api)),
periodically ([transient](https://html.spec.whatwg.org/#transient-activation-gated-api)) or
once per API call ([transient consuming](https://html.spec.whatwg.org/#activation-consuming-api)).
Note that while user activation is in many cases necessary,
it is not always *sufficient*
to protect users from invasive behaviours,
and seeking [meaningful consent](#consent) is also important.
<h3 id="support-non-fully-active">Support non-fully active BFCached documents</h3>
Specify how your feature behaves
in non-[=Document/fully active=] BFCached (Back/forward cached) documents if possible.
If your feature does **anything**
that falls into the
following categories:
* Interacts with a document from the "outside"
(e.g. sends information to a document)
* Makes cross-document interaction/resource sharing possible
(e.g. holding locks)
* May malfunction when a document is
kept in a non-[=Document/fully active=] BFCached state
(instead of getting destroyed)
after the user navigates away from it
or gets restored
(e.g. expects that a state saved in the document
won’t span multiple navigations)
Specify how your feature works
with non-[=Document/fully active=] BFCached documents,
following the guidelines in the
[Supporting BFCached Documents](https://w3ctag.github.io/bfcache-guide/) guide.
Note: It is possible for a document
to become non-[=Document/fully active=]
for other reasons not related to BFcaching,
such as when the iframe
holding the document gets detached.
This guidance only focuses
on the case where BFCache is involved,
and not other cases that might
cause a document to become non-[=Document/fully active=].
<h3 id="third-party-tools">Prioritize usability over compatibility with third-party tools</h3>
Design new features with usability as the primary goal, and compatibility with third-party tooling as a secondary goal.
The web platform benefits from a wide ecosystem of tooling
to facilitate easier and faster development.
A lot of the time, the syntax of an upcoming web platform feature
may conflict with that of a third-party tool causing breakage.
This is especially common as third-party tools are often used to prototype
new web platform features.
In general, web platform features last a lot longer than most third-party tools,
and thus giving them the optimal syntax and functionality should be of high priority.
In some cases, the conflict will introduce problems across a large number of
web sites, necessitating the feature's syntax to be redesigned to avoid clashes.
<div class="example">
<code>Array.prototype.contains()</code> had to be renamed to
<code>Array.prototype.includes()</code> to avoid clashes with
the identically named but incompatible method from PrototypeJS,
a library that was in use in millions of websites.
</div>
However, these cases should be exceptions.
When deciding whether to break third party tools with new syntax, there are several factors to consider,
such as severity of the breakage,
popularity of the third party tool,
and many more.
Possibly the most important factor is how severely would the usability of the web platform feature be compromised
if its syntax was changed to avoid breaking the third party tool?
If several alternatives of similar usability are being considered,
it is usually preferable to prioritize the ones that inconvenience third party tools the least.
<div class="example">
When the CSS WG was designing [[CSS-GRID-1|CSS Grid Layout]],
square brackets were chosen instead of parentheses for naming grid tracks
to avoid breaking Sass, a popular preprocessor.
</div>
However, if avoiding breaking the third party tool would lead to
a *significant* negative impact on of the feature's usability,
that is rarely an acceptable tradeoff,
unless it causes significant breakage of live websites.
Languages should also provide mechanisms for extensibility
that authors can use to extend the language
without breaking future native functionality,
to reduce such dilemmas in the future.
<h2 id="html">HTML</h2>
This section details design principles for features which are exposed via HTML.
<h3 id="attribute-reuse">Re-use HTML attribute names (only) for similar functionality</h3>
If you are adding a feature that is specified through an HTML attribute,
check if there is an existing attribute name on another element
that specifies similar functionality.
Re-using an existing HTML attribute name means authors can utilize existing knowledge,
maintains [consistency](#consistency) across the language,
and keeps its vocabulary small.
<div class="example">
The same attribute name, <{select/multiple}>,
is used on both <{select}>
to allow selection of multiple values,
as well as on <{input}>
to allow entry of multiple values.
</div>
<div class="example">
The <{details/open}> attribute was introduced on the <{details}> element,
and then re-used by <{dialog}>.
</div>
If you do re-use an existing HTML attribute,
try to keep its syntax as close as possible to the syntax of the existing attribute.
<div class="example">
The <{label/for}> attribute was introduced on the <{label}> element,
for specifying which form element it should be associated with.
It was later re-used by <{output}>,
for specifying which elements contributed
input values to or otherwise affected the calculation.
The syntax of the latter is broader:
it accepts a space-separated list of ids,
whereas the former only accepts one id.
However, they both still conform to the same syntax,
whereas e.g. if one of them accepted a list of ids,
and the other one a selector, that would be an antipattern.
</div>
The inverse also applies:
do **not** re-use an existing HTML attribute name if
the functionality you are adding is **not** similar to that of the existing attribute.
<div class="example">
The `type` attribute is used on the <{input}> and <{button}> elements
to further specialize the element type,
whereas on every other element (e.g. <{link}>, <{script}>, <{style}>)
it specifies MIME type.
This is an antipattern; one of these groups of attributes should have had a different name.
</div>
<h3 id="html-lists">Use space-separated attributes for short lists of values, separate elements for longer lists</h3>
<!-- https://github.com/w3ctag/design-principles/issues/277 -->
When specifying metadata about an element that can be a list of values,
common practice is to use a space-separated list and expose it as a {{DOMTokenList}}.
<div class=example>
The <{global/class}> attribute on elements takes a space-separated list of class names.
{{Element/classList}} is a {{DOMTokenList}} that allows authors to add and remove class names.
</div>
<div class=example>
The <{iframe/sandbox}> attribute takes a space-separated list of sandbox flags.
`iframe.sandbox` is a {{DOMTokenList}} that allows authors to add and remove sandbox flags.
</div>
Consistency with other parts of the Web Platform is important,
even if this means using another character to separate values.
<div class=example>
The <{input/accept}> attribute is a comma-separated list of values,
because it needs to match the syntax of the `Accept` HTTP header. (See [guidance on HTTP headers](#new-http-header-syntax))
</div>
Regardless of syntax, attributes should only be used for short lists of values.
For longer lists, embedding the entire list in an attribute is discouraged.
Instead, current practice is to use separate elements to represent the list items (and any metadata about them).
These elements could either be children of the element in question, or linked through an attribute.
<div class=example>
The list of values for the <{select}> element is provided as a series of <{option}> element children.
However, when providing a list of recommended values for an <{input}> element, a separate element is used (<{datalist}>),
linked through a <{input/list}> attribute.
</div>
<div class=example>
The list of media sources for a <{video}> or <{audio}> element is provided as a series of <{source}> element children.
</div>
In rare instances, other tradeoffs are necessary.
<div class=example>
The <{img/srcset}> attribute allows for a comma-separated list of image candidate strings.
This syntax was chosen over a list of child elements to avoid verbosity
and because the <{img}> element is an empty element that does not permit child elements.
A space-separated syntax would not have been possible, as each list item includes multiple values.
<!--
TODO: link to the "microsyntaxes are usually bad" principle once it's been written.