Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Selectors] Numeric or Typed Attribute Value and Pseudo Attribute Selectors #354

Open
Crissov opened this issue Jul 28, 2016 · 2 comments
Open
Assignees

Comments

@Crissov
Copy link
Contributor

Crissov commented Jul 28, 2016

The CSS WG Wiki already mentions numeric comparisons of attribute values for Selectors Level 4 (or 5). @LeaVerou brought it back up in November 2015 and cites a post by @alastc from January 2007. I’ve provided an overview of more or less intuitive operands in April 2011 which I will partially repeat below, so it gets properly tracked.

Existing attribute selectors

As of 2016, attribute values are matched as (parts of) character strings only.

  • = exact match

    We also have the i modifier suffix for explicit case-insensitive comparisons. I would have liked it better if that would have been the default (despite host language conventions) and == would have been used for case-sensitive values; or if a colon indicated a case-insensitive “pseudo” value =:. Please, let’s not add more single-letter grep-like suffixes.

  • ^= starts with

  • $= ends with

  • *= contains

  • ~= in (space-separated) list

  • |= exact or starts with followed by dash anything

    The pseudo-class :lang() already is more complex than what this similar attribute value operand allows for.

Proposed operands for attribute value selectors

Instead of complex :not() phrases, it would be handy to have negated comparisons, e.g.:

  • != or =! and !== or ==! or =!=
  • !~= or ~!= or ~=!
  • !|= or |!= or |=!
    *!^= or ^!= or ^=!
  • !$= or $!= or $=!
  • !*= or *!= or *=!

As mentioned in the intro, others have already noted that it would be useful to have numeric equality comparison where ‘0’ = ‘0.0’ = ‘.0’ = ‘00’ = 0x0 = ‘0e1’ = ‘’. Since we probably need to distinguish this from string comparisons explicitly, let’s just add another character:

  • #= or
  • == or
  • %= if also ‘0.5’ = ‘50%’

Numeric attribute selectors should be able to do simple greater and lesser than comparisons, of course. They’re not as useful for string comparisons, so we could spare the added character from above:

  • < = !>= or =!> but neither >!= nor >=!
  • > = !<= or <!= but neither =!< nor <=!
  • ‘≤’: <= or =< = !>
  • ‘≥’: >= or => = !<

I don’t think we’d need calc()-like dynamic arithmetic expressions on either side of the operand, because authors should be able to adjust the static selector value accordingly, although some might want to specify rounding or precision. With step-based values, follows and precedes may be useful:

  • ‘≺’: << or <=< or -=
  • ‘≻’: >> or >=> or +=

As has been correctly observed, not all such comparisons are between simple scalars. Dates and times can be converted to single numbers (e.g. in spreadsheet applications, Unix timestamps or Julian Day Numbers), but are usually expressed as tuples for human readability even in code (but at least usually within the same calendar system). Another case are strongly typed values with units, e.g. ‘25.4mm’ = ‘1in’ = ‘72pt’ in CSS, and yet another are values with multiple components or channels like colors, e.g. ‘#FF0000’ = ‘red’.

Preferably, these should just work when using a single equals sign = and literal comparison would be invoked by doubling it == (or tripling === if #= wasn’t accepted), but I’m fine with the inverse, too. If another, different character was needed to mark a comparison as possibly involving unit or base conversion (i.e. opt-in and don’t treat 2016-07-28 as 1981 or 28/7/16 as 0.25), I’ve previously suggested the underscore, but I think pseudo-attributes would actually be more useful:

  • _= etc.

A boolean or binary logic attribute selector could handle (case-insensitive) values like ‘yes’ = ‘true’ = ‘1’ = ‘on’ = attribute-name and ‘no’ = ‘false’ = ‘0’ = ‘off’ = null, possibly depending on the host language:

  • ?=

Pseudo-attribute selectors

I’ve previously mentioned an assertion attribute selector using := that could be used to test whether a value would be legal, but I can’t come up with a use case for it. Sub-values are more realistic, e.g. [color:red>50%] or [href:protocol=http] and these could be generalized to pseudo-attribute selectors, e.g. [:value], [:datetime], [:url] or [:class=foo] == .foo and [:name=foo] or [:ID=foo] == #foo.

@Crissov
Copy link
Contributor Author

Crissov commented Jan 26, 2021

Another useful attribute value selector would be in list, although this is already possible to express more verbosely:

@bramus
Copy link
Contributor

bramus commented Sep 12, 2022

To numerically compare attribute values today, authors can work around this by:

  1. Injecting all the values that the item is not equal to, using data-* attributes.
  2. Using the CSS Attribute “Value Contains” Selector (e.g. [attribute~=value]) on those data-* attributes.

I’ve detailed this nasty and cumbersome hack back in the day over at https://www.bram.us/2016/10/13/css-attribute-value-less-than-greater-than-equals-selectors/.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants