Asked  7 Months ago    Answers:  5   Viewed   30 times

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?

 Answers

67

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.

Tuesday, June 1, 2021
 
the_e
answered 7 Months ago
95

This depends on what you're actually trying to do.

If you simply wish to apply styles to a :before pseudo-element when the a element matches a pseudo-class, you need to write a:hover:before or a:visited:before instead. Notice the pseudo-element comes after the pseudo-class (and in fact, at the very end of the entire selector). Notice also that they are two different things; calling them both "pseudo-selectors" is going to confuse you once you run into syntax problems such as this one.

If you're writing CSS3, you can denote a pseudo-element with double colons to make this distinction clearer. Hence, a:hover::before and a:visited::before. But if you're developing for legacy browsers such as IE8 and older, then you can get away with using single colons just fine.

This specific order of pseudo-classes and pseudo-elements is stated in the spec:

One pseudo-element may be appended to the last sequence of simple selectors in a selector.

A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence.

A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.

A pseudo-class is a simple selector. A pseudo-element, however, is not, even though it resembles a simple selector.

However, for user-action pseudo-classes such as :hover1, if you need this effect to apply only when the user interacts with the pseudo-element itself but not the a element, then this is not possible other than through some obscure layout-dependent workaround. As implied by the text, standard CSS pseudo-elements cannot currently have pseudo-classes. In that case, you will need to apply :hover to an actual child element instead of a pseudo-element.


1 Of course, this does not apply to link pseudo-classes such as :visited as in the question, since pseudo-elements aren't links.

Tuesday, June 1, 2021
 
mdevils
answered 7 Months ago
42

Because the writer of Baseclass has explicitly declared that Bar has to be a read-only property. It doesn't make sense for derivations to break this contract and make it read-write.

I'm with Microsoft on this one.
Let's say I'm a new programmer who has been told to code against the Baseclass derivation. i write something that assumes that Bar cannot be written to (since the Baseclass explicitly states that it is a get only property). Now with your derivation, my code may break. e.g.

public class BarProvider
{ BaseClass _source;
  Bar _currentBar;

  public void setSource(BaseClass b)
  {
    _source = b;
    _currentBar = b.Bar;
  }

  public Bar getBar()
  { return _currentBar;  }
}

Since Bar cannot be set as per the BaseClass interface, BarProvider assumes that caching is a safe thing to do - Since Bar cannot be modified. But if set was possible in a derivation, this class could be serving stale values if someone modified the _source object's Bar property externally. The point being 'Be Open, avoid doing sneaky things and surprising people'

Update: Ilya Ryzhenkov asks 'Why don't interfaces play by the same rules then?' Hmm.. this gets muddier as I think about it.
An interface is a contract that says 'expect an implementation to have a read property named Bar.' Personally I'm much less likely to make that assumption of read-only if I saw an Interface. When i see a get-only property on an interface, I read it as 'Any implementation would expose this attribute Bar'... on a base-class it clicks as 'Bar is a read-only property'. Of course technically you're not breaking the contract.. you're doing more. So you're right in a sense.. I'd close by saying 'make it as hard as possible for misunderstandings to crop up'.

Thursday, June 3, 2021
 
edsk
answered 6 Months ago
22

If it's a problem with the not selector, you can set all of them and override the last one

li:after
{
  content: ' |';
}
li:last-child:after
{
  content: '';
}

or if you can use before, no need for last-child

li+li:before
{
  content: '| ';
}
Thursday, July 8, 2021
 
Packy
answered 5 Months ago
26

A Ruby-Talk post suggests using the pdftk toolkit to merge the PDFs.

It should be relatively straightforward to call pdftk as an external process and have it handle the merging. PDF::Writer may be overkill because all you're looking to accomplish is a simple append.

Monday, September 20, 2021
 
AlterPHP
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share