Is the :before pseudo-element allowed on an input[type=checkbox]?
This is uncharted land; the specifications do not clear things up. The CSS 2.1 spec says:
“Note. This specification does not fully define the interaction of :before and :after with replaced elements (such as IMG in HTML). This will be defined in more detail in a future specification.” And, debatably, INPUT could be seen as a replaced element in CSS 2.1 sense.
One might think that these pseudo-elements cannot be used for elements that cannot have any content (i.e., with EMPTY declared content), such as IMG or INPUT. However, the wording mentions IMG, and Appendix D has a rule with the selector br:before
.
And CSS3 Selectors, one of the few parts of CSS3 that have reached recommendation status, does not clear things up. It says:
“The
::before
and::after
pseudo-elements can be used to describe generated content before or after an element's content. They are explained in CSS 2.1 [CSS21].”
Can I use a :before or :after pseudo-element on an input field?
:after
and :before
are not supported in Internet Explorer 7 and under, on any elements.
It's also not meant to be used on replaced elements such as form elements (inputs) and image elements.
In other words it's impossible with pure CSS.
However if using jquery you can use
$(".mystyle").after("add your smiley here");
API docs on .after
To append your content with javascript. This will work across all browsers.
Why is :read-only CSS pseudo-class being applied on this checkbox?
- 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:
From the current WHATWG HTML specification (emphasis mine, especially the last point):
https://html.spec.whatwg.org/multipage/semantics-other.html#selector-read-only
The
:read-write
pseudo-class must match any element falling into one of the following categories, which for the purposes of Selectors are thus considered user-alterable: [SELECTORS]
<input>
elements to which the<input readonly
attribute applies, and that are mutable (i.e. that do not have the<input readonly
attribute specified and that are not<input disabled
).<textarea>
elements that do not have a<textarea readonly
attribute, and that are not<textarea disabled
.- elements that are editing hosts or editable and are neither
<input>
elements nor<textarea>
elements.
- [i.e.
contenteditable
]- The
:read-only
pseudo-class must match all other HTML elements.
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"]) {
}
non-disabled checkbox being targeted by the :read-only pseudo element
I've found why this behavior is occuring.
According to the HTML standard
The :read-only pseudo-class must match all other HTML elements.
Here, the all other HTML elements refer to the html elements on which the :read-write
property does not apply.
On the same page, we can see what define an html element that is :read-write
-able.
The :read-write pseudo-class must match any element falling into one of the following categories, which for the purposes of Selectors are thus considered user-alterable:
input elements to which the readonly attribute applies, and that are mutable (i.e. that do not have the readonly attribute specified and that are not disabled)
textarea elements that do not have a readonly attribute, and that are not disabled
elements that are editing hosts or editable and are neither input elements nor textarea elements
The relevent part, here, is input elements to which the readonly attribute applies. If we check the HTML standard page for checkboxes, we can see that the readonly
attribute, indeed, does not apply.
The following content attributes must not be specified and do not apply to the element: accept, alt, autocomplete, dirname, formaction, formenctype, formmethod, formnovalidate, formtarget, height, list, max, maxlength, min, minlength, multiple, pattern, placeholder, readonly, size, src, step, and width.
Which makes the checkbox falls into the categories of html elements on which the :read-write
property cannot be applied. Hense the behavior of the original question's snippet.
While this does not explain how to bypass the behavior ( see ADITYA's answer ), It explains why it is occuring, which was the part I was originaly interessed in.
As an aditional note, I'm still not sure as why it the background-color was not working of the :read-only
element in Chrome 89.
CSS :after pseudo checkbox not working in IE or Firebug
:before
and :after
pseudo elements add new content before or after the target element's content. Since Input elements have no content; they just have a value. so technically we can't use pseudo element
for input
element.
so I guess in this case chrome
Browser is wrong. and IE
and Firefox
Browser are right.
you may have a look what w3c says.
css form checkbox styling with checked and after tags
The cross-browser solution that worked for me was to include an empty label (with class "checkbox_label") after the checkbox input and then style IT rather than the checkbox.
input[type=checkbox] + label:after
{
content: url(images/unchecked_after.gif);
position:relative;
left:0px;
top:1px;
z-index:100;
}
input[type=checkbox]:checked + label:after
{
content:"";
}
.checkbox_label
{
height:0px;
width:0px;
display:inline-block;
float:left;
position:relative;
left:20px;
z-index:100;
}
:before && :after pseudo elements not showing Firefox
You cannot use ::after
and ::before
on elements that cannot have content, such as <input />
or <img />
.
::after
and ::before
work like this:
<element>
::before
***content***
::after
</element>
<next-element>***content***</next-element>
They get inserted before and after the content of a DOM node. Since <input />
cannot have content, there's nowhere to put it.
Now let's check with a checkbox:
<input type="checkbox" />
<next-element>***content***</next-element>
Here, there cannot be ***content*** to surround with pseudo elements.
Related Topics
Animated Cursor Support in Web Applications
I Need an Overflow to Truncate from the Left, with Ellipses
Correct Terms and Words for Sections and Parts of Selectors
Comparison of Loading CSS Inline, Embedded and from External Files
3 Columns, Center Column Fixed, Sides Fill Parents
Why Doesn't Min() (Or Max()) Work with Unitless 0
Using Two CSS Classes on One Element
How to Change CSS Validation Scheme in VS2010
Using CSS to Make Table's Outer Border Color Different from Cells' Border Color
Put Background Image Over Text
Comma in CSS, Multiple Selectors Using the Same CSS
(Really) Long Background Image Does Not Render on iPad Safari
How to Align Items in a <H:Panelgrid> to the Right
How to Extend CSS Class with Another Style
How to Combine Two Media Queries
Equal Height of Elements Inside Grid Item with CSS Grid Layout