Tailwindcss: How to use peer pseudo-class to detect existence of peers? - css

I'm trying to create a generic input component that rounds it's corners based on what's around it. Normally this works using the first: and last: pseudo-classes but there is one case where the label is a peer to the input so it should be fully rounded.
I think what I need to do is identify what the peer element is and then styling according. How can I use the custom peer selector to identify if a peer exists in tailwind?
<div class="flex flex-col">
<label hmtlFor="email" className="peer-[label]">Email</label>
<input id="email" class="peer-label:only-of-type:rounded-3xl rounded-none bg-green-400" />
</div>
Tailwind Playground: https://play.tailwindcss.com/PzMukUDQuX
^ The playground shows what I'm fully trying to do, but for this question, just need to figure out how the custom peer syntax is supposed to work.

is this what you are looking for?
https://play.tailwindcss.com/erZse7TDD4
explanation:
I am not sure peer would work here because:
the span is not aways there
the label is not a peer of the input it is a peer of the parent container of the input.
I used a bunch of complex selectors which works but not sure it is the best solution here. I think you can do something similar via code when you render the items if you are using react.
Edit: improved code and further selector explanation.
One change I would make is wrapping everything with a div as the last 3 elements had and removing the rounded corners. that gives a generic html like below and we can focus only on the first and last child:
<div class="flex flex-col">
<!-- label -->
<div>
<!-- maybe a span here -->
<!-- there is aways an input here -->
<!-- maybe a span here -->
</div>
</div>
now we can take advantage of something called arbitrary variant values.
now we apply the below selectors directly to the wrapping div:
"[&>*:first-child]:rounded-l-3xl"
// which is apply rounder left (rounded-l-3xl) to any (*) first child (:first-child) directly descendant (>) of myself (&).
"[&>*:last-child]:rounded-r-3xl"
// which is apply rounder right (rounded-r-3xl) to any (*) last-child (:last-child) directly descendant (>) of myself (&).
the resulting is: https://play.tailwindcss.com/K3vSiUxa4V
EDIT2: without arbitrary values:
similar effect without arbitrary variants:
https://play.tailwindcss.com/Yup53pmaS4

Related

how to alternate based on how many specific parents deep a child is nested

I would like to select a child if it is a specific number of specific (eg. .specialid) parent elements away from a specific (eg. .specialchild) child element.
example (selecting .specialchild under odd nestings of .specialid:
<span>ignored</span>
<div class="specialid"><!--odd - select-->
<span>ignore</span>
<span class="specialchild">not ignored</span><!--do not ignore b/c odd parent of .specialid-->
<div class="specialid"><!--even - do not select-->
<div>
<div>
<span class="specialchild">ignored</span><!--ignore-->
</div>
</div>
<div class="specialid"><!--odd - select-->
<span class="specialchild">not ignored</span><!--do not ignore b/c odd parent of .specialid-->
<span>ignored</span><!--ignore-->
</div>
</div>
<div><!--not .specialid, so ignore in even-odd toggle-->
<div class="specialid"><!--even - select-->
<span class="specialchild">ignored</span><!--ignore b/c even parent of .specialid-->
</div>
</div>
</div>
EDIT: If needed, I am open to JavaScript alternatives. (but no JQuery)
EDIT 2: visual: I am making a dark theme chrome extension, and i am using css filters to do it. when applied over each other, they cancel out. the element with the white background and the metal wolf thing, since it has a background image set, has the filter applied over it as well, thus keeping it from looking weird. However, my profile icon is located inside this element, and <img> tags are also filtered again to cancel out the effect. this is where the problem begins. this then leaves it with three filter effects, two of which cancel out, and leaving the image inverted. i am attempting to solve this issue for elements no matter how deeply they are nested. btw im using javascript to detect the background image and add a data- attribute to it.
EDIT i just figured out that i could also just have it so that all children of odd nestings of .specialid can be selected EXCEPT another nested .specialid, without even referencing .specialchild
Ok, first of all, you can't have repeated ID's as ID's are used for unique elements. In order to correct your code you'd have to do something like this:
<span>ignored</span>
<div class="specialid"><!--odd - select-->
<span>ignore</span>
<span class="specialchild">not ignored</span><!--do not ignore b/c odd parent of #specialid-->
<div class="specialid"><!--even - do not select-->
<div>
<div>
<span class="specialchild">ignored</span><!--ignore-->
</div>
</div>
<div class="specialid"><!--odd - select-->
<span class="specialchild">not ignored</span><!--do not ignore b/c odd parent of #specialid-->
<span>ignored</span><!--ignore-->
</div>
</div>
<div><!--not #specialid, so ignore in even-odd toggle-->
<div class="specialid"><!--even - select-->
<span class="specialchild">ignored</span><!--ignore b/c even parent of #specialid-->
</div>
</div>
</div>
Honestly, I am not really sure what you're trying to achieve with this code, and the structure is a little strange, but I would probably recommend using definitions like these:
To refer to odd .specialid elements.
.specialid:nth-child(odd) { ... }
To refer to odd .specialchild child element of odd .specialid
.specialid:nth-child(odd) > .specialchild:nth-child(even) { ... }
To refer to odd .specialid elements inside odd .specialid elements
.specialid:nth-child(odd) .specialid:nth-child(even) { ... }
I am not sure what else you're trying to achieve but you should work on your HTML structure first.
I was able to answer my own question:
:not(.specialid) *:not(.specialid) .specialid *:not(.specialid) .specialchild{
/*styles*/
}

CSS BEM syntax without element class name

I have to create a primary heading component, below is my markup along with CSS classes. I'm following BEM naming convention for class name.
I have h1 element consists of two spans. One span for main heading text, and second span for sub heading text. The main and sub are variations of my heading.
I have not specified the Element class (Which could be heading-primary__text ) and i have directly attached modifier classes to span elements.
<h1 class="heading-primary">
<span class="heading-primary--main">Video Background Option</span>
<span class="heading-primary--sub">One Page Parallax</span>
</h1>
Is that a right way to follow BEM methodology without specifying Elements classes & attaching Block's modifiers classes to Elements(span)? Because i don't need elements classes.
Is there any alternate?
While this is subjective, and as per the convinience of the project . i'd recommend doing something like this- as you already have a header-primary_text element class
<h1 class="heading-primary">
<span class="heading-primary_text">Video Background Option</span>
<!--create a modifier -->
<span class="heading-primary_text--sub">One Page Parallax</span>
</h1>
In this way you can make the sub a modifier class for the subtext.
More info can be seen here https://en.bem.info/methodology/quick-start/#modifier
Hope this helps :)
I think there is a much simpler way to do this just using basic HTML. You only want to have one h1 per page and since you said that your second span of your h1 is a "subheading" I feel like you would be way better off marking that one as an h2 instead of two spans of different context within one h1 heading! Always good to use the built in benefits of HTML first if you can.
No, it is not the right way. You cannot use block (or element) modifier alone on the HTML tag without specifying the block (or element) class itself.
Please refer to BEM documentation here: https://en.bem.info/methodology/quick-start/#modifier
A modifier can't be used alone From the BEM perspective, a modifier
can't be used in isolation from the modified block or element. A
modifier should change the appearance, behavior, or state of the
entity, not replace it.
Here is a code example from the docs:
<!-- Correct. The `search-form` block has the `theme` modifier with the value `islands` -->
<form class="search-form search-form_theme_islands">
<input class="search-form__input">
<button class="search-form__button">Search</button>
</form>
<!-- Incorrect. The modified class `search-form` is missing -->
<form class="search-form_theme_islands">
<input class="search-form__input">
<button class="search-form__button">Search</button>
</form>
You mentioned that you don't need an element class, this topic is also covered in BEM docs
https://en.bem.info/methodology/faq/#why-include-the-block-name-in-modifier-and-element-names
semuzaboi's suggestion sounds as a good alternative to me.
First of all, elements are specified after two __ like block__element_modifier.
Secondly, yes. Blocks may not have any elemenets inside, but rather have modifiers (most common case a block with lang modifiers for Internationalization (block_lang_ru))
PS as well as element may not have any modifiers inside. But block can not be nested inside another one. They should be placed inside one directory on the same level.

How can I select an element by an attribute set on its parent using CSS 2.0 selectors?

I have a HTML like this in my QWebView
<div class='a' id='root'>
<div id='x'>...</div>
<p> ...
<p>
...
<div id='x2'>...</div>
<div>
<a href='go/xxxx'>go</a>
</div>
</div>
How do I select the a? I tried this selectores:
div[id='root'].a
div[id='root'] + a
but it didn't worked. Code:
QWebFrame* frame = webView->page()->mainFrame();
QWebElement button = frame->documentElement().findFirst("div[id='root'].a");
assert(!button.isNull()); // gets executed
Your selector is selecting the div with id='root' and class='a'. If you want to select the a tag inside of that div, you need to make your selector:
div[id='root'].a a
The additional 'a' at the end of the selector tells jquery to select the a inside of the div.
You can switch to using XPath 2.0 in Qt to have more expressive freedom, but then you need to process your HTML as XML.
To resolve, add a descendant selector1 for a. I.e., change this div[id='root'].a into this:
div[id=root].a a
As an alternative, if there's a bug in Qt, try:
div[id=root][class=a] a
Or (which is potentially a bit wider):
div[id~=root][class~=a] a
These last two are just alternatives in case for some reason the original fix to your code (adding the a descendant selector) didn't work.
The code snippets above doesn't use quoted strings, this is optional.
1 adding a was seen in stevenc4's answer), after my original (wrong) solution. Kudos to him :)

Selecting terminal elements

Is there a way to select elements that are not parents of any dom (of the type written as <...>)? I know that individual characters may count as dom, but ignoring that, I want to select the terminal nodes. In the following, <div id=2> would be such element but <div id=1> would not.
<div id=1>
<div id=2>
Hello World
</div>
</div>
Unfortunately, this isn't possible with a CSS selector. You need to find another way around it depending on what you're trying to achieve.
For the record, the :empty pseudo-class won't work here because it only matches an element that doesn't have any text or element children, not even whitespace. Since your second-level div contains text, it is not :empty.

Adding :last-child or :last-of-type to nav menu

Normally CSS is my thing, but I'm somehow dumbfounded why this isn't working for me. I'm building a site through Cargo for CMS purposes and you can see it here: http://cargocollective.com/mikeballard
In my menu, I have five main categories, and clicking on them (images, for example) reveals the list of work under that category.
<div id="menu_2444167" class="link_link">
<a id="p2444167" name="mikeballard" target="" href="http://cargocollective.com/mikeballard/filter/images">Images</a>
</div>
<div id="menu_2444188" class="project_link">
<a name="mikeballard" rel="history" href="mikeballard/#2444188/Ultra-Nomadic-Def-Smith-Cycle-2011">Ultra Nomadic Def Smith Cycle, 2011</a>
</div>
<!-- more divs here -->
<div id="menu_2444201" class="project_link">
<a name="mikeballard" rel="history" href="mikeballard/#2444201/Archive">Archive</a>
</div>
Basically, I'm trying to select the last div in this set, and add a margin-bottom:15px to that div. I've tried using:
.project_link:last-child or .project_link:last-of-type but it doesn't seem to be working.
The HTML, which can't be altered too much to rely on Cargo, isn't great as if they had used list items, instead of divs with anchor tags I'm assuming this would be a lot easier.
The :last-of-type and :last-child selectors are not supported before IE9.
Class names, etc are not looked at when it comes to the :last-child and :last-of-type selectors. The .project_link:last-child selector will only trigger if the specific element is the last child in the parent element and has the class "project_link", and the .project_link:last-of-type selector will only trigger if the specific element is the last element of that type and has the class "project_link".
Both should trigger in a supporting browser, since it is implied as *.project_link:last-of-type and will check for every type of element inside that parent (which appears to only be divisions anyways). The last division shown here has the class "project_link" which would match this rule. The only reason these wouldn't trigger is if you had extra elements (or divisions) below what you're showing us, or you're using a browser which doesn't support it.

Resources