Skip to content

Commit

Permalink
[css-ui-4] Revamp the definition of 'user-select'
Browse files Browse the repository at this point in the history
The previous definition was more a list of open questions than a
definition. This definition takes a stand, and attempts to
find a sensible middle ground between existing implementations.
Differences between existing implementations are mentioned
as issues against the proposed definition, rather than open questions.
  • Loading branch information
frivoal committed Mar 31, 2015
1 parent a0fa7ff commit 1c0b6c9
Showing 1 changed file with 83 additions and 91 deletions.
174 changes: 83 additions & 91 deletions css-ui-4/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -100,113 +100,107 @@ Abstract: This is a delta specification over CSS-UI Level 3.
Name: user-select
Value: auto | text | none | element | all
Initial: auto
Inherited: yes
Applies to: all elements except replaced elements
Inherited: no
Applies to: all elements
Media: interactive
Computed value: See below
</pre>

Issue: In Firefox, -moz-user-select is not inherited by absolutely positioned elements,
but in Safari and Chrome,
-webkit-user-select is inherited by those elements.
In IE, it is not an inherited property.

Issue: Some browsers (Safari at least) select and copy not only text,
but also images.
Should we make this property apply to (some) replaced elements as well?
In Firefox it applies to buttons,
but not in Safari and Chrome (where buttons always behave like ''user-select/none''.
I am tempted to make it apply to all elements, and the UA stylesheet to deal
with form controls. What it does when you copy&paste the selection and it contains
non textual elements (images? videos?) is out of scope for this specification,
but I see no reason why this property should not apply to such elements.

The computed value is the specified value,
except on elements containing editable text
except on <a>editable element</a>s
where the computed value is always ''user-select/element''
regardless of the specified value.

Issue: Prefixed implementations disagree on the computed value of ''user-select/auto''.
In Webkit and Blink, it computes to ''user-select/text''.
In IE, it computes to ''user-select/text'' on editable elements;
on other elements, if the parent element's is ''user-select:none''
it computes to ''user-select/none'',
otherwise it computes to ''user-select/text''.
In Firefox, it computes to ''user-select/auto'' with the same meaning as text on most elements,
but to ''user-select/none'' on &lt;buttons>, and to ''user-select/text'' on &lt;input>
(and maybe other things, I could not find documentation and have not run extensive tests)
regardless of the specified value,
and when the specified value is ''auto'',
which computes one of the other values as defined below.

For the purpose of this specification,
an <dfn>editable element</dfn> is either
an <a href="https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#editing-host">editing host</a>
or a <a href="http://www.w3.org/TR/html/forms.html#mutability">mutable</a> form control with textual content,
such as <{textarea}>.


<dl dfn-type=value dfn-for=user-select>
<dt><dfn>auto</dfn>
<dd>The computed value of ''auto'' is determined as follow:
<ul>
<li>If the element is an <a>editable element</a>
the computed value is ''element''
<li>Otherwise, if the element is not absolutely positioned
and the computed value of 'user-select' on the parent of this element is ''all'',
the computed value is ''all''
<li>Otherwise, if the element is not absolutely positioned
and the computed value of 'user-select' on the parent of this element is ''none'',
the computed value is ''none''
<li>Otherwise, the computed value is ''text''
</ul>

Note: This unusual combination of a non inherited property with an initial value of ''auto''
whose computed value depends on the parent element
makes it possible to create what is effectively selective inheritance.
This was initially proposed by Microsoft in IE to introduce a behavior similar to inheritance
except that the ''element'' value does not inherit.
This also enables the behavior introduced by Mozilla in Firefox where absolutely positioned
children do not inherit from their parent.

<dt><dfn>text</dfn>
<dd>The element imposes no constraint on the selection.

Issue: Webkit's documentation claims that
auto selects anything,
while text it means only select text,
but this does not appears to be true
since ''user-select/auto'' computes to ''user-select/text'',
and you can select tables (in both chrome and safari)
and images (in safari) anyway.

Issue: Do we really need both ''user-select/text'' and ''user-select/auto''?
In Webkit/Blink, the two values
are redundant. While in Firefox they are not. However, the way firefox uses
auto could be replace by UA styles.
Issue: Shouldn't we call this "normal" instead? The selection
is not restricted to textual elements, and may contain tables, images...
The webkit documentation claims their implementation of text only selects text,
while auto selects anything,
but sine webkit computes ''auto'' into ''text'',
this does not match reality.

<dt><dfn>none</dfn>
<dd>users cannot select the content of the element.

Note: ''user-select/none'' is not a copy protection mechanism,
<dd>Users cannot select the content of the element.
No selection may be started in this element.

However, if this element has descendants on which the computed value of 'user-select' is not ''none'',
these descendants can be selected.

A selection started outside of this element may not end in this element.
If the user attempts to create such a selection,
the UA must instead end the selection range at the element boundary.

Issue: As of the time of writing, experimental implementations do not all behave like this.
Firefox does.
Chrome and Safari almost do: for a selection started after the element
and trying to go backwards into the element
they behave as specified here,
but for a selection started before the element
and trying to go into the element
they behave as if the element has ''all'' and select it entierly.
IE does not restrict selections started outside of the element
from going into it at all.

A selection may extend across this element.
In this case, browsers which support multiple ranges per selection
may exclude this element from the selection.
If the element has descendants on which 'user-select' does not compute to ''none'',
these descendants must be included in a selection extending across the element.

Note: ''none'' is not a copy protection mechanism,
and using it as such is ineffective:
it will have no effect on legacy User Agents that do not support it,
and the user can disable it through the user style sheet or equivalent mechanisms
on UAs that do anyway.
Instead, ''user-select/none'' is meant to
Instead, ''none'' is meant to
make it easier for the user to select the content they want,
by letting the author disable selection on UI elements
that are not useful to select.

<div class=issue> In IE,
it only prevents the selection from starting on that element,
but it will not block an existing selection from entering the element.
Other browsers do block an existing selection from entering the element
(mostly. Webkit&Blink's behavior isn't that straightforward),
though they differ in terms of
what happens when an existing selection extends across the element.
We have a few options:
<ol>
<li>Do as IE does.
This is the simplest,
and avoids complications for selections that extend across an element.
It may not be what authors want though.
<li>Prevent selections from ending in the element
and from extending across it,
stopping the selection range at the element boundary.
<li>Prevent selections from ending in the element
but allow extending across it,
and excplicitly include the content the element in such selections.
<li>Prevent selections from ending in the element
but allow extending across it,
and leave undefined whether to include the content the element in such selections,
allowing browsers with multi-range selections to skip it,
while others would include it.
</ol>
An interesting subcase is when the ''user-select/none'' element
has a non ''user-select/none'' child. Can the selection go from
outside of the element to inside the child?
</div>


<dt><dfn>element</dfn>
<dd>A selection which is started in this element
may not be extended outside of this element.

Issue: If the user tries to create a selection
that starts outside and ends inside, what happens?
What about starting outside and ending across?

Issue: children inheriting the ''element'' value seems wrong.
How about selections that extend across this element?
At the time of writing, browsers behave differently.
The behavior can be observed even on browsers that do not explicitly support ''element''
by trying to select into / across from a &ly;textarea>.

<dt><dfn>all</dfn>
<dd>The content of the element must be selected atomically:
Expand All @@ -219,20 +213,18 @@ Abstract: This is a delta specification over CSS-UI Level 3.
If this element has descendants on which the computed value of 'user-select' is not ''all''
and if a selection is entirely contained in these descendants,
then the selection is not extended to include this whole element.

Issue: What happens if descendants of an ''all'' element are ''none''?
That depends on what we say about selections that extend across a ''none'' element.
</dl>

Issue: IE has an auto value (which is the initial value)
where if the element contains editable text
such as an input element or contenteditable element,
the text is selectable,
but otherwise selection is determined by the parent node’s value.
Should we have this?
The approach taken by this spec is
to have the property be inherited (it isn't in IE),
and have user-select compute to ''element'' on editable elements.
Note: Selections can include more than just text and extend over images, tables, videos, etc.
The behavior when copying and pasting a such selections is out of scope for this specification.

The following additions are made to the UA stylesheet for HTML:
<pre><code class="lang-css">
button, meter, optgroup, progress, select { user-select: none; }
</code></pre>

Issue: the list above is incomplete, and needs to include
at least the various button-like variants of <{input}>.

<hr title="Separator from footer">

Expand Down

0 comments on commit 1c0b6c9

Please sign in to comment.