I am looking to using CSS3 pseudo selectors of Odd and Even to select every 2nd image in the HTML. However the images are nested inside P tags. And not every P tag has an image.
For example:
<p><img src="/example.jpg" /></p>
<p>text</p>
<p>text</p>
<p><img src="/example.jpg" /></p>
<p><img src="/example.jpg" /></p>
<p>text</p>
<p><img src="/example.jpg" /></p>
The placement of P tags inbetween without images inside is random.
I tried this solution, but it doesn't work as it targets the odd and even of the P tags (not the image)
p:nth-child(odd) img{
border:4px solid #000;
}
This isn't possible with CSS, as far as I am aware. 'Content aware' selectors have been proposed for the CSS specification, but have not been implemented.
The easiest solution would be to use Javascript to target the images in the <p> tags. I assume all your p's are in a containing element, such as a div? If so, the following solution is possible, using jQuery:
$('div.mycontainer img').each(function(index, element) {
if (index % 2 != 0) {
element.addClass('border');
}
});
The logical condition of the if statement targets even elements by using the modulus operator. border is a class which could contain your special styling rules, like so:
.border {
border:4px solid black;
}
Related
This question already has answers here:
Understanding CSS selector priority / specificity
(4 answers)
Closed 4 years ago.
This must be a very simple question for HTML ninjas out there, but I feel I'm missing something obvious here. Here is a snippet:
#red span {
color: red;
}
#green span {
color: green;
}
<div id="red">
<p><span>red</span></p>
<div id="green">
<p><span>green</span></p>
</div>
</div>
If I swap the stylesheet order, all of the text becomes red:
#green span {
color: green;
}
#red span {
color: red;
}
<div id="red">
<p><span>red</span></p>
<div id="green">
<p><span>green</span></p>
</div>
</div>
This happens despite the fact that <div id="green"> is a more inner parent of <span>green</span> than <div id="red"> in the DOM tree. I suppose it doesn't take precedence simple because its CSS now appears first in the order of stylesheets. So the order of stylesheets is what matters here.
Is this an expected behavior? Is this implementation/browser specific? Is there some official specs detailing that?
Finally, is there any CSS selector syntax I can use to make it work as in the first snippet, without relying on the order of stylesheets or adding new class names, ids, etc?
Yes, the result you got is absolutely expected—well, maybe not expected, but they are correct. Here are the official specs. And here’s a tweet poll of mine detailing the exact same problem. (Spoiler: the majority of voters got it wrong.) Read the replies for a more in-depth discussion.
Currently, there’s not any CSS technology that takes “closest parent” scope into account. And this is a common misconception a lot of programmers have. (CSS is not a programming language.) A typical programmer will think, “The selector #red span means wherever I see a #red, look for a span inside, and then apply the styles. Since #green span is inside the #red, the green will apply after the red.” This is simply incorrect.
The way CSS actually applies styles is that it looks at each element, then goes through the stylesheets from top to bottom, decides if it matches, and then applies/overrides styles as it goes. That’s just one aspect of the cascade, among others (such as inheritance and specificity). Since in your second example #red span comes last in the CSS source, it gets applied last, overriding #green span, regardless of “how close” the span is within the #red in the DOM.
To fix your specific problem, the easiest thing to do is use a direct child selector, like #red > p > span and #green > p > span. But as you’d suspect, these selectors would have to be updated if you ever change the HTML. Coupling your CSS and HTML is a hassle, especially as your project grows.
The best strategy is not to depend on the DOM to style your elements. What happens when you move the span outside the #red? Would you want it to keep its style? For maintainable and scalable CSS, you should use classes only (not IDs) and apply the class to the actual element you want styled, without depending on DOM structure or parent-child relationships. That way, when your HTML structure changes, you don’t have to adjust your CSS to match.
Example:
.red {
color: red;
}
.green {
color: green;
}
<div>
<p><span class="red">red</span></p>
<div>
<p><span class="green">green</span></p>
</div>
</div>
You can use > selector to make it apply to only specific span inside the div with the id you give and not all the span inside the div
#green > span {
color: green;
}
span {
color: red;
}
<div id="red">
<p><span>red</span></p>
<div id="green">
<span>green</span>
</div>
</div>
If you want to do it to all descendants, you can achieve it by Javascript like following, it decreases many line of codes if you want to apply many colors, but will be slower time than css. It's up to your preferences
var colors = ['red', 'green', 'blue', 'orange', 'brown']
var spans = document.querySelectorAll('span');
spans.forEach(function(spanElement) {
colors.forEach(function(color){
if(spanElement.closest(`#${color}`)){
spanElement.style.color=color
}
})
})
<div id="red">
<span>red</span>
<div id="green">
<span>green</span>
<p><span>green</span></p>
</div>
<div id="blue">
<span>blue</span>
</div>
<div id="orange">
<span>orange</span>
</div>
<div id="brown">
<span>brown</span>
</div>
</div>
Is it possible to use the CSS3 selector :first-of-type to select the first element with a given class name? I haven't been successful with my test so I'm thinking it's not?
The Code (http://jsfiddle.net/YWY4L/):
p:first-of-type {color:blue}
p.myclass1:first-of-type {color:red}
.myclass2:first-of-type {color:green}
<div>
<div>This text should appear as normal</div>
<p>This text should be blue.</p>
<p class="myclass1">This text should appear red.</p>
<p class="myclass2">This text should appear green.</p>
</div>
No, it's not possible using just one selector. The :first-of-type pseudo-class selects the first element of its type (div, p, etc). Using a class selector (or a type selector) with that pseudo-class means to select an element if it has the given class (or is of the given type) and is the first of its type among its siblings.
Unfortunately, CSS doesn't provide a :first-of-class selector that only chooses the first occurrence of a class. As a workaround, you can use something like this:
.myclass1 { color: red; }
.myclass1 ~ .myclass1 { color: /* default, or inherited from parent div */; }
Explanations and illustrations for the workaround are given here and here.
The draft CSS Selectors Level 4 proposes to add an of <other-selector> grammar within the :nth-child selector. This would allow you to pick out the nth child matching a given other selector:
:nth-child(1 of p.myclass)
Previous drafts used a new pseudo-class, :nth-match(), so you may see that syntax in some discussions of the feature:
:nth-match(1 of p.myclass)
This has now been implemented in WebKit, and is thus available in Safari, but that appears to be the only browser that supports it. There are tickets filed for implementing it Blink (Chrome), Gecko (Firefox), and a request to implement it in Edge, but no apparent progress on any of these.
This it not possible to use the CSS3 selector :first-of-type to select the first element with a given class name.
However, if the targeted element has a previous element sibling, you can combine the negation CSS pseudo-class and the adjacent sibling selectors to match an element that doesn't immediately have a previous element with the same class name :
:not(.myclass1) + .myclass1
Full working code example:
p:first-of-type {color:blue}
p:not(.myclass1) + .myclass1 { color: red }
p:not(.myclass2) + .myclass2 { color: green }
<div>
<div>This text should appear as normal</div>
<p>This text should be blue.</p>
<p class="myclass1">This text should appear red.</p>
<p class="myclass2">This text should appear green.</p>
</div>
I found a solution for your reference. from some group divs select from group of two same class divs the first one
p[class*="myclass"]:not(:last-of-type) {color:red}
p[class*="myclass"]:last-of-type {color:green}
BTW, I don't know why :last-of-type works, but :first-of-type does not work.
My experiments on jsfiddle... https://jsfiddle.net/aspanoz/m1sg4496/
This is an old thread, but I'm responding because it still appears high in the list of search results. Now that the future has arrived, you can use the :nth-child pseudo-selector.
p:nth-child(1) { color: blue; }
p.myclass1:nth-child(1) { color: red; }
p.myclass2:nth-child(1) { color: green; }
The :nth-child pseudo-selector is powerful - the parentheses accept formulas as well as numbers.
More here: https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child
You can do this by selecting every element of the class that is the sibling of the same class and inverting it, which will select pretty much every element on the page, so then you have to select by the class again.
eg:
<style>
:not(.bar ~ .bar).bar {
color: red;
}
<div>
<div class="foo"></div>
<div class="bar"></div> <!-- Only this will be selected -->
<div class="foo"></div>
<div class="bar"></div>
<div class="foo"></div>
<div class="bar"></div>
</div>
As a fallback solution, you could wrap your classes in a parent element like this:
<div>
<div>This text should appear as normal</div>
<p>This text should be blue.</p>
<div>
<!-- first-child / first-of-type starts from here -->
<p class="myclass1">This text should appear red.</p>
<p class="myclass2">This text should appear green.</p>
</div>
</div>
Not sure how to explain this but I ran into something similar today.
Not being able to set .user:first-of-type{} while .user:last-of-type{} worked fine.
This was fixed after I wrapped them inside a div without any class or styling:
https://codepen.io/adrianTNT/pen/WgEpbE
<style>
.user{
display:block;
background-color:#FFCC00;
}
.user:first-of-type{
background-color:#FF0000;
}
</style>
<p>Not working while this P additional tag exists</p>
<p class="user">A</p>
<p class="user">B</p>
<p class="user">C</p>
<p>Working while inside a div:</p>
<div>
<p class="user">A</p>
<p class="user">B</p>
<p class="user">C</p>
</div>
I found something that works
If you have a bigger class which contains something like grid, all of elements of your another class
You can do like that
div.col-md-4:nth-child(1).myclass{
border: 1px solid #000;
}
Simply :first works for me, why isn't this mentioned yet?
I wondered if there is a better solution than to what I found without changing the html-structure
The HTML structure looks like this
<div class="wrap">
<div class="divider"></div>
<div class="block"></div>
<div class="block"></div>
<div class="divider"></div>
</div>
So there's various DIVs on the same level, what I want to do is to color every fourth block differently, until a divider appears, then it'd have to recount.
I thought something like .block:nth-child(4n) would do the trick, but it actually counts the elements based on the parent, not based on the class.
Here's the JSFiddle to try out.
Block #4 and #8 in each row should be differently colored
http://jsfiddle.net/SKgdH/3/
And this is how I made it sort-of work:
http://jsfiddle.net/SKgdH/1/
What I did was to look for the 4th sibling of the .divider like this .divider + .block + .block + .block + .block
It works, however, I'd have to write the same for the 8th, 12th, 16th, .. block, which doesn't make it automatic anymore.
Is there something like .divider + .block:nth-sibling(4) or .divider + .block:nth-of-class(4)?
Maybe one of you got an idea on how to solve this without changing the source code or using javascript.
Such a pseudo-class would not work because you are expecting it to match elements relative to a different compound selector, which is not how simple selectors work. For example, if you wrote a complex selector that only had a single compound selector with that pseudo-class (and no sibling combinators):
.block:nth-sibling(4n)
Would you expect this to match .block:nth-child(4n), match nothing at all, or be invalid?
It'd be nice to be able to abridge + .block + .block + .block + .block and make it repeat somehow, but unfortunately due to how the selector syntax is designed, it's just not possible.
You'll have to use JavaScript and/or add extra classes to the appropriate elements instead.
The issue here is that :nth-of-type refers to the type of element and both .divider and .block are elements of type <div>.
What you really need is for .divider to be a different type of element from .block.
On that basis, if the only two child elements of <div class="wrap"> are:
<div class="divider">
<div class="block">
I'd be tempted to swap out <div class="divider"> for <hr> - the thematic break element.
Then you can use:
.wrap div:nth-of-type(4)
to style .block.
As explained by BoltClock, you can't do this without JavaScript. If you choose that route (even though you explicitly say without JavaScript), it can be done with jQuery like this:
var counter = 0;
$('.wrap > div').each(function() {
if ($(this).hasClass('divider')) {
counter = 0;
}
else if ($(this).hasClass('block')) {
counter++;
if (counter % 8 == 4) {
$(this).css('background-color','#ff0');
}
}
});
That will color the 4th column in every row yellow.
I came across html>body in one of the stylesheets and wanted to know as to why it is used.
html>body {
font-size: 16px;
font-size: 78.75%;
}
It's called a Child Selector.
The reason it's being used is likely because it's a hack to exclude IE6 and below. Those browsers don't understand the > selector.
More Information
the '>' means that it is referencing on child elements of the parent (in this case 'html')
so for example I could have an arrangement of divs that look like so
<div id="outermost">
<div class="inner">
<div class="inner">
</div>
</div>
</div>
and i wrote some css like so
#outermost>.inner { background-color: #CCC; }
it would only apply the rules to the first level '#inner'
Obviously there is only one body tag however it used to be a hack to exclude ie6 and below to write different rules for ie7+ ;)
Child selector, more info here: http://www.w3.org/TR/CSS2/selector.html#child-selectors
So in your code it would be any body child of html
'> symbol indicates child of
Above code means
The style applies to all the tag body which is a child of html
#sample>div
above applies to all divs which are children of the element with id sample
Can somebody please explain what the selectors mean?
As far as I understand having #myId - is css for control with id=myId.
.myClass is Css for controls with class myClass.
Can somebody please explain the other combinations?
div.img a:hover img
{
border:1px solid #0000ff;
}
div.desc
{
text-align:center;
font-weight:normal;
width:120px;
margin:2px;
}
div.img a:hover img
selects images that are inside hovered links, that are inside div elements with class img, and gives them a blue border.
div.desc
selects divs with the class desc.
An id (#) can exist only once in a document. It is really useful to identify an element in CSS ans in JavaScript as well (should you ever need it).`
A class (.) can be used as often as it is required.
Example: you have only one header: <div id="header">Header</div>, but several articles: <div class="article">...</div>
Say you have this HTML document:
<div id="site">
<h1>Some heading...</h1>
<div class="article">
<h1>Title</h1>
<p>Some content...</p>
</div>
<div class="article">
<h1>Title</h1>
<p>Some content...</p>
</div>
</div>
The heading of the articles shouldn't be as big as the heading of the site, so we have to use a more specific selector: .article h1 {...}. This will style every <h1>element in a element of the class "article".
If we want to have an even more specific selector, we would use: div.article h1 {...}. This will only style every <h1> element in a <div> box with the class "article"
div.img a:hover img means: find me an img element which is a descendant of an a element that is currently being hovered over, which is in turn a descendant of a div element with a class name og img.
div.desc simply selects any div with a class name of desc.
Have a look at the standards definition, I always find this useful: CSS selectors at W3C.
div.img a:hover img
This will match any img tag that is within an a tag which is currently in a hover state that is within a div tag that has class="img".
div.desc
This will match any div tag with class="desc".
When items are chained like this with only spaces between them, it matches on that specific hierarchy of elements. For example, in the first one, an img tag that's not in an a tag won't be matched.
You can also delimit items with a comma, which instead of matching a hierarchy of items will match each item individually. So something like div.img, img will match any div tag with class="img" and will match any img tag.
Specifically for the :hover attribute, that's called a pseudo-class. It modifies the attribute to which it's attached (in this case an a) by looking for items of that type which are in a specific state (in this case, being hovered over).