-1

The :lang selector is very different from all other selectors (AFAIK).

Other selectors only (directly) effect the actual matched elements themselves, whereas the :lang pseudo class is very different in that all elements within an element targeted by :lang selector are also directly targeted.

So let's say I place a border around an ul element - only the ul itself gets the border - not all of the list items (demo). Not so with :lang if I target that same ul which has an attribute of lang="en" - all of the list items will also get the border - to the extent that in order to override that rule (on the child !!) I have to use a selector with greater specficity (DEMO !!!).

:lang(en) {
  border: 5px solid red;
}
<ul lang="en">
  <li>item
    <li>item
      <li>item
        <li>item
          <li>item
</ul>

So I would like to know why the :lang selector was implemented in this very strange way. (apart from the fact that that's what it says in the spec) for the following reasons:

1) Counter-intuitive:

If we use the logic that all the descendants of the element with a lang attribute should be matched - because they share the same language - then conceptually the [lang] attribute selector should match in exactly the same way!

2) Not necessary:

a) Typically when dealing with different languages in a document you need to adjust text-related properties like font-family, font-size, color, quotes etc to suit the other language. The thing is that these properties anyway inherit such that by matching just the parent element element - all subsequent descendants get these changes. (demo)

b) If this functionality was necessary for some reason it could be achieved with the universal selector like so .parent,.parent * {} (demo)

Danield
  • 121,619
  • 37
  • 226
  • 255
  • **Disclaimer**: I had a go - unsuccessfully I think - at trying to work out what it was for [here](http://stackoverflow.com/q/35683530/703717) so I decided to ask this as a question in itself. – Danield Feb 28 '16 at 16:05
  • "Other selectors only (directly) effect the actual matched elements themselves" The :dir() pseudo-class works in much the same way. – BoltClock Feb 29 '16 at 04:28
  • I don't see how this is counter-intuitive. I would *expect* a child of a [lang=de] element to be in German just like the rest of the content within the element with the language declaration - simply because the child of that element is part of its content! Consider your example - would you not consider the li elements to be in English since they are in a ul element that is declared to be in English? – BoltClock Feb 29 '16 at 05:04
  • Related: [What's the difference between html\[lang=“en”\] and html:lang(en) in CSS?](http://stackoverflow.com/questions/8916360/whats-the-difference-between-htmllang-en-and-htmllangen-in-css) – BoltClock Feb 29 '16 at 05:04

3 Answers3

1

So I would like to know why the :lang selector was implemented in this very strange way.

It works that way because that's how we want it to work, most of the time. This way we can specify a language for the entire document, or for parts of the document, by putting the lang attribute just once at the top level.

For example, let's say I give a quoting rule for German (see this question):

q:before { content: open-quote; }
q:after  { content: close-quote; }

:lang(de) { quotes: "«" "»"; }

To make this work, I certainly do not want to have to apply the lang attribute to every single element throughout my HTML to which I might want to apply quotes. Instead, I need only apply it to the <html> element.

A semi-related example (see this question). Here we want the text-transform property to work properly with Greek. For that to happen requires the language to be known. Again, we can make this work properly by specifying the language for our entire page by putting lang='el' on the html element.

So let's say I place a border around an ul element - only the ul itself gets the border - not all of the list items (demo). Not so with :lang. If I target that same ul which has an attribute of lang="en" - all of the list items will also get the border (DEMO !!!).

Right, which is why you would not do things that way. If you want to target the ul, target it some other way, or if you must, you could use an attribute selector [lang='en'].

On the other hand, perhaps you wanted to make all Japanese text on a page red. If you've deployed the lang attribute correctly, that is a case where you would want to target using the :lang selector:

:lang(ja) { color: red; }
Community
  • 1
  • 1
  • I don't think the quotes example is a good one.Quotes seem to work even without the `:lang` selector. See [this demo](http://codepen.io/danield770/pen/XdWxpj) - notice the difference between the :lang selector and the lang attribute selector - but in both cases quotes work. – Danield Feb 28 '16 at 16:43
  • @Danield: The quotes property is inherited, so that is indeed not the best example. Actually, many CSS properties pertaining to text are inherited, and with good reason. But a selector is not a property, and selectors can be used outside of CSS altogether, so having a selector is still justified. – BoltClock Feb 29 '16 at 05:00
  • @BoltClock - actually *none* of the points mentioned here actually answer the question at all: the quotes,text-transform and color properties are all inherited and will work fine using say the `[lang]` attribute selector and don't need the special functionality of the `:lang` pseudo class ([demo](http://codepen.io/danield770/pen/oxNKKZ)) – Danield Feb 29 '16 at 09:46
  • @Danield: Like I said, that doesn't make the pseudo-class any less useful. Even in CSS it can still be useful with properties that don't normally inherit, such as a border. – BoltClock Feb 29 '16 at 10:02
  • If you wish to dispute the utility of the :lang pseudo you are free to do so on the relevant mailing list. The fact is that :lang can be used to match elements without having to rely on a document language-specific attribute or, in the context of CSS, inheritance. – BoltClock Feb 29 '16 at 10:09
  • @BoltClock - I updated the question with more concrete points - I can't think of one good use case for `:lang` to work like this. If anything a more generalized selector like :descendants() would be warranted. – Danield Feb 29 '16 at 10:09
  • @BoltClock - Don't get me wrong my point is NOT to dispute the selector, I just have a feeling that there's something more to it that I'm not getting which warranted the guys at w3c to justify it.... i'm *asking* not *complaining* – Danield Feb 29 '16 at 10:12
  • @BoltClock when writing this post I had some false premises about how :lang works, which I think I later understood [here](http://stackoverflow.com/a/35711431/703717) - so now I don't think that the post is productive. Would it be impolite to delete it? – Danield Mar 02 '16 at 11:32
  • 1
    @Danield: You would not be able to delete it as there is an upvoted answer. I think it's fine to keep as someone else might learn from your question and the answers given. You can still accept your own answer. – BoltClock Mar 02 '16 at 11:34
0

You're targetting every element with a lang set to en, and the lang value does inherit. But you want to only select the ul. So, simply add the ul selector, as you're supposed to, and would do with every other normal pseudo-selector.

ul:lang(en) {
  border: 5px solid red;
}
<ul lang="en">
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
</ul>

If you, for some reason, don't want to use the ul selector, use the attribute lang itself, since it does not inherit, like this:

[lang="en"] {
  border: 5px solid red;
}
<ul lang="en">
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
  <li>item</li>
</ul>
LarsW
  • 1,514
  • 1
  • 13
  • 25
0

There's nothing counter-intuitive with the :lang pseudo-class. All pseudo classes work this way in that they represent element states - so all elements in that particular state are targeted.

The [lang] attribute selector on the other hand will only select the elements themselves which have the attributes - because attribute selectors check for attributes not state.

Whether the :lang attribute is absolutely necessary or if its functionality could be achieved using other selectors might be debatable, but there's certainly nothing strange with the way :lang works.

Danield
  • 121,619
  • 37
  • 226
  • 255