Rollover child changes parent - html

Is there a way through pure CSS to change the style of a parent LI on the hover of a child LI?
<ul>
<li>
1
<ul>
<li>10</li>
<li> 20</li>
</ul>
</li>
<li>2</li>
</ul>
So that when I hover over 10 or 20, a style is applied to 1 or 2?

No, there is no parent selector in CSS.
See here for why this is the case:
http://snook.ca/archives/html_and_css/css-parent-selectors
In short: performance reasons.

Related

Can you set an element's padding based on the depth of its nesting using SCSS?

I'm designing a dropdown menu with many levels and need to set the padding of the li option based on the depth of the nesting.
<ul>
<li>1</li>
<li>2</li>
<ul>
<li>a</li>
<li>b</li>
<ul>
<li> i </li>
<li> ii </li>
<li> iii </li>
</ul>
</ul>
</ul>
The option 2 has two suboptions: a and b. The option b has 3 suboptions: i,ii,iii
Is there any way I can have all li on the first level have 16px padding-left, and all lis after that have padding-left of something like (parent li's padding-left) + 20px?
Note: what I really want is all options one after the other and each option's padding is based on its level of nesting without having to write an explicit class for each level.
Edit: Here's a basic codepen Codepen for the main problem: What I want is the hover background for each item to extend to the full width of the main container
Edit: To dynamically increase padding you can do something like this:
ul:nth-child(1) > * {
padding-left: 16px;
}
Check the snippet below:
ul:nth-child(1) > * {
padding-left: 16px;
}
<ul>
<li>1</li>
<li>2</li>
<li>
<ul>
<li>a</li>
<li>b</li>
<li>
<ul>
<li> i </li>
<li> ii </li>
<li> iii </li>
</ul>
</li>
</ul>
</li>
</ul>

How to select last element that don't have specific class? [duplicate]

This question already has answers here:
Combining :last-child with :not(.class) selector in CSS
(2 answers)
Closed 6 years ago.
How can I select last li that doesn't have the .hidden class?
I have HTML and CSS like this:
ul li:last-child:not(:first-child):not(.hidden) button {
background-color: red;
}
<ul>
<li>
<button>1</button>
</li>
<li>
<button>2</button>
</li>
<li class="hidden">
<button>3</button>
</li>
</ul>
At the current moment, there is no CSS way of being able to find an element that is then followed by another specific element.
Possibly soon, there will be the CSS Relational Pseudo-class :has() which will make what you want possible. This is currently in the CSS Selectors Level 4 Draft and looks unlikely to be rolled out across any browsers any time soon.
A demo is below but don't expect it to work until the Selectors 4 Draft is at least in Working Draft.
Keep an eye on CanIUse to see when it becomes readily available.
ul li:has(+ .hidden:last-child),
ul li:last-child:not(.hidden) {
background: red;
}
<ul>
<li>
<button>1</button>
</li>
<li>
<button>2</button>
</li>
<li class="hidden">
<button>3</button>
</li>
</ul>
:has() is available in jQuery though, so here's a jQuery alternative
Read more here from the Official jQuery Docs
$('ul li:has(+ .hidden:last-child), ul li:not(.hidden):last-child').css('background', 'red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
<button>1</button>
</li>
<li>
<button>2</button>
</li>
<li class="hidden">
<button>3</button>
</li>
</ul>
The CSS :nth and :last-child pseudo selectors can only work with tags and not other selectors like :not or class but if there is always going to be only one .hidden li at the end, then you could use something like this:
li:nth-last-child(2) { background: lightblue; }
<ul>
<li>1</li>
<li>2</li>
<li class="hidden">3 hidden</li>
</ul>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li class="hidden">4 hidden</li>
</ul>

CSS selector: element without any its children

I have a nested unordered list with one "li" element defined with identifier: [data-main]
1 (must be selected)
1.1
1.2
2
using the following html:
<ul>
<li data-main>1 (must be selected)
<ul>
<li>1.1</li>
<li>1.2</li>
</ul>
</li>
<li>2</li>
</ul>
I'm trying to find the right CSS selector for selecting only element 1 without its children: 1.1 and 1.2. Selectors, I tried:
li:not([data-main]) - selects all li except main, but i need something opposite
[data-main]:not(:nth-child(1)) - selects nothing
https://jsfiddle.net/DaViking/dtqhag2t/
What you're not realising is that the [data-main] selector in your JSFiddle demo is selecting only that top-level li element. The problem you're facing here is that this li element contains the other li elements. Those aren't selected by this selector individually, but they are contained within the element which is selected:
If you want to style just the text held within the [data-main] element but not within the ul element contained within it, you'll need to override the [data-main] style declarations:
[data-main] {
color: red;
}
[data-main] ul {
color: initial;
}
<ul>
<li data-main>1 (must be selected)
<ul>
<li>1.1</li>
<li>1.2</li>
</ul>
</li>
<li>2</li>
</ul>
If you want to place a border around the "1 (must be selected)" text and nothing else, you can wrap that text in a span element and apply styling to that instead:
[data-main] span {
border: 1px solid red;
}
<ul>
<li data-main>
<span>1 (must be selected)</span>
<ul>
<li>1.1</li>
<li>1.2</li>
</ul>
</li>
<li>2</li>
</ul>

not able to apply css rules to parent elements only

I m having a list with ul and li s.
Now I want to apply a css rule to the parents only and not to the children.
For this I'm using the > symbol but that is applied to the children as well.
The example here
The code I used at the css -
#nav > li a {
padding-bottom: 30px;
}
The html being -
<ul id="nav">
<li>
Home
</li>
<li>
About
<ul>
<li>The product</li>
<li>Meet the team</li>
</ul>
</li>
<li>
Services
<ul>
<li>Sevice one</li>
<li>Sevice two</li>
</ul>
</li>
<li>
Product
<ul>
<li>Small product (one)</li>
<li>Small product (two)</li>
</ul>
</li>
<li>
Contact
<ul>
<li>Out-of-hours</li>
<li>Directions</li>
</ul>
</li>
</ul>
I think you want to use #nav > li > a which covers a children of the <li>. Otherwise any <a> descendant of the <li> is also selected (which is everything).
As of CSS3, there is no way to select an element based on its children. I think that something like that is coming in CSS4, but I'm not sure.
Small note: the > selector selects only the children, not the parents and the children.

making block level elements clickable links

I have the following design problem. I have a list of items and I want to make the whole of each of the first li to be a clickable link. I have tried adding a link in each li, making it a block level element and positioning it absolute, but that doesn't work because the parent and all li's are floated left for layout purposes. Any help would be appreciated, thanks
<ul style='float:left;width:x>
<li>
<ul>
<li>Title</li>
<li>Description</li>
</ul>
</li>
<li>
<ul>
<li>Title</li>
<li>Description</li>
</ul>
</li>
<li>
<ul>
<li>Title</li>
<li>Description</li>
</ul>
</li>
</ul>
If the parent li has position: relative, you can position things absolutely inside it without messing with the way the parent floats around.
Another, somewhat inelegant solution would be to add an onclick event to each of the parent lis, and use JavaScript to change the URL. Also, add cursor: pointer to your CSS to make it look like a link. But as I said, this is not elegant.
Have you thought about jQuery as an option? Its probably not the best solution but it would work. so i would rig something up like this:
$("ul li:first-child").bind('click',function(){
// click event here.
alert("Boom!");
$(this).find("li a").trigger('click');
});
and i would have your code look like this:
<ul>
<li>
<ul>
<li>title</li>
<li>description</li>
</ul>
</li>
<li>
<ul>
<li>title</li>
<li>description</li>
</ul>
</li>
<li>
<ul>
<li>title</li>
<li>description</li>
</ul>
</li>
<li>
<ul>
<li>title</li>
<li>description</li>
</ul>
</li>
</ul>
Put the links in the li and use display:block. Don't absolutely position them.