Select HTML Element Versus Class - css

Assume I have HTML code like this:
<ul class="my-list">
<li> One </li>
<li> Two </li>
<li> Three </li>
</ul>
If I wanted to style the <li> elements, I could use the following selector in CSS:
.my-list li {...}.
The .my-list class here ensures I won't change any <li> elements for other lists.
Is there any additional benefit or usefulness to adding the same class to each <li> element and simply using that as the selector instead, e.g:
<li class="my-list-item">
.my-list-item {...}

I don't think there is because at the end of the day, you are just selecting an element rather than a class or vice-versa.
Unless you are doing something to target specific elements in a list, then adding a class to the li's would be beneficial as then you can make all the .my-list-item red and the .my-list-item--blue blue for example
I could be completely wrong as there might be some more side effects that even I don't know as in it's quicker to select an element rather than a class but even if that is the case, you wouldn't notice anything.

Related

select previous and next elements on hover

I have some html which looks something like this
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
I want to apply a style on any specific <li> on hover AND apply a different style to the previous and next <li> elements (the one next to the hovered one).
If possible I want to do this with pure css (no JS).
So to be clear there are 3 different states and 3 different sets of styles a <li> could have
the element is hovered over.
the element is not hovered over but the element before or after it is hovered over.
the element is not hovered over and the elements before or after it are not hovered over.
I know that the :hover psudo selector can be used to apply a style to the hovered element - no problem
I know that the next element can be selected with :hover + li - no problem
Applying a style to the previous element is however a problem.
I know there is no previous sibling selector, is this still the case?
I have looked at another stack overflow post which talks about applying a style directly to the previous sibling and then using two adjasent sibling selectors to apply styles to the 2nd and 3rd elements. I cant do that in this case because the hover has to be on the 2nd element.
I have considered using [attribute] selectors combined with attr()
my plan would be to give each li a data attribute and a unique specific number, ie <li data="1">
on hover the attr() feature would be used to read the previous elements data attribute and then pass that to the [attribute] selector.
it might look something like this
li:hover [data-number-type=attr(data-number-type)]
<ul>
<li data-number-type="1">Owl</li>
<li data-number-type="2">Owl</li>
<li data-number-type="3">Owl</li>
<li data-number-type="4">Owl</li>
<ui/>
That snippet of code does not work.
but is there any way to get something like that working?
Is there any other css only way that i have not considered?

Wildcard CSS Selector That Can Detect A Class Inside Same Class

I am creating a dynamic navigation list and I want to be able to highlight the page from that list that the user is currently browsing without having to explicitly add the style into a CSS document. For instance,
<div class="check-me">
<ul class="any-class">
<li class="hats">Hats</li>
<li class="shirts">Shirts</li>
<li class="pants">Pants</li>
</ul>
</div>
Essentially, I want to be able to replace the "any-class" with another class, one that appears on an LI element within the "any-class" UL.
<div class="check-me">
<ul class="shirts">
<li class="hats">Hats</li>
<li class="shirts">Shirts</li>
<li class="pants">Pants</li>
</ul>
</div>
I cannot append an "active" class to any LI due to limitations, so I wonder if this is possible using a wildcard CSS selector to use inside div.check-me to highlight anything that shares the same class with the UL. I hope I've been clear enough.

How create CSS Selector which selects the Xn tag including descendants

Say I have the following DOM tree:
<div class="box">
<ul class="gallery">
<li id="1">text</li>
<li id="2">text</li>
<li id="3">text</li>
<li id="4">text</li>
<li id="5">text</li>
<li id="6">text</li>
<li id="7">text</li>
<li id="8">text</li>
<li id="9">text</li>
</ul>
<div id="random"></div>
<ul class="gallery">
<li id="10">text</li>
<li id="11">text</li>
<li id="12">text</li>
<li id="13">text</li>
<li id="14">text</li>
<li id="15">text</li>
<li id="16">text</li>
<li id="17">text</li>
<li id="18">text</li>
<li id="19">text</li>
<li id="20">text</li>
</ul>
</div>
I want to create a CSS selector that will pick every 6th <li> tag under the div with the class "box". But I need the selector to take into account the entire <li> tags in the page and not to count them per <ul> tag. So in the end, the selector should pick the <li> with IDs 6,12,18. Currently I was only able to create a selector that picks IDs 6 & 15 when I used:
div.box li:nth-of-type(6n)
Notice 1: the IDs numbers are only added for reference. In reality the <li> tags don't have a class or an ID.
Notice 2: the number of <li> tags in each <ul> tag varies from site section to site section. Sometimes there can be even a 3rd and a 4th </ul> with more <li> tags.
Notice 3: I don't have control over the hard-coded HTML, which means I cannot unify tags, add IDs or CSS classes, etc. The selector will be called from an external JS file. While I can edit the DOM with jQuery after the page loads, I prefer to avoid such a solution to make the selector easier to handle.
Thanks
Generally Agree Impossible, except...
I basically agree with Sych and Fabrício that it is not currently possible to do as a pure CSS solution. However, there are always some exceptions, depending on actual html structure.
In your case, there may be an exception, but it does depend on the full constraints of your situation.
When Would it Be Possible?
Based off your given code, if these two constraints are true, then you can still get what you want via CSS:
All ul items that are direct children of .box are of class .gallery.
All gallery groups (except perhaps the very last one) consist of exactly nine li elements (both groups in your example do, but I don't know if that was coincidence or how you are actually setting up your code).
If the above two factors in your html are true, then this code gets what you want (using color to show selection here):
ul.gallery:nth-of-type(2n+1) li:nth-of-type(6n) {
color: red;
}
ul.gallery:nth-of-type(2n+2) li:nth-of-type(6n+3) {
color: red;
}
You can see it works on the code you gave in this fiddle, then you can see it continues to work given an expansion of the html as this fiddle shows, even if the final list is short of nine as both this fiddle and this fiddle shows, but it will fail if the .gallery varies in length at some midpoint of the sequence, as seen in this fiddle (notice how the last two selected texts are not 6 apart from each other because the second to last .gallery has only 7 items).
The Overarching Principle
So in general, if your dynamic html is output in some type of a regular pattern as demonstrated here, then it can open up the possibility of a pure css solution along the lines of that given. It is when the dynamic generation is also fully random (so in your case if either #1 or #2 condition above is not guaranteed true) that a pure css solution is impossible.
CSS does not provide such scope, it only provides traversing "deeper in to the DOM" tree. It does not even have a parent element selector.
If you are in jQuery environment, you can write your own selector, call it, say, ":nth-from-top(n)" that will work using jQuery's DOM traversing functions.
Note, that this type of selector will be much slower, because it cannot take advantage of the performance boost provided by the native DOM methods.
nth-child and nth-of-type match based in the element's position relative to its siblings only.
As far as I know there's currently no CSS-only solution for that unless all lis had the same parent. You will have to add a class to every 6th element or use some JavaScript.
So, constraining the answer to CSS selectors only without altering the markup and without hardcoding the nth start indexes: impossible. I'd like to be proven wrong though.
Looking by the bright side, adding a class will provide better selector performance. nth-child is already considered inefficient, now if what you want would be possible it'd mean that browsers would be forced to recursively evaluate selectors and count matches each time the DOM is updated. Though this would be terrible performance wise, I believe it'd still be possible to implement through new "scoped" nth selectors a la CSS Counters. Just food for thought.

Styling individual list items using inline style?

I'm completely new to HTML and CSS, so please bear with me.
I want to change the color of an individual list item in an ordered list, but I don't want the list number to change style. I also need to do this within the one html-document -- no separate CSS.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> Test-page </title>
</head>
<body>
<h1> An html-file </h1>
<ol>
<li> Item 1 </li>
<li style="color:blue"> Item 2 </li>
<li> Item 3 </li>
</ol>
</body>
</html>
The only thing I can think of to solve this using inline styling, is:
<ol>
<li> Item 1 </li>
<li><p style="color:blue"> Item 2 </li>
<li> Item 3 </li>
</ol>
But the list items will appear to be separate paragraphs.
I don't want to use the font-tag, and I want to use HTML5. I want it to be as short as possible, in one file, therefore inline styling.
Any CSS rule that you set on a li element also applies to the list item marker (bullet, number). This is inconvenient, and CSS still lacks any way to style the list marker separately.
So your approach of using something like <li><p style="color:blue"> Item 2 </li> is the workaround you need to use, but when selecting the added inner element, you need to consider the consequences. A p element has default top and bottom margin, so using it, you would need to remove them here:
<li><p style="color:blue; margin:0"> Item 2 </li>
A simpler way is to use div instead of p, since div is a semantically emply block-level container element, which causes no change in default rendering except that its content starts on a fresh line and the content after it starts on a fresh line, which happens here anyway due to the list markup. So:
<li><div style="color:blue"> Item 2</div></li>
Instead of div, you can use span, if there is only inline (phrase-level) content. But div is more flexible, as it allows elements like inner lists, tables, etc.
LIke this
demo
css
ol li span{
color:blue;
}
Try using the span tag in place of p. And don't forget to close the tags properly:
<ol>
<li><span style="color:blue">Item 2</span></li>
</ol>
All the best.
<li><span style="color:blue">Item</span>2</li>

Applying :nth-of-type to a pseudoselector rather than a class or element type (without jQuery or even JS)

I have this:
<ol>
<li class="letter">
<li class="letter">
<li>
<li>
<li>
<li>
<li>
<li>
<li>
<li>
<li>
<li>
<li>
<li>
</ol>
I want the first 9 of the li elements not of class "letter" to be styled a certain way. So, my thinking is, I select those not of class "letter", then select using nth-of-type:
li:not(.letter):nth-of-type(-n+9):before { ... }
However, this selects the first 9 regardless of class, the same result I get using:
li:nth-child(-n+9):before { ... }
I see examples out there of selecting based on E:nth-of-type and .c:nth-of-type. How come it stops there? Why can't I build a selection using nth-of-type off a pseudo-class like I can off an element or class? (Or can I somehow?)
Because the word "type" in :nth-of-type() specifically refers to "element type", and nothing else.
Even examples that you see that qualify :nth-of-type() with a class selector are doing it wrong; they're really matching by the nth sibling of its element type, and not by its class. The class selector is there to say "only match this element if it has this class", and isn't actually considered when counting siblings. This is why you get the same result with both selectors in your example.
With the current Selectors specification, you're not able to select the nth sibling that matches a complex combination of selectors, so what you want to achieve is currently not possible with CSS without knowing about or having control over the HTML structure. Of course, if you know that only the first two li elements will ever have the class then you could just do
li:nth-child(n+2):nth-child(-n+9)::before { ... }
But that's not very useful if your HTML structure will vary.
There's an :nth-match() being proposed in Selectors 4 for this specific purpose, but no word on implementations yet. So for now, you're out of luck when it comes to pure CSS.

Resources