:read-write / :read-only

Avatar of Chris Coyier
Chris Coyier on (Updated on )

The :read-write and :read-only selectors are two mutability pseudo-classes aiming at making form styling easier based on disabled, readonly and contenteditable HTML Attributes. While the browser support is not that bad, the various implementations are quite wonky.

According to the official CSS Specifications, a :read-write selector will match an element when:

  • it is either an input which has readonly nor disabled attributes.
  • it is a textarea which has neither readonly nor disabled
  • it is any other editable element (thanks to the contenteditable attribute)

Syntax & Example

/* Any element that is not writable */
:read-only { }

/* ... so you might want to scope it */
input:read-only, 
textarea:read-only,
[contenteditable]:read-only {
  cursor: not-allowed;
}

/* Any enabled text input 
   or enabled textarea 
   or element with the contenteditable attribute */
:read-write {
  background: white;
  cursor: text;
}

Browser support

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
363*No139

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
1231241239.0-9.2

There is a major difference between what is recommended in the specifications and what the browsers actually do. For instance, if we stick to the specs, every element which is user-editable but disabled (disabled or readonly) or simply not user-editable should be targeted by an unqualified :read-only selector.

ChromeFirefoxSafariOpera
input:read-write:read-write:read-write:read-write
input[disabled]:read-write:read-write:read-write:read-write
input[readonly]:read-only:read-only:read-only:read-only
[contenteditable]:read-write:read-only
*:read-only:read-only

Meanwhile, only Firefox seems to do so, and apparently not too well either since it considers a disabled input as :read-write. Regarding Opera not tagging a contenteditable element as :read-write, it’s simply because it doesn’t support contenteditable.