Can't use children with :not pseudo selector - html

I'm having trouble using some relatively simple CSS selectors using :not. Namely, the following selector is giving me an error:
a:not(.ebook_document *)
I am trying to get all <a> elements that are not children of the element with class ebook_document. This also fails:
a:not(.ebook_document > *)
As well as this:
a:not(.ebook_document, *)
Putting the selectors on their own, not in a :not section works fine. What have I done wrong?

:not only takes a simple selector. (For now, CSS 4 expands that to a selector list.)
Plus, https://developer.mozilla.org/en/docs/Web/CSS/:not -
This selector only applies to one element; you cannot use it to exclude all ancestors. For instance, body :not(table) a will still apply to links inside of a table, since will match with the :not() part of the selector."
What you want is not possible using :not.
You can only go about it the other way around - format all "normal" links, and then apply different formatting for the links inside the target element(s) using .ebook_document a { ... }
So that means rather than not applying styles to those links in the first place, you might need to overwrite the styles you don't like for those links again.
(Or use initial/all to actually reset styles, but browser support for that is still lacking AFAIK.)

Hmm shouldn't it just be a:not(.ebook_document)? I didn't test it but it seems that that should reference all the a tags that don't have a .ebook_document tag.

Related

How to filter HTML elements based on the parent

I need to apply a function to checkbox elements that are not part of a bootstrap-multiselect element. To do this I'm trying to make a css selector that fitlers out based on the parent they have. The syntax that I have so far is this:
$(this).find("input[type='checkbox']:not(ul.multiselect-container>input)")
Where the :not(ul.multiselect-container>input) is my attempt to specify to the css selector that I want all css elements except for the ones that are children of an unordered list that has the class multiselect-container.
From doing some investigation it seems that this should be possible, but my syntax doesn't seem to cut it. How can I make this work with the :not function? OR perhaps another way.

Is it possible to select elements that do not have a child of a certain type?

I'm trying to select <a> elements that are not the parents of <img> elements. (Note: if it's relevant some of the anchors I want to select are childless.) I tried this:
a > :not(img) {}
and this:
a:not(> img) {}
but neither of them seem to work. How would I accomplish this in CSS?
There is a spec, currently in draft, for a :has() pseudo-class. No browser supports it yet. If the spec is someday approved and implemented, you'd be able to do this:
a:not(:has(img)) {
// Styles
}
The MDN page says that :has would never work in stylesheets, only in JavaScript; but in saying that, it links to a section of the spec about a "dynamic selector profile" that apparently no longer exists.
I think the browser vendors typically have a problem with implementing CSS features that require knowledge of the DOM that only exists after the selected element is created, so I don't know if we should get our hopes up for this. Someone who follows the mailing lists or is generally smarter than me might offer a better prognosis.
Unfortunately, no. You'd need to use jQuery.
You could do some kind of workaround using CSS:
Assign a class to links that do not have child elements that are images and use that class to style the links as normal (e.g. a.class{color: red})
Assign a class to links that do have an image child element, and use a:not(.class){} to change their color
Reason: There is no parent selector in CSS. See:
Is there a CSS parent selector?, CSS Parent/Ancestor Selector

CSS: Hide parent if all children are hidden

I have a list with groups in it, and use CSSOM to dynamically filter the contents using a text field. This is a way to implement a "search" using only CSS.
Unfortunately when the filter filters everything out, the group containers still remain visible. I'd need to also set display: none onto them using CSS somehow, otherwise I need to add a bunch of JS to control them.
Is this remotely possible? I know this is a big of a long shot, but is there a selector that can select elements whose children (fitting some selector) all must have a style selected on them?
Is it even possible if I greatly relax the constraints, where this might be a selector that selects elements whose children (fitting some selector) all must have a particular class?
No, it's impossible only via CSS:
There is no parent selector.
There is no visibility selector, except something like :not([style*="display:none"]):not([style*="display: none"]) if you hide elements only using inline CSS.
There is no CSS way to know if all children satisfy some condition.
This can be solved only using pure JS loops and conditions or via jQuery selectors like .parent:not(:has(:visible)).

Using CSS selectors to get first child from a nested element

I am trying to understand CSS selectors better and am fiddling around with Google/Gmail. When you go to Google's home page and enter "gmail", it will automatically present you with search results for that term. I want to write a CSS selector that will find the first one (that is, the link to Gmail, since it should always be the first result). The HTML for these results looks like:
<div class="srg">
<div class="g">
<h3 class="r">
Gmail - Google
...
Based on what I could gather from the W3schools CSS docs, it seems like I want the first <a> child of a class named r, or:
h3.r a:first-child
However, the tool I'm using doesn't recognize this as the first link. So I ask: is this a correct selector for the Gmail (first) link, or did I go awry somewhere?
Well, the anchor element you're referring to is the only child of the h3.r parent.
So :first-child, :last-child and :only-child would all apply.
A simple h3.r > a (child selector) or h3.r a (descendant selector) should suffice, assuming it's unique in the document.
Your selector – h3.r a:first-child – should, technically speaking, work as well.
Based on the image above, an attribute selector may also work:
h3.r a[data-href="https://mail.google.com/"]
More information: https://www.w3.org/TR/css3-selectors/#selectors
Within Geb, you can also use
`$("h3.r").find("a")[0]
to select the first child.
Using :first-of-type is very similar to :nth-child, but there is a critical difference: it is less specific.
In the example above, if we had used p:nth-child(1), nothing would happen because the paragraph is not the first child of its parent (the <article>). This reveals the power of :first-of-type: it targets a particular type of element in a particular arrangement with relation to similar siblings, not all siblings.
Reference: https://css-tricks.com/almanac/selectors/f/first-of-type/

CSS first-child and last-child don't work when used on the same element

I just noticed that CSS :first-child and :last-child don't work when used on the same element. Only one is used. I'm wondering why is that and if there is any workaround to that in CSS? It seems like CSS bug to me - first element can be also last element.
I couldn't find anything in Google on that subject. Each tutorial assumes that there will be at least 2 elements.
I'm looking for something like: "first child is also last child" selector. Does it exist?
I'm wondering why is that and if there is any workaround to that in CSS? It seems like CSS bug to me - first element can be also last element.
It's not a bug. It's how the cascade works: if an element is both the first child and the last child, then if you have :first-child and :last-child in separate rules and they both match the same element, then anything in the later declared or more specific rule will override the other.
You can find an example of this behavior here, with the border-radius shorthand property, and workarounds that include using the component properties instead of the shorthand, as well as specifying a separate rule altogether using one of the following selectors...
I'm looking for something like: "first child is also last child" selector. Does it exist?
Literally, you would chain both pseudo-classes like this, which works fine:
:first-child:last-child
However there exists a special pseudo-class that acts the same way:
:only-child
The main difference (in fact, the only difference) between these two selectors is specificity: the first one is more specific as it contains one additional pseudo-class. There is no difference even in browser support, as :last-child and :only-child are both supported by the exact same versions of each browser.
I realise I'm massively late to this, but you can also use is CSS's :first-of-type and :last-of-type. For example:
<blockquote>
<p>Some text you want to quote</p>
</blockquote>
This CSS will add quotes to the paragraph:
blockquote{
quotes: "“" "”" "‘" "’";
}
blockquote p:first-of-type:before{
content:open-quote;
}
blockquote p:last-of-type:after{
content:close-quote;
}