A partial archive of discourse.wicg.io as of Saturday February 24, 2024.

Selector based on non-attribute “value”. Maybe :value pseudo?

noamr
2021-12-21

The following elements have an accessible “value” getter, but that value is not accessible as an attribute or as a selector:

  • textarea
  • output
  • button (maybe I forget a few additional ones)

This makes it harder to style based on their content, unlike their cousins - the input element, which changes its value attribute when its value is set.

The idea would be to have somsething like a .something:value$="123" selector, which would be similar to input.something[value$="123"] but would act upon whatever the value getter represents rather than the particular expression of that in the DOM. In the case of input elements the two would behave in the same way.

This is a suggestion similar to Text-content() CSS value akin to attr() - #16 by tomhodgins But more focused on a particular set of elements (form “listed” elements).

simevidas
2021-12-28

Could you give a practical example? How would you use this feature?

noamr
2021-12-28

Of course! Here is an example, where a “delete all” button would be hidden if a sibling output field has a zero value. Today you can only do this with an input or something else that has a value attribute.

<style>
#tasks #count:value^="0" + #delete {
  display: none;
}
</style>
<form id="tasks">
  <output id="count"></output>
  <button id="delete">Delete All</button>
</form>
<script>
  document.forms.tasks.elements.count.value = 0;
</script>
simevidas
2021-12-28

In this case you’re setting the value via JavaScript, which sets the value property, not the value attribute, so the [value="0"] attribute selector wouldn’t work either.

Demo: https://jsbin.com/zeduzah/edit?html,css,js,output

The [value="0"] selector only matches the element if the value="0" attribute appears in the HTML source code, I think.

noamr
2021-12-28

Of course, I know, that’s why I’m suggesting a new selector :slightly_smiling_face: The idea of the new selector is that it would work on things that have a value property but not necessarily a value attribute, like output/textarea.

MaxArt
2021-12-28

Small correction: as Šime is suggesting in his reply, the property that’s reflected on the value attribute is actually defaultValue, not value.

All in all, your proposal doesn’t seem to be quite security-prone. In the past, we had cases of applications that got exploited because the adopted framework use to reflect the value property of <input> elements on the value attribute, allowing CSS rendering attacks on password inputs (think of [value^='a'] + .x { background: url('a.gif') }. This proposal would lead to the same issue all over again.

What do you suggest to mitigate the problem?

noamr
2021-12-28

Good point re. the password element - I suggest to not enable this on password elements, but only on safer elements like textarea/output. It doesn’t have to have 1:1 mapping with all elements that have a value property, but rather reflect that concept.

bramus
2022-02-14

Would be nice to also have this on <select> elements, so that we can selectively show/hide succeeding form controls based on its value:

/* ❌ Doesn't work */
select[value="1"] ~ select[data-showwhen="1"],
select[value="2"] ~ select[data-showwhen="2"],
select[value="3"] ~ select[data-showwhen="3"],
select[value="4"] ~ select[data-showwhen="4"] {
  display: block;
}

For now, we can work around this using :has() (demo on CodePen, use Safari TP):

/* ✅ Works */
select:has(option[value="1"]:checked)  ~ select[data-showwhen="1"] { … }

Would be nice if select[value="…"] worked as well, as it’s easier to use. It’s also a less specific selector of (0,1,1) (vs (0,2,2) using :has()).