Selecting last consecutive sibling - html

How do I select the last element in a sequence of adjacent elements?
Consider the following markup:
HTML
<ul>
<li class="foo">...</li>
<li class="foo">...</li>
<li class="foo">...</li> <!-- bingo -->
<li class="bar">...</li>
<li class="bar">...</li>
<li class="bar">...</li>
<li class="bar">...</li> <!-- bingo -->
<li class="foo">...</li> <!-- bingo -->
<li class="bar">...</li>
<li class="bar">...</li> <!-- bingo -->
</ul>
The number of consecutive foo or bar elements is dynamic. Also, assume the markup cannot be modified in any way.
Selecting adjacent elements is pretty straight forward:
CSS
.foo + .foo,
.bar + .bar { /* do something */ }
But selecting the last element in a series of consecutive elements, is that possible?

The CSS support for :has is still poor but it can solve the problem:
/* selects any .foo that has no .foo immediately after it */
.foo:has(+ :not(.foo)) {}

You must be dynamically setting up the list.... in that case give a name or an id to the last element and add the css effect you want....
What you asked is not possible according to me unless you have some way of recognizing the last element (may be the id or the name, again set this up if you are in control)

I don't believe there's a way to do this without changing the HTML or the way you generate it. However, if you generate it via the .append() method, all you'd have to do to use this (theoretically) is change it to .prepend(). If you do that, you can change the ul's css to have it select backwards, and then you can use the + selector like so:
(edit: I don't know how to reorder the snippet, but the JS is the least important and only there for if you want to see the .prepend() in action)
//some generation examples just for fun
foo.addEventListener('click',addKnown);
bar.addEventListener('click',addKnown);
r.addEventListener('click',addRandom);
function addKnown(e) {
let li = document.createElement('li');
li.className = e.target.id;
li.textContent = e.target.id;
document.querySelector('ul').prepend(li);
}
function addRandom(e) {
let li = document.createElement('li');
let type = ['foo','bar'][Math.round(Math.random())];
li.className = type;
li.textContent = type;
document.querySelector('ul').prepend(li);
}
ul {
display: flex;
flex-direction: column-reverse;
}
li:first-of-type,
.foo+.bar,
.bar+.foo {
color: red
}
<ul>
<li class="bar">bar</li> <!-- bingo -->
<li class="bar">bar</li>
<li class="foo">foo</li> <!-- bingo -->
<li class="bar">bar</li> <!-- bingo -->
<li class="bar">bar</li>
<li class="bar">bar</li>
<li class="bar">bar</li>
<li class="foo">foo</li> <!-- bingo -->
<li class="foo">foo</li>
<li class="foo">foo</li>
</ul>
<!-- some generation examples just for fun-->
<button id="foo">Add foo</button>
<button id="bar">Add bar</button>
<button id="r">Add random</button>
I would also recommend giving the ul some sort of class or id unless you only have one or want this to be the case for all of your uls on the page.
I'm sorry, I know this isn't exactly what you wanted (because it does technically change the markup by making it backwards), but I hope it's something that's at least possible or helpful in finding something that is.

There appears to be an nth-last-child selector:
http://css-tricks.com/almanac/selectors/n/nth-last-child/
You should be able to use it with a zero argument to get the last one
Edit: nth-last-child will indeed select the last child, which does not match the bingo's
Hopefully you can change the structure:
<ul>
<ul>
<li class="foo">foo 1</li>
<li class="foo">foo 2</li>
<li class="foo">foo 3 bingo</li>
</ul>
<ul>
<li class="bar">bar 1</li>
<li class="bar">bar 2</li>
<li class="bar">bar 3</li>
<li class="bar">bar 4 bingo</li>
</ul>
<ul>
<li class="foo">foo 1</li>
<li class="foo">foo 2 bingo</li>
</ul>
</ul>
and this css will work:
.foo:nth-last-child(1),
.bar:nth-last-child(1)
{
background-color: blue;
}

Related

BEM. Can Elements contain Blocks?

Here is my HTML
<ul class="menu">
<li class="menu__item">
</li>
<li class="menu__item">
<ul class="list"> // can I place this block inside here?
<li class="list__item">
...
</li>
<li class="list__item">
...
</li>
</ul>
</li>
</ul>
In this case, I place the block list inside the element menu__item.
I wonder, is this legal?
As per this documentation from BEM, we can nest the blocks. I.e. a block can have another block in it.
The only condition is that the children blocks should be independent on the parent.
https://en.bem.info/methodology/block-modification/#placing-a-block-inside-another-block
Yes, it is valid. See example from section Nested Lists
in - https://html.com/lists/.

nested list item when another element is hovered

I have a nested list in my menu and I wanted the first child of the sub list highlighted when the parent is highlighted. I want to code this just by using CSS (in SCSS file format) This is a list within a list. I have list items below another list item of another
<ul id="sub-list">
<li class="sub-list-item">
<span>창업교육</span> <!--serves as the parent when this is highlighted, the first child is also highlighted.-->
<ul class="sub-sub-list"> <!--sublist-->
<li class="item">창업정규교과</li>
<li class="item">창업비정규교과</li>
</ul>
</li>
<li class="sub-list-item">
<span>this is another list item in class="sub-list"</span>
</li>
</ul>
*EDIT: changed some of the words being used in this question to make this one understandable. and added another child item to .sub-list to make a better understanding of the issue.
The 'span' (<a>) isn't actually a parent. It's a sibling. The parent to the first child (list item) in the sub list is the <ul class="sub-sub-list">. That means they are siblings.
You can use the + selector to target siblings: https://www.w3schools.com/cssref/css_selectors.asp
.sub-list-item a:hover + ul > li:first-child {
background-color: lightgrey;
}
<ul id="sub-list">
<li class="sub-list-item">
<span>창업교육</span>
<!--serves as the parent when this is highlighted, the first child is also highlighted.-->
<ul class="sub-sub-list">
<!--sublist-->
<li class="item">창업정규교과</li>
<li class="item">창업비정규교과</li>
</ul>
</li>
</ul>

What priority are CSS styles applied? Example provided that is confusing me

I know this should be a stupidly easy topic, but I'm confused and I spent way longer than I should trying to understand this example that my professor gave us.
From what I understand, the rules are supposed to be that you go first for inline css, then document css, then external css, and then priority. The priority was from what I thought 100*IDs+10*Class+1*Element reference.
Here is the code that's really confusing me below:
<div id="id1">
<ul>
<li class="c1" id="id2">Item 1</li>
<li class="c2 c3">Item 2</li>
<li class="c3">Sublist:
<ul>
<li class="c1">Subitem 1</li>
<li class="c2">Subitem 2</li>
<li class="c2" id=”id3”>Subitem 3</li>
</ul></li>
<li>Item 4</li>
</ul>
<div id="id4">
<ul>
<li id="id5">One thing</li>
<li id="id6" class="c2">And another thing</li>
<li id="id7" class="c1">A third thing.</li>
</ul>
</div>
</div>
<style>
div > li
{
color: yellow;
}
.c2
{
color: red;
}
ul li+li+li
{
color: green;
}
#id1, #id4
{
color: orange;
}
#id7
{
color: blue;
}
</style>
In the above code though, item 2 is red, sublist(+subitem1) are green, etc. How is that possible? Why isn't everything coming out orange? Shouldn't the #id1 style be applied to everything automatically since it is the only one with an ID specifier(and everything is a child of div with id="id1"?
The priority formula you wrote is ok if you have two rules to same element.
In css child element inherits from parents the colors, like in your example.
If new rules, despite having a lower specificity number, is applied to child, this override the inheritance.
Anyway read this: https://css-tricks.com/specifics-on-css-specificity/
An element's style overrides it's inheritance.In cases when a style was not defined we will prefer inherited value over default.
There is misunderstanding.
It did orange at first place to all tags .but later as some of the tags are defined different according to css, then it changes to specified color that you mentioned in css.
For CSS types:
http://webdesign.about.com/od/css/qt/aatypesofcss.htm
edited.

How can I target a block after another block with css?

My html looks like this:
<ul>
<li class="myItemClass">item foo</li>
<li class="myItemClass specialItemClass">item foo</li>
<li class="myItemClass">item foo</li>
<li class="myItemClass">item foo</li>
<li class="myItemClass specialItemClass">item foo</li>
<li class="myItemClass specialItemClass">item foo</li> <!-- problem here -->
<li class="myItemClass">item foo</li>
<li class="myItemClass">item foo</li>
</ul>
Now I want to define a css-style for an item that has the 'specialItemClass' and is located after an item that has the 'specialItemClass', too. How can I do that?
Further explanation: The 'specialItemClass' includes having a 2px coloured border. But if two special items are right beneath each other, the borders are doubled. So I don't want to add the special border at the top [or bottom] if there's another special item above [or below].
Use the adjacent sibling selector +
.specialItemClass + .specialItemClass{
/*styles here*/
}
use adjecent css3 selector to work around your issue.
its better to have mere specific selector.
Please see the fiddle
li.specialItemClass + li.specialItemClass{
border-top:none;
}
https://jsfiddle.net/0ou3a02u/

Space between menu item in Firefox

I made a menu , I have worked with chrome but now when I try with firefox I get spacing between items
In chrome
In Firefox
Here's The CSS
http://jsfiddle.net/Mazala/mpc1o2gf/
HTML :
<nav>
<ul class="menu">
<li id="accueil">Accueil</li>
<li id="bureau">Bureau</li>
<li id="actualites">Actualités</li>
<li id="partenaires">Partenaires</li>
<li id="contact">Contact</li>
<li id="liens">Liens utiles</li>
<li id="Liens">lien+subtitles
<ul class="sousmenu">
<li id="Liens">Liens utiles</li>
<li id="Liens">Liens utiles</li>
<li id="Liens">Liens utiles</li>
<li id="Liens">Liens utiles</li>
</ul>
</li>
</ul>
</nav>
CSS in the link .
Thanks for help.
Using inline block will make any text/spaces between your elements treated as text, and style them accordingly. One quick fix (if pure images) was to set the font-size to 0 (that wouldn't work for you since you have actual text in there).
The easiest solution, if you don't care about having the perfect looking code and just getting it to work, is to remove all extra spaces in your code. Which I did to your code, and it works:
<ul class="menu">
<li id="accueil">Accueil</li><li id="bureau">Bureau</li><li id="actualites">Actualités</li><li id="partenaires">Partenaires</li><li id="contact">Contact</li><li id="liens">Liens utiles</li><li id="Liens">lien+subtitles<ul class="sousmenu"><li id="Liens">Liens utiles</li><li id="Liens">Liens utiles</li><li id="Liens">Liens utiles</li><li id="Liens">Liens utiles</li></ul></li>
</ul>
https://jsfiddle.net/mpc1o2gf/1/
That's a common issue with inline-block elements. By default, there some some spacing surrounding those elements. It's somewhat counter-intuitive but default behavior.
There are a few fixes to this. My preferred is to float the li elements. There are some caveats. Read this for a full understanding.