Detect if an input has text in it using CSS -- on a page I am visiting and do not control?
It is possible, with the usual CSS caveats and if the HTML code can be modified. If you add the required
attribute to the element, then the element will match :invalid
or :valid
according to whether the value of the control is empty or not. If the element has no value
attribute (or it has value=""
), the value of the control is initially empty and becomes nonempty when any character (even a space) is entered.
Example:
<style>
#foo { background: yellow; }
#foo:valid { outline: solid blue 2px; }
#foo:invalid { outline: solid red 2px; }
</style>
<input id=foo required>
The pseudo-classed :valid
and :invalid
are defined in Working Draft level CSS documents only, but support is rather widespread in browsers, except that in IE, it came with IE 10.
If you would like to make “empty” include values that consist of spaces only, you can add the attribute pattern=.*\S.*
.
There is (currently) no CSS selector for detecting directly whether an input control has a nonempty value, so we need to do it indirectly, as described above.
Generally, CSS selectors refer to markup or, in some cases, to element properties as set with scripting (client-side JavaScript), rather than user actions. For example, :empty
matches element with empty content in markup; all input
elements are unavoidably empty in this sense. The selector [value=""]
tests whether the element has the value
attribute in markup and has the empty string as its value. And :checked
and :indeterminate
are similar things. They are not affected by actual user input.
You can use the :placeholder-shown
pseudo class. Technically a placeholder is required, but you can use a space instead.
input:not(:placeholder-shown) {
border-color: green;
}
input:placeholder-shown {
border-color: red;
}
<input placeholder="Text is required" />
<input placeholder=" " value="This one is valid" />
<input placeholder=" " />
Stylish cannot do this because CSS cannot do this. CSS has no (pseudo) selectors for <input>
value(s). See:
- The W3C selector spec
- The Mozilla/Firefox supported selectors
- Cross-browser, CSS3 support table
The :empty
selector refers only to child nodes, not input values.
[value=""]
does work; but only for the initial state. This is because a node's value
attribute (that CSS sees), is not the same as the node's value
property (Changed by the user or DOM javascript, and submitted as form data).
Unless you care only about the initial state, you must use a userscript or Greasemonkey script. Fortunately this is not hard. The following script will work in Chrome, or Firefox with Greasemonkey or Scriptish installed, or in any browser that supports userscripts (i.e. most browsers, except IE).
See a demo of the limits of CSS plus the javascript solution at this jsBin page.
// ==UserScript==
// @name _Dynamically style inputs based on whether they are blank.
// @include http://YOUR_SERVER.COM/YOUR_PATH/*
// @grant GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
introduced in GM 1.0. It restores the sandbox.
*/
var inpsToMonitor = document.querySelectorAll (
"form[name='JustCSS'] input[name^='inp']"
);
for (var J = inpsToMonitor.length - 1; J >= 0; --J) {
inpsToMonitor[J].addEventListener ("change", adjustStyling, false);
inpsToMonitor[J].addEventListener ("keyup", adjustStyling, false);
inpsToMonitor[J].addEventListener ("focus", adjustStyling, false);
inpsToMonitor[J].addEventListener ("blur", adjustStyling, false);
inpsToMonitor[J].addEventListener ("mousedown", adjustStyling, false);
//-- Initial update. note that IE support is NOT needed.
var evt = document.createEvent ("HTMLEvents");
evt.initEvent ("change", false, true);
inpsToMonitor[J].dispatchEvent (evt);
}
function adjustStyling (zEvent) {
var inpVal = zEvent.target.value;
if (inpVal && inpVal.replace (/^\s+|\s+$/g, "") )
zEvent.target.style.background = "lime";
else
zEvent.target.style.background = "inherit";
}