I have the following SCSS code:
input[type="checkbox"] {
...
&:read-only, &[readonly] {
cursor: default;
filter: grayscale(1);
}
}
That is being applied to
<input type="checkbox" id="checkbox" onChange={this.rememberMe} />
CodePudding user response:
- Because
<input type="checkbox" />
and<input type="radio" />
(and most other elements) are inherently read-only. - Unlike an
<input type="text" />
or<input type="date" />
, when you interact with (i.e. toggle) a checkbox or radio button you are not changing itsvalue
, you are changing itschecked
state. - Yes, I agree it's counter-intuitive.
Consequently...
- You should not apply the
<input readonly
attribute to aradio
orcheckbox
for any purpose.- Because it won't do anything useful.
- You should not define a CSS selector that uses the
:read-only
pseudo-class to select<input>
elements that have an explicit HTML<input readonly
attribute set.- Instead use the has-attribute-selector:
input[readonly]
. - It's probably a good idea just to avoid using the
:read-only
pseudo-class entirely because it also selects pretty-much every HTML element on the page too; a function with little practical utility, imo.
- Instead use the has-attribute-selector:
Now, if you want a "read-only checkbox/radio" then you don't have too many good options, unfortunately; instead you have a mix of terrible options and barely-adequate ones...:
- There is this popular QA, however most of the highest-voted answers have suggestions that I think are bad ideas: such as depending upon a client-script to block user-interaction ...very imperfectly (from people who are ignorant of the fact a radio and checkbox can be manipulated in far, far more many ways than just
onclick
), or using CSS'spointer-events: none;
while completely disregarding the fact that computer keyboards both exist and are regularly used by human computer operators. - The least worst suggestion, I think, is using
<input type="checkbox/radio" disabled />
, as demonstrated with this answer. (The<input type="hidden">
is necessary because disabled (and unchecked) inputs are not submitted, which is another violation of the principle of least astonishment by the then-nascent browser vendors of the late-1990s.
If you want to use the :read-only
pseudo-class on all input
elements except radio and checkboxes then you need to think carefully (and test it too, using variations on document.querySeletorAll("input:read-only")
in your browser's console!)
I recommend that you do not apply any styles using selectors for input
elements without also explicitly specifying the [type=""]
attribute selector - this is because styles with a selector like "input
" (without any attribute-selectors) will be applied to future HTML input elements that we don't know about yet and could be introduced at any point in the near-future, and maybe next week Google Chrome adds a new <input type="human-dna-sample" />
or Microsoft adds <input type="clippy" />
to a particularly retro edition of their Edge browser - so you definitely don't want a :read-only
style applied to those elements until you at least know how it will look and work - and so the browser will use its default/native styling which won't violate your users/visitor's expectations if they happen to come across it on your website at some point.
...so it means you need to write out rules for every known <input type="...">
as repetitive input[type=""]
style rules, and now you might wonder if there were any pseudo-classes for input
elements based on their default native appearance because a lot of them sure do look share similar, if not identical, native appearance and visual-semantics (and shadow DOM structure, if applicable) - for example in desktop Chrome the input types text
, password
, email
, search
, url
, tel
and more are all clearly built around the same native textbox widget, so there surely must be a pseudo-class for different input "kinds", right? Something like input:textbox-kind
for text
, password
, etc and input:checkbox-kind
for checkbox
and radio
- unfortunately such a thing doesn't exist and if introduced tomorrow the W3C's CSS committee probably wouldn't approve it for a few more years at least - so until then we need to explicitly enumerate every input[type=""]
that we know about so that we can accurately anticipate how browsers will render them with our type=""
-specific style rules instead of throwing everything as input {}
and seeing what sticks.
...fortunately the list isn't too long, so I just wrote the rules out just now:
Feel free to copy paste this; it's hardly even copyrightable. And I want to see how far this spreads across the Internet in my lifetime.
At the bottom is a CSS selector that will select only <input
elements that are from the future by using an exhaustive set of :not([type="..."])
selectors, as well as not matching input
elements with an empty type=""
attribute or missing one entirely.
/* Textbox-kind: */
input[type="text"]:read-only,
input[type="password"]:read-only,
input[type="search"]:read-only,
input[type="tel"]:read-only,
input[type="url"]:read-only,
input[type="email"]:read-only,
input[type="number"]:read-only {
background-color: #ccc;
cursor: 'not-allowed';
}
/* Date/time pickers: */
input[type="date"]:read-only,
input[type="datetime-local"]:read-only,
input[type="time"]:read-only,
input[type="week"]:read-only,
input[type="month"]:read-only {
background-color: #ccc;
cursor: 'not-allowed';
}
/* Button-kind (these are all practically obsolete now btw, as the <button> element is far, far, far superior in every way) */
input[type="button"]:disabled,
input[type="reset"]:disabled,
input[type="submit"]:disabled,
input[type="image"]:disabled {
background-color: #ccc;
border: 1px outset #666;
cursor: 'not-allowed';
color: #666;
text-shadow: 0 1px rgba(255,255,255,0.2);
}
/* Checkbox-kind (Don't use `:read-only` with these): */
input[type="checkbox"]:disabled,
input[type="radio"]:disabled {
/* I'm not setting any properties here because it's impossible to effectively style these elements without resorting to image-replacements using the `:checked` state in selectors for their parent or adjacent `<label>` or ::before/::after` of other proximate elements. */
}
/* Weird-stuff-kind: */
input[type="color"]:read-only,
input[type="file"]:read-only,
input[type="hidden"]:read-only,
input[type="range"]:read-only {
/* Again, due to differences in how different browsers and platforms display (and consequently style) these inputs I don't think it's worth doing anything. */
}
/* If you **really** want to select _future_ <input> elements in-advance... do this: */
input[type]:not([type="text"]):not([type="password"]):not([type="search"]):not([type="tel"]):not([type="url"]):not([type="email"]):not([type="number"]):not([type="date"]):not([type="datetime-local"]):not([type="time"]):not([type="week"]):not([type="month"]):not([type="button"]):not([type="reset"]):not([type="submit"]):not([type="image"]):not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="file"]):not([type="hidden"]):not([type="range"]) {
}