CSS Adjacent Selector Issue - css

The HTML looks like this:
<div id="content_wide">
<div class="photo-center borderless"><img src="http://example.com/travel-path-map.png" alt="" title="" /></div>
...but for some reason I can't seem to target the photo-center div like this:
#content_wide + .photo-center { margin-top:10px }
Interestingly enough, a more general child selector works:
#content_wide > .photo-center { margin-top:10px }
Thoughts?

The div with the class photo-center is inside the div with the id content_wide so the child selector (>) works. The adjacent selector (+) would only work if they were next to each other, similar to this:
<div id="content_wide"><!-- content --></div>
<div class="photo-center borderless"><!-- more content --></iv>

In your posted code, .photo-center is a child of #content_wide, not a sibling.
The + is a sibling selector and the > is a child selector.
The sibling selector isn't working because the elements aren't siblings.

You can't use + because .photo-center is not an adjacent sibling of #content_wide, it's a direct descendant (a child), so you can use the child selector >.
According to the Mozilla docs for adjacent sibling selectors:
The + combinator separates two
selectors and matches the second
element only if it is immediately
following the first.
The child selector documentation says:
The > combinator separates two
selectors and matches the second
element only if it is a direct child
of the first.
Here is a jsFiddle demo of the above selectors, http://jsfiddle.net/YcHKm/1/

That's because .photo-center isn't adjacent to content_wide. It is a child of content_wide.
Here is an example of adjacent tags:
<h1>Test</h1>
<h2>Test</h2>
In this example, h2 is adjacent to h1. This way, the + selector should work.

Related

Nested relative selectors in :has()?

Say I have
<div id="outer-div">
<div class="inner-div"></div>
<div class="inner-div"></div>
</div>
I want to select outer-div
.outer-div:has(> .inner-div:has(+ inner-div)) {...}
does not work.
can I nest relative selectors like this anyway?
how best to select a parent with 2 specific children in it?
Thanks!
Oh - nesting cannot be done
The :has() pseudo-class cannot be nested within another :has().
https://developer.mozilla.org/en-US/docs/Web/CSS/:has
#outer-div:has(> .inner-div + .inner-div) works to select "a parent with a child who is a sibling" which is sufficient

CSS combinator not working - Differnce of one space?

I have two carousels on a page and need to style them differently. So I have this css combinator to style a child bootstrap element inside an id element...
#menuCarousel .carousel { ...
Which doesn't work as I expected. However, if I close the space like this...
#menuCarousel.carousel { ...
the styles are applied. According to W3Schools, there is meant to be a space so I'm thinking I'm doing something else wrong.
What's happening here y'all?
Thanks.
Just in case the html is important:
<div id="menuCarousel" class="carousel slide" data-ride="carousel" data-interval="false">
First off in this case the .carousel shouldn't be necessary at all, because IDs must be unique and that alone would be sufficient to select the div.
But to get down to your question, a space between CSS selectors will select a descandant element. Removing the space means to select the element with that class.
So #menuCarousel .carousel { ... says select all elements with the class carousel that are descendants of the element with the ID #menuCarousel.
#menuCarousel.carousel { ... means select the element that has the ID menuCarousel AND the class carousel.
(And on a side note, don't use w3schools to learn CSS. Use https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors)
The id= (#) and class= (.) are applying to the same element, so I would think they would have to be combined as #menuCarousel.carousel. Otherwise it would be looking for a .carousel under a #menuCarousel, wouldn't it?
So a space indicates a nested element like this
<div id="parent" class="parent">
<div class="child"></div>
</div>
#parent .child{background-color:blue;}
The above example would make the child element blue.
However two selectors without a space is used to select an element using two different selectors on the same element. So
#parent.parent{background-color:blue;}
Would make the parent element blue in the same way as just #parent

CSS get other set of elements when pseudo-selectors occur

Here's a short version of my html:
<div id="section1" class="section">...</div>
<div id="section2" class="section">...</div>
<div id="section3" class="section">...</div>
<div id="section4" class="section">...</div>
One of these sections will be a target for the :target pseudo-selector, and I currently want to select all siblings of the target. For one, I know that CSS has no "all siblings" selector, just the general ~ and the adjacent + sibling combinator.
So instead, I want to find out of there was a way (or closest way) for CSS to get another set of elements (in this case, the siblings) only if the pseudo-selector happened.
.section:target then .section:not(:target){
//apply to all .section not being the target
}
If I were to use jQuery, it's something like:
//if a section was a target
if($('.section:target').length > 0){
//get all sections that are not the target
$('.section:not(:target)').css({
//apply css to them
});
}
I have to note that the styles only happen if there is a target. If there's no target, then the styles should not be applied.

last child with element inside

I think this is impossible :-(
Using CSS, I need to select the last label in the list of paragraphs, which is inside of a span.
<div>
<p>
<span>
<label>no good, because not the last</label>
</span>
</p>
<p>
<span>
<label>good</label> <!-- This one should be selected -->
</span>
</p>
<p>
<label>no good, because is not inside of a span</label>
</p>
</div>
Virtually the selector would be something like this:
div (p > span):last-child label {
background: red;
}
But I don't think CSS understands parenthesis (yet).
The reason for this is that ExtJS (Sencha) puts radio buttons in nested containers. The visibility of buttons is declared in the inner containers (that would be the span tags in the example above). I want to round corners of the last VISIBLE label, thus I need to find the last outer container that has an inner container declaring it's visibility.
Perhaps there is a different workaround for this? As a last resort, I'd accept a JS solution, as long as it's based on native ExtJS components/elements traversing syntax, rather than jQuery.
Please ask for more detail if needed.
It will (maybe, depends on if the selector will be in the final spec) partly be possible with CSS 4:
!p > span {
background: red;
}
But this will select all <p/> that have a <span/> inside, not only the last one. CSS currently does not know a :last selector, and as far as I can see even with CSS 4 this won't be implemented1.
So the summary is: Currently there is no way to do this in pure CSS.
Currently your only option is to use JavaScript. A sample in jQuery would be:
$('p:has(span)').last().css({ 'background': 'red' });
Here is a demo.
Or, as you mentioned in your comment, with extjs:
Ext.select('p:has(span):last').setStyle('background', 'red');
Here is a demo.
Answer to your updated question
Your new example does not need a parent selector anymore. The partly working CSS would be
div > p > span > label {
background: red;
}
But still: There is no :last selector in CSS1. Updating the above JavaScript samples:
jQuery:
$('div > p > span > label').last().css({ 'background': 'red' });
extJS:
Ext.select('div > p > span > label:last').setStyle('background', 'red');
1 About the :last selector:
To make it more clear: :last-child selects the last child inside an element in the dom, whatever it is. It is no sub query. So, even if your parenthesis version would be implemented, :last-child would select nothing because the really last element is not part of the query. You would need a :last selector like in some JavaScript libraries which selects the last item of the resultset, so it's a sub query. This is a completely different selector and will not be part of CSS soon.

Why does this selector not work

Given the following markup
<div class="fixed">
<div class="clmn2">
</div>
<div class="clmn2">
</div>
</div>
And the information given on mdn
By my interpretation this selector should work.
*:not(.fixed) [class*="clmn"]
Unfortunately it does not, however this does.
div:not(.fixed) [class*="clmn"]
Any ideas why?
*Update *
If you check the linked fiddle the column in rows not marked with the class fixed should be floated.
*:not(.fixed) foo matches
A foo element that is a descendant of any element that is not a member of the fixed class
This is different to:
A foo element that is not a descendant of any element that is a member of the fixed class
If we had:
<a class="fixed">
<b>
<foo></foo>
</b>
</a>
Then the foo element is a descendant of a b element that is not a member of the fixed class. (It is also a descendant of an a element that is a member of that class, but that doesn't matter because *:not(.fixed) will happily match the b element instead.)
Your "bad" selector matches any element with a class as given that is a descendant of any element without class fixed.
Since both the <html> and <body> elements do not have the class fixed and your inner <div>s are their descendants, the selector matches them.
The "good" selector only considers descendants of any <div> that does not have the class fixed. Since the only <div> in your HTML that has descendants also has that class, the selector matches nothing.
In general, plain :not(whatever) followed by a descendant combinator is not really useful. In your case it looks like the solution would be to replace the "descendant" combinator with the child combinator >:
:not(.fixed) > [class*="clmn"]
Your selector is too general. Since * will also select things like body. And body is not(.fixed), the rule will still be applied.
Change it to something more specific like .row:not(.fixed).
http://jsfiddle.net/sVpTA/2/
CSS
.row:not(.fixed) [class*="clmn"]{
float: none;
width: 100%;
margin-left: 0!important;
}
Actually, it's working better than you want it to.
*:not(.fixed) matches, among other things, your body element. Eventually, somewhere within the body, it finds your clm* divs, and applies the styles.
If you only want to match things that are direct descendants of something non-fixed, use:
*:not(.fixed) > [class*="clmn"] { /* ... */ }
Which does work.

Resources