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

Children selectors #1984

Closed
jenstornell opened this issue Jun 29, 2020 · 18 comments
Closed

Children selectors #1984

jenstornell opened this issue Jun 29, 2020 · 18 comments

Comments

@jenstornell
Copy link

jenstornell commented Jun 29, 2020

To prevent repetition both in CSS and HTML we can use a component. However, when working with static lists it may not be a good idea to have every list item as a component.

A simplified example below:

<ul>
  <li class="bg-red-500 hover:bg-red-700 rounded text-sm text-white">Home</li>
  <li class="bg-red-500 hover:bg-red-700 rounded text-sm text-white">About</li>
  <li class="bg-red-500 hover:bg-red-700 rounded text-sm text-white">Projects</li>
  <li class="bg-red-500 hover:bg-red-700 rounded text-sm text-white">Hello</li>
  <li class="bg-red-500 hover:bg-red-700 rounded text-sm text-white">World</li>
  <li class="bg-red-500 hover:bg-red-700 rounded text-sm text-white">Foo</li>
  <li class="bg-red-500 hover:bg-red-700 rounded text-sm text-white">Bar</li>
  <li class="bg-red-500 hover:bg-red-700 rounded text-sm text-white">Tail</li>
  <li class="bg-red-500 hover:bg-red-700 rounded text-sm text-white">Wind</li>
<ul>

For static lists like this you could split the data into an array and keep the classes as a variable. It's a bit more hassle and not always as readable.

Solution - Child selectors

Let's take the first example again:

<ul class="bg-red-500> hover:bg-red-700> rounded> text-sm> text-white>">
  <li>Home</li>
  <li>About</li>
  <li>Projects</li>
  <li>Hello</li>
  <li>World</li>
  <li>Foo</li>
  <li>Bar</li>
  <li>Tail</li>
  <li>Wind</li>
<ul>
  1. When need to change a class, you only do that in one place.
  2. It should only affect direct children, not grand children.
  3. Children classes on the li should override the child class set in the ul.
  4. I put > last as class names needs to start with a letter.
  5. Very similar to the current Tailwind syntax.

Cons

I can only come up with one con at the moment.

  1. It would probably double the filesize of the CSS file before purge.
@royvanv
Copy link

royvanv commented Jul 1, 2020

I think > is the worst character to use, to be fair. Something like children:bg-red-500 would be my preference.

Also, in your example both text-sm and text-white can be set on the parent <ul> tag and need no child selector class.

@jenstornell
Copy link
Author

I had children: in my first draft. There are two reasons why I changed my mind:

  1. The line of classes was getting quite long.
  2. It collides with hover: for example children:hover:bg-red-500.

Note that because of how these screen variants are implemented in Tailwind you can't combine breakpoints with dark mode using this approach, for example md:dark:text-gray-300 won't work. This is something we're hoping to address with official dark mode support in a future release.

https://tailwindcss.com/docs/breakpoints/

Because > is also part of a HTML tag, that character may not be perfect. What about @?

<ul class="@hover:bg-red-500"></ul>

You are however right about that text-white is inherited. I just added a bunch of classes to illustrate my point. Real scenarios elements will have a different set of classes.

@royvanv
Copy link

royvanv commented Jul 1, 2020

1. The line of classes was getting quite long.

If it bothers you, you could always use @apply in your preprocessed CSS.

2. It collides with hover: for example children:hover:bg-red-500.

Note that because of how these screen variants are implemented in Tailwind you can't combine breakpoints with dark mode using this approach, for example md:dark:text-gray-300 won't work. This is something we're hoping to address with official dark mode support in a future release.

https://tailwindcss.com/docs/breakpoints/

This seems to only apply to breakpoints, as they are both relying on a media query.

I would still prefer the prefix children, as it seems more in line with Tailwind's other class names.

@nternetinspired
Copy link
Contributor

Text colour and size are inherited, why not just set them on the parent?

<ul class="text-sm text-white">
  <li class="bg-red-500 hover:bg-red-700 rounded"></li>
  <li class="bg-red-500 hover:bg-red-700 rounded"></li>
</ul>

@adamwathan
Copy link
Member

No plans to add this to core right now, instead I would recommend using this plugin:

https://github.com/benface/tailwindcss-children

Can revisit this some time in the future if there is an overwhelming demand for it 👍

@HenrijsS
Copy link

Well that seems unfortunate.
Is there an option to just use @apply for the children? For example:

ul {
  li {
    @apply flex;
  }
}

@royvanv
Copy link

royvanv commented May 28, 2021

You could use postcss-nested to nest selector similar to SCSS/SASS.

@jenstornell
Copy link
Author

@HenrijsS I use https://www.npmjs.com/package/postcss-nesting because then it uses the syntax that probably will be implemented as native CSS in the future.

ul {
  & li {
    @apply flex;
  }
}

@ixartz
Copy link

ixartz commented Jul 9, 2021

No plans to add this to core right now, instead I would recommend using this plugin:

https://github.com/benface/tailwindcss-children

Can revisit this some time in the future if there is an overwhelming demand for it 👍

@adamwathan, in tailwind 2.2, you've introduced the peer selector: https://tailwindcss.com/docs/just-in-time-mode#sibling-selector-variants

Why not children selector in JIT mode?

There are some reference #3922 and #277 about children selector with JIT mode.

@adamwathan
Copy link
Member

Not opposed to it just takes some set aside time to properly design the best version of that feature. The "peer" feature for example wasn't a 5 minute thing, and is miles different in terms of how it works and the power it affords than the way anyone had implemented that before in plugins or any of the Tailwind spin-off projects out there.

Have a bunch of other higher priority work right now but definitely can think about it again when there's time.

@deadcoder0904
Copy link

Cool @adamwathan 👍

Take a look at my use-case using CSS Grid under the answer's comment where it'll be helpful to me -> https://stackoverflow.com/a/68509649/6141587

@benjaminhoffman
Copy link

For those that came here from nextjs by trying to style your Image component, I found these resources helpful:

@timothyis
Copy link

Just to add an idea to this thread, I just wanted to add some classes to all anchors inside of a nav element and would have found this feature really helpful if there was some kind of child combinator "modifier" (quotes because, I was thinking of it like you can use hover: etc.

Might be a cool idea in the future to do something like:
child:bg-sky-600 translates into something like selector > * { background: rgb(14 165 233/var(--tw-bg-opacity)) }

@Arturexe
Copy link

Tailwind needs a child selector. It would make life so much easier.

@RobinMalfait
Copy link
Contributor

@Arturexe here is a quick little plugin you can add if you need this behaviour: https://play.tailwindcss.com/h7eDGStsE9?file=config

@josias-r
Copy link

With TW 3.1, it's now also possible using arbitrary variants:
https://tailwindcss.com/docs/hover-focus-and-other-states#using-arbitrary-variants

@HenrijsS
Copy link

With TW 3.1, it's now also possible using arbitrary variants: https://tailwindcss.com/docs/hover-focus-and-other-states#using-arbitrary-variants

Don't know how I missed this. Looks amazing!

The problem is that it's not available through search, so I managed to miss it.

@Sleepful
Copy link

Sleepful commented Oct 7, 2022

arbitrary variants allows Descendant combinator by using a _ instead of a (white space). It's in the docs but took me a while to find.

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