The CSS :lang() selector targets elements within documents that do not specify a particular language

Can elements that do not have a language set or inherited, meaning they are in an unspecified ("unknown") language, be targeted?

Facts

The language of an HTML document or element can be specified using the HTML lang attribute, for example:

<html lang="en">
<h1>Dictionary</h1>
<dl>
<dt><abbr lang="en-Mors">-... - .--</abbr>
<dd><i lang="fr-Latn">à propos</i>
</dl>

or by including code(s) in the HTTP Content-language header:

HTTP/2 200 OK
[other headers]
Content-language: en,en-Brai,fr-Latn

<html>
<h1>Dictionary</h1>
[rest of document]

or using the deprecated, yet still functional <meta http-equiv> tag:

<html>
 <head>
  <meta http-equiv="content-language" content="en,en-Brai,fr-Latn">
</head>
<html>
<h1>Dictionary</h1>
[rest of document]

In all cases, the CSS selector :lang(en) would target the main heading and other elements with no explicit lang attribute set to "en".

Objective

If a document is sent without the Content-language HTTP header or <meta> element, and without a lang attribute, is it possible to target elements in the inevitable "unknown" language?

Furthermore, can the lang() CSS selector be used to match elements with an empty lang="" attribute, effectively opting out of having a language?

HTTP/2 200 OK
[no content-language header or meta present]

<html>
<p>I Want to select this. <span>And this.</span></p>
<p lang="">And this.</p>
<p lang="en">Not this. <span lang="">But this again.</span></p>

Methods that Do Not Work

Neither :lang(), :lang(unknown), :lang(''), nor :not(:lang(*)) work for this purpose. Selectors such as :not([lang]), [lang=''] would logically result in false negatives for scenarios involving the HTTP Content-language header/meta.

Answer Criteria

We are looking for an answer that either provides a solution without false negatives or confirms that it is impossible, with references to specifications (or their absence), along with an explanation of why this is the case.


Additional Notes:

When targeting the empty lang="" attribute, using the selector [lang=""] works, but may seem awkward given the dedicated :lang() pseudo-class for language-related selections.

Answer №1

Update 2021: After thorough investigation, this issue is now recognized as a bug here


We incorporate language range in the :lang() rule and they are compared against language tags. There have been mentions of supporting asterisks in language ranges:

Language ranges containing asterisks should be either correctly escaped or quoted as strings, for instance: :lang(*-Latn) or :lang("*-Latn") reference

In an old draft from 2013:

Each language range in :lang() must be a valid CSS identifier [CSS21] or consist of an asterisk (* U+002A) immediately followed by an identifier beginning with an ASCII hyphen (U+002D) for the selector to be valid. reference

However, I am unable to make p:lang(\*-US) work on Windows in Chrome and Firefox. While the rule p:lang(en\002DUS) functions correctly, p:lang(en\002D\002A) does not. The support for the special range "*" in browsers remains uncertain. Moreover, there is no indication of matching "undefined" with the special range "*" in Matching of Language Tags.


Nonetheless, p:lang(\*) and p:not(:lang(\*)) operate effectively on iPadOS across Safari and Chrome. Test it out on iPad by visiting this jsfiddle
https://i.stack.imgur.com/omNKB.png
It appears that chromium may lack complete support for the :lang() feature.


Solution: If utilizing a bit of JavaScript is feasible, consider the following workaround:

document.addEventListener('DOMContentLoaded', init);

function init() {
  if (!document.documentElement.lang) {
    fetchSamePageHeaders(checkHeaderLanguage);
  }
}

//make a lightweight request to the same page to get headers
function fetchSamePageHeaders(callback) {
  var request = new XMLHttpRequest();
  request.onreadystatechange = function() {
    if (request.readyState === XMLHttpRequest.DONE) {
      if (callback && typeof callback === 'function') {
        callback(request.getAllResponseHeaders());
      }
    }
  };

  // The HEAD method asks for a response identical to that 
  // of a GET request, but without the response body.
  //you can also use 'GET', 'POST' method depending on situation      
  request.open('HEAD', document.location, true);
  request.send(null);
}

function checkHeaderLanguage(headers) {
  //console.log(headers);
  headers = headers.split("\n").map(x => x.split(/: */, 2))
    .filter(x => x[0]).reduce((ac, x) => {
      ac[x[0]] = x[1];
      return ac;
    }, {});

  if (!headers['content-language']) {
    console.log('No language in response header. Marking the html tag.');
    let html = document.querySelector('html');
    html.lang = 'dummyLang';
  } else {
    console.log('The response header has language:' + headers['content-language']);
  }
}
p {
  margin: 0;
}

p[lang=""],
p:lang(dummyLang) {
  color: darkgreen;
  font-size: 2em;
}

p:lang(en\2dus)::after {
  content: '<= english';
  font-size: 0.5em;
  color: rebeccapurple;
}
<p>I Want to select this.</p>
<p lang="">And this.</p>
<p lang="en-us">Not this.</p>
<span lang='en-us'>
    <p>Also, not this.</p>
    <p lang="">But, this too.</p>
</span>


Here, JavaScript is used to determine whether the language is mentioned in the HTML tag or the response header. It assigns the language "dummyLang" to the HTML tag. Consider checking meta tags as well.
For a detailed explanation on retrieving HTTP headers in JavaScript and the advantages and disadvantages of this approach, refer to this discussion on Stack Overflow.

Answer №2

After brainstorming, I've devised a clever solution. Firstly, you can execute some JavaScript code to assign the "xyz" language attribute to all elements that do not have one. Then, you can target those elements using CSS...

document.querySelectorAll("p").forEach(e => {
  if (e.lang == "") e.lang = "xyz";
})
p:lang(xyz) {
  color: red;
}
<p>I Want to style this.</p>
<p lang="">And this.</p>
<p lang="en">But not this.</p>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide to creating animated sections using only CSS as you scroll the webpage

I am searching for a method to add animation effects (using @keyframes, transform...) to certain elements as the user scrolls down the page. For instance: When the offset is 0: the div will have a height of 100px. When the offset is between 0 and 100: th ...

Tips for using JavaScript to style an array items individually

I have currently placed the entire array within a single div, but I would like to be able to display each element of the array separately so that I can style "date", "title", and "text" individually. This is my JSON structure: [ { "date": "Example ...

Incorporate a pseudo class to a unique custom template or directive within an Angular project

I have been developing a custom dropdown menu directive in AngularJS. The issue I'm facing is that the buttons in my template become inactive when interacting with the dropdown menu, unlike a regular HTML select which remains active while the dropdown ...

Creating a table with a tableHead cell comprised of multiple components in ReactJS/CSS using Material UI

It's possible that the title lacks description. I am attempting to generate a table with a specific layout like this Essentially, the "Average" cell is combined with two smaller cells for "height" and "width," which can be subdivided further. Unfortu ...

The mysterious behavior of CSS3 transforms on intricate rotations

When a div is viewed in perspective and has the transformations rotateY(-90deg) rotateX(-180deg), adding rotateZ(-90deg) to it results in a rotation of +270 degrees instead of -90 degrees. The new style of the div changes from transform: rotateY(-90deg) ...

How can I specifically target and count children from a certain class using CSS selectors?

Consider this HTML structure with items arranged at the same level: <div class="h2">Title: Colors</div> <div class="pair">Hello world (1)</div> <div class="pair">Hello world (2)</div> <div class="pair">Hello wo ...

Using Jinja2/Python, is it possible to alter the parent's style depending on the child's value?

Initially, I found that the :has() combinator accomplishes my desired outcome. In my HTML, I have a table structured like this: <table class="table"> {% for dict_item in data | sort(attribute='name') %} <tr class=" ...

I am looking to add some flair to my ID "checkimg" using JavaScript

JavaScript if ((valid1 && valid2 && valid3 & valid4 && valid5 && valid6 && valid7 && valid8)==1) { // include an image in the specified ID. document.formElem.next1.disabled=false; } else { docume ...

Select the five previous siblings in reverse order using jQuery's slice method

I have a unique approach to displaying a series of divs where only 5 are shown at a time using the slice() method. To navigate through the items, I include an ellipsis (...) link after every 4th item, which allows users to easily move on to the next set of ...

Setting up a responsive footer using Bootstrap and responsive design involves following a few key steps

Seeking assistance with making the footer of my website responsive using a combination of Bootstrap and custom CSS. I am aiming for a result similar to the examples shown below, both optimized for Desktop and Mobile platforms. Your help in achieving this ...

Does Less undergo a compilation process in a single pass?

Does Less execute a single pass on the files, or does it perform multiple passes? I am particularly worried about what will happen if I include another file that redefines variables and mixins. Will the generated output use the original values, or will it ...

Is it necessary to restart the IIS Site when altering the contents of index.html?

I am currently working on updating a website that runs on a Custom Designed CMS with files using the .asp extension. The site seems to be quite dated and is hosted on an IIS Server, which I do not have direct access to. The user has requested some changes ...

Maximizing Content Width in FullCalendar v5 to Ensure Screen Compatibility

As I develop a calendar and timeline view using fullcalendar v5, my clients are requesting a month view that displays the entire month without any scroll bars. While I am aware of setting the contentHeight to auto, there seems to be no option for adjusting ...

Tips on automatically centering an image within a div as it is resized

I'm currently working on a website that showcases cards featuring Discord users. Each card includes an avatar image within a div element, and when the user hovers over it, the image expands. However, I've noticed that as it expands, it shifts to ...

What is the best way to define the width of text inside a div block?

I'm having trouble adjusting the width of the text in my code to only fill 80% of the body element. I've tried using both the width property and padding, but neither seems to be working for me at the moment. Here's the HTML: <body&g ...

Adjust the width of the table's td elements

I am looking to create a table similar to the one shown above. Here is my implementation. Please review my JSFiddle. HTML: <table border="0" id="cssTable"> <tr> <td>eredgb</td> <td><a href="self">0 ...

Centering <th> elements is key for achieving a visually appealing print layout

Is there a way to center align the header and body of a table when printing it? I am using datatable. Here is how it currently looks: Check out this screenshot I have tried adding classes to the th tags in the HTML table, but they still appear aligned t ...

Can you identify the specific name of the IE CSS bug affecting double vertical padding?

(Just when I thought I've encountered all the strange IE CSS bugs, here comes another one. Is there a name for this double-vertical-padding bug?) After creating a simple test case that worked perfectly in browsers like FF and Opera, I was surprised t ...

Tips for maintaining a sticky header while continuing to utilize Bootstrap table classes such as table-responsive and table-stripped

This is Here's my code on jsfiddle I've attempted to make the header sticky while maintaining the current layout, but every approach I've tried ends up messing with the responsiveness of the table. My next plan involves using a JavaScript ...

Cross-Platform: Varied functionalities in disabled input fields (avoiding any direct replication)

My input HTML field is disabled, but I've noticed that in some browsers (such as Chrome, Edge, Internet Explorer, and Opera), it's still possible to select and copy the text. However, in Firefox, this functionality does not work. To test this yo ...