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

Descendant combinator breaks & selector #208

Open
Aokp82ES opened this issue Jul 5, 2024 · 0 comments
Open

Descendant combinator breaks & selector #208

Aokp82ES opened this issue Jul 5, 2024 · 0 comments

Comments

@Aokp82ES
Copy link

Aokp82ES commented Jul 5, 2024

Nested vectors using the Garden parent selector (&) wrapping a descendant combinator ( ) aren't rendered correctly.

Descendant combinators can be used with the :not() CSS selector. The Mozilla Developer Network (MDN) docs have this note with a:not(table a) as an example (<a> elements not inside a <table>):

Description

There are several unusual effects and outcomes when using :not() that you should keep in mind when using it:

  • ...
  • This selector will match everything that is "not an X". This may be surprising when used with descendant combinators, since there are multiple paths to select a target element. For instance, body :not(table) a will still apply to links inside a <table>, since <tr>, <tbody>, <th>, <td>, <caption>, etc. can all match the :not(table) part of the selector. To avoid this, you can use body a:not(table a) instead, which will only apply to links that are not descendants of a table.
  • ...

:not on MDN

If someone tries to write CSS statements for both a and a:not(table a) as a single value with Garden, they might try something like this:

(ns my-website.styles.anchor
  (:require
   [garden.core :refer [css]]
   [garden.selectors :as s]))

(def anchor-style
  (css
   [s/a
    {:color "blue"}
    [(s/& (s/not (s/descendant s/table s/a)))
     {:color "green"}]]))

This should result in the following CSS:

a {
  color: blue;
}

a:not(table a) {
  color: green;
}

Garden, however, renders this instead:

a {
  color: blue;
}

/*
  :not(...) isn't appended to a.
*/
a &:not(table a) {
  color: green;
}

Instead, users need to split the styles across 2 values to avoid using the & selector.

(ns my-website.styles.anchor
  (:require
    [garden.core :refer [css]]
    [garden.selectors :as s]))

(def anchor-style-pt-1
  (css
   [s/a
    {:color "blue"}]))

(def anchor-style-pt-2
  (css
   [(s/a (s/not (s/descendant s/table s/a)))
    {:color "green"}]))

This makes writing style mixins harder since they can't be combined into a single value for other places to consume.


As an extra, letting users use the & selector inside the :not() pseudoclass's selector list with the descendant combinator would be convenient. It would let people write mixins like this:

(ns my-website.styles
  (:require
    [garden.core :refer [css]]
    [garden.selectors :as s]))

(def outside-table-mixin
  [(s/& (s/not (s/descendant s/table s/&)))
   {:color "green"}])

(def anchor-style
  (css
   [s/a
    {:color "blue"}
    outside-table-mixin]))

(def button-style
  (css
   [s/button
    {:color "red"}
    outside-table-mixin]))

This would render to this:

a {
  color: blue;
}

a:not(table a) {
  color: green;
}

button {
  color: red;
}

button:not(table button) {
  color: green;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant