76

In CSS it is possible to style placeholder text within an input using a combination of vendor-specific pseudo-classes and pseudo-elements (to get the best cross-browser coverage).

These all share the same basic properties (ie: text styling and color declarations).

However whilst I inevitably want to apply the same styles irrespective of browser vendor, it doesn't appear to be possible to combine these together into a comma-separated selector (as you would with any other piece of CSS where you want two selectors to share the same styles).

As an example, I tend to target placeholder styling using the four following selectors:

  • input:-moz-placeholder
  • input::-moz-placeholder
  • input:-ms-input-placeholder
  • input::-webkit-input-placeholder

(although :-moz-placeholder is being deprecated in favor of ::-moz-placeholder this only occurred with the release of FireFox 19 so at present both are needed for better browser-support).

What's frustrating is that declaring and giving each (the same) style leads to a lot of repetition within the CSS.

So, to make sure that placeholder text is right-aligned and italic, I would end up with:

input:-moz-placeholder{
    font-style: italic;
    text-align: right;
}
input::-moz-placeholder{
    font-style: italic;
    text-align: right;
}
input:-ms-input-placeholder{
    font-style: italic;
    text-align: right;
}
input::-webkit-input-placeholder{
    font-style: italic;
    text-align: right;
}

What I really want to do is to combine them as one single comma-seperated rule set like this:

input:-moz-placeholder,
input::-moz-placeholder,
input:-ms-input-placeholder,
input::-webkit-input-placeholder{
    font-style: italic;
    text-align: right;
}

However, despite trying this on a fair few occasions, this never seems to work. It makes me concerned that there's some fundamental part of CSS that I'm not understanding.

Can anybody shed any light on why this happens?

Timwi
  • 61,190
  • 29
  • 155
  • 224
johnkavanagh
  • 4,416
  • 2
  • 23
  • 37

2 Answers2

75

CSS2.1 states:

The selector (see also the section on selectors) consists of everything up to (but not including) the first left curly brace ({). A selector always goes together with a declaration block. When a user agent cannot parse the selector (i.e., it is not valid CSS 2.1), it must ignore the selector and the following declaration block (if any) as well.

Note that since CSS2.1 pre-dates CSS3, "it is not valid CSS 2.1" is written under the assumptions that a user agent is fully CSS2.1-compliant and that CSS3 does not exist in theory. In practice, wherever the spec says "it is not valid CSS" or something to that effect, it should be taken to mean "it is not understood by the user agent". See my answer to this related question for a more in-depth explanation.

Namely, since one vendor's browser doesn't understand other vendors' prefixes, it has to drop any rules that contain those unrecognized prefixes in pseudo-class and pseudo-element selectors.1

For some insight as to why such a rule was put in place, see this answer.


1 Note that WebKit is notorious for partially flouting this rule: it has no trouble parsing rules whose selectors have unrecognized prefixed pseudo-elements (which in this case is ::-moz-placeholder). That said, the :-moz-placeholder pseudo-class in your combined rule will cause it to break anyway.

BoltClock
  • 630,065
  • 150
  • 1,295
  • 1,284
  • Thank you, very thorough and makes perfect sense. Still quite frustrating! Just for your future reference: `:-moz-placeholder` pseudo-class was [only depreciated relatively recently](https://developer.mozilla.org/en-US/docs/Web/CSS/:-moz-placeholder) with the introduction of FireFox 19 so sadly both `:-moz-placeholder` and it's double-coloned successor `::-moz-placeholder` have to be used at present to ensure best browser coverage. – johnkavanagh Jun 07 '13 at 11:08
14

The specs say that if a user agent doesn't recognize part of a selector, it has to ignore the whole selector and its block.

http://www.w3.org/TR/css3-syntax/#rule-sets

The selector (see the Selectors module [SELECT]) consists of everything up to (but not including) the first left curly brace ({). A selector always goes together with a {}-block. When a user agent can't parse the selector (i.e., it is not valid CSS3), it must ignore the {}-block as well.

Alessandro Vendruscolo
  • 12,889
  • 4
  • 29
  • 38
  • The link here didn't work for me (in not leading to the cited text); I found this one: . IMO, there should be no problem to _parse_ selector lists like `input:-moz-placeholder,:-any-other-bogus-selector`, so the rule **should** work, and browsers which drop it do so in violation of the rules. – Tobias Mar 15 '16 at 14:58