forked from bkardell/common-panel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
preferrential-display.html
189 lines (168 loc) · 12.9 KB
/
preferrential-display.html
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
<!DOCTYPE html>
<html>
<head>
<title>Preferrential Display Explainer</title>
<meta charset='utf-8'>
<script src='http://www.w3.org/Tools/respec/respec-w3c-common'
async class='remove'></script>
<style>
.todo { color: red; font-weight: bold; }
#whynot li > em { font-weight: bold; }
</style>
<script class='remove'>
var respecConfig = {
specStatus: "unofficial",
shortName: "preferred-display",
editors: [
{ name: "Brian Kardell",
url: "https://twitter.com/briankardell",
company: "Apollo Education Group",
companyURL: "http://www.apollo.edu/"
}
]
};
</script>
</head>
<body>
<section id='abstract'>
<p>
This document decribes a proposal for a CSS mechanism and DOM APIs to
aid in increasing the level of separation between visual and non-visual
structures with runtime reuse. It is useful for Custom Elements, introduces potentially new
explanations for how existing elements in the platform work.
</p>
</section>
<section id='sotd'>
</section>
<section>
<h2>Introduction</h2>
<p>
When editing a document, an author attempts to mark it up semantically and control
a separation of visual aspects through CSS. This allows various the user-agent
and tools to use the same semantic data to provide any number of affordances
for accessibility, navigation, styling and interaction. HTML elements are generally
carefully constructed to define <em>what</em> they do that makes them unique,
rather than very specifically how they look. This separation leaves room for
certain experimentation and variance that is healthy for the long term adaptability
of the platform. For example, because a
<code><select></code> element doesn't strictly define all aspects of the
visual properties, it was possible for mobile phones to provide a better user
experience where visual real estate is very limited and click areas are shrunk.
</p>
<p>
Similarly, an author may use various types on the <code><input></code> element,
which, if undefined still defaults to <code>type="text"</code> and allows UAs like mobile
devices provide native controls. In <em>this aspect</em>, the <code>type</code> attribute in
some ways acts more like a hint than a requirement. This is, of course, not <em>entirely</em>
true (input type is kind of a debacle actually, APIs actually vary making it improbable to
use the intended 'text only' fallback without much pain) but it is a laudbile
aim and provides a conceptual background for some of the rationale for this proposal.
</p>
<p>These examples which already exist in the platform are good, but they are also potentially
limited and somewhat magical. They can have impacts on more than visualization as well, to the
end effect that they make it difficult for authors to deal with or innovate within.</p>
<p><em>Preferential Display</em> is a more generalized and more capable extension of the <code>type</code> idea,
allowing an author to specify preference hints of the type <em>"when the media is screen and max-width is 767px, I would
like to display elements #foo, #bar and #bat as tabsets if possible".</em> At some low level it simply allows the user to manage
a special attribute based on a media query from outside the markup and it desugars into existing platform code
in JavaScript something like this:
<pre class="example highlight">/* This is basically a possible approach today */
matchMedia("screen and (max-width: 767px)").addListener(function(evt) { <br>
var element = Array.prototype.slice.call(document.querySelectorAll("#foo, #bar, #bat")); <br>
elements.forEach(function (el) { <br>
if (evt.matches) { <br>
el.setAttribute("preferrential-display", "tabset"); <br>
} else { <br>
el.removeAttribute("preferrential-display"); <br>
} <br>
}); <br>
})</pre>
</p>
<p>
However, this would be a bit more than you'd like to manage in terms of boilerplate, and order should probably follow selector
specificity if they have a generic means to add these, and so we can introduce a new API to manage it - something like this:
</p>
<pre class="example highlight">CSS.associateDisplayPrefernce({ <br>
mediaQuery: "screen and (max-width: 767px)", <br>
selector: "#foo, #bar, #bat", <br>
preference: "tabset" <br>
});</pre>
<p>
This is considerably more conveneint, but ideally you'd be able to express this in CSS itself in a way that is familliar ala something like:
</p>
<pre class="example highlight">@media screen and (max-width: 767px) { <br>
#foo, #bar, #bat { preferred-display: tabset; } <br>
};</pre>
<p>For example,
it might be possible to offer a Preferrential Display for <code><select-timezone></code> elements
which provides a map-like interface similar to those used for choosing timezones in a desktop interface,
but ultimately provides a common <code><select></code> view on the same DOM, or a <code><common-panel-set></code>
which can be displayed as any number of visualizations (tabset, accordion, deck or carousel, for example)
but has identical structures and accessibility concerns. It is useful then for an author to be able to
state "under these media conditions I prefer a tabset view if you have it".
</p>
<p>The design of this proposal is intended to be such that it introduces minimal new concepts, but offers
new capabilities which answer some existing questions, highlight the importance of this separation,
and provide new opportunities for experiementation.
</p>
<section>
<h2>Aims and Requirements</h2>
<ul>
<li>It should be possible to create an element which might have many different visual variations decided by CSS, solve issues like aria once.</li>
<li>It should be possible for an author of HTML to provide no additional information and get a default view that retains the meaning of that thing</li>
<li>It should be possible for an author of HTML to temporarily provide inline information (we do this with style attribute, for example,
or by manually attaching a class which would otherwise be attached dynamically) to verify that what they have renders as expected.</li>
<li>It should be easy for a designer to indicate different visuals in a "whole" way which doesn't require JavaScript authorship. This is a different role in many organizations. That is, it should be possible simply say "this element should opt to this display if possible under these media query conditions."</li>
<li>It should not inflate the payload of the CSS dramatically (see point above - preprocessors offer some author time facilities for this, but not runtime - they are copy/paste use oriented)</li>
<li>It should ideally not require an additional HTTP requests or inlining in the HTML.</li>
<li>It should not introduce wholly new semantics and complicated concepts for authors - minimal magic explainable by things in the platform today.</li>
</ul>
<em>To these points, what I am proposing is a single, display oriented attribute which is maintained via CSS which allows CSS to express informtation that it can select upon in normal fashion and allow experimentation with the various pieces of the platform that are already in place.</em>
</section>
<section>
<h2>Why not...</h2>
<ul id="whynot">
<li><em>Just use CSS as it is today?</em> - The authoring/maintenance of this approach is very painful. If you took something like the above examples, you'd be styling individual elements and pseudo-elements of instances without any hint in the CSS itself (aside from comments perhaps) about what it was styling (ie, I want to display '#foo' as a tabset under these conditions). The CSS winds up being excessively verbose (see <a href="#panelset-without-pd">Vanilla CSS example below</a>) and cannot be re-used in other stylesheets.. In other words, if you define an 'accordion' it's just a bunch of rules which mean accordion, there is no way from another stylesheet to say 'use those rules', you have no choice but to repeat them.</li>
<li><em>Just use CSS preprocessor?</em> - The authoring/maintenance of this approach is way better (see <a href="#panelset-cpreuse">preprocessor example below</a>), but it's authoring reuse, so the verbosity and difficult to understand still exists. If it takes 100 lines of CSS to define all of the aspects of a 'tabset' and 100 lines to define all of the aspects of an 'accordion', then you have to define when to use them with those lines in a Media Query. If you put your entire applications CSS into a single sheet which it can statically analyze, you'd have the best possible outcome with this approach, but it just isn't how a lot of things work, so you wind up with a lot of copies of the same rules and no runtime reuse...</li>
<li><em>Wait for CSS aliases, wouldn't they solve this?</em> - They would make the problem better, for sure. However, it requires you to define all of the aliases at once and then to style individual elements and pseudo-elements with aliases, so many of the same sorts of runtime problems above come into play. The author's mental model is more like 'now it should be type "x"' and then just use CSS as per normal and gain all of the normal benefits of CSS and reuse, so it's better if we can reflect that.</li>
<li><em>Just set a type attribute?</em> - Because a type is static, but if what we are giving is a rendering hint
and you are aiming for definiing what it -is- and then styling it, can be variable.</li>
<li><em>Manage a type attribute with DOM APIs in JavaScript?</em> - Because styling information about visual presentation
really belongs in CSS. There should be an explanation of the system in terms of these primitives, but they should
be aiming to describe a concept in the right part of the system, JS and CSS are not exclusive domains and the API
should be defined by a CSS WG proposal who is thinking about the larger problem.</li>
</ul>
</section>
<h3>Vanilla CSS example without Preferred Display</h3>
<pre id="panelset-without-pd" class="example highlight" data-include="panelset-without-pd.css" data-include-format="text"></pre>
<h3>Preprocessor authoring example without Preferred Display</h3>
<pre id="panelset-cpreuse" class="example highlight" data-include="panelset-cpreuse.less" data-include-format="text"></pre>
</section>
<section>
<h1>Preferred Display</h1>
<p>
An element's <em>Preferential Display</em> is determined by whether or not a Media Query has <em>activated</em> it.
If the preferential display has not been activated by a Media Query, setting it has no effect. Thus:
<br>
<pre class="example highlight">/* this has no effect as the rule's preferrential-display is not activated by a MediaQuery */ <br>
.foo { <br>
preferred-display: map; <br>
} <br>
<br>
/* this rule defines a preferrential-display which can be activated by a MediaQuery */ <br>
@media screen and (min-width: 767px) { <br>
#foo { <br>
preferred-display: tabset; <br>
} <br>
} <br>
</pre>
<br>
Upon activation, the media query relays the preferred display value to the preferred-display attribute in the DOM. This attribute is
settable in markup, like <code>type</code>, but once set is read-only except via the CSS provided interface. This design
allows that only a media query can cause CSS to change the DOM and simply prevents cycles which would normally prevent this sort of thing. Its presence in the DOM allows it to be
easily used in normal CSS and JavaScript to do simple adaptations. MediaQueryList and listners can be used to explain how this works
fairly well today.
</p>
</section>
</body>
</html>