Styling an <li> within another <li>? - css

I have the following:
<ul id='foo'>
<li class='fooitem'>
<ul class='grok'>
<li class='grokitem'></li>
</ul>
</li>
</ul>
I want to style the fooitem elements differently than the grokitem elements:
#foo li {
background-color: red;
}
.grok li {
background-color: green;
}
but the #foo li definition is overriding the .grok li definition, so all are appearing red. How do I define a style for the grok items?
Thanks

You need a slightly different style rule (currently the first, with an ID, has a greater level of specifity).
You can resolve it like this:
#foo li {
background-color: red;
}
#foo .grok li {
background-color: green;
}
You can give it a try here

You can do it by creating a more specific rule like so:
#foo li {
background-color: red;
}
#foo .grok li {
background-color: green;
}

Since your lis appear to have classes assigned to them, you can target them specifically, like so:
ul.grok li.grokitem
{
/* your styles here */
}

#foo li {
background-color: red;
}
#foo .grok li {
background-color: green;
}

You don't need any classes in your example
#foo li { background-color: red; } // All <li>s in foo
#foo li li { background-color: green; } // All <li>s in <li>s in foo

Related

Edit CSS to apply for certain elements

I know it's a dumb question but I couldn't find a solution myself. I have two lists in my HTML page. First one is :
<ul id="menu">
<li><a href='#Url.Action("MainPage","Shirts")'>Main Page</a></li>
<li><a href='#Url.Action("OnSale","Shirts")'>On Sale</a></li>
<li><a href='#Url.Action("Recent","Shirts")'>Recent</a></li>
</ul>
The second one is a PagedListPager which generates an HTML list :
#Html.PagedListPager(Model, page => Url.Action("Mainpage",
new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
This is my CSS for this HTML :
ul {
list-style-type:none;
margin:0;
}
li {
display:inline-block;
float: left;
margin-right: 1px;
}
li a {
display:block;
min-width:140px;
}
li:hover a {
background: #19c589;
}
li:hover ul a {
background: #f3f3f3;
color: #2f3036;
}
li:hover ul a:hover {
background: #19c589;
color: #fff;
}
li ul li {
display: block;
float: none;
}
li ul li a {
width: auto;
min-width: 100px;
}
My problem is that, I want my CSS to work for only the first list, not the second one. I know I need to add a class for first list's elements and edit CSS for that class. But I couldn't do it. I don't know what to do for li ul li a in CSS. Can you tell me how to edit CSS and first list in this case? Thanks.
Try:
#menu > li {
display:inline-block;
float: left;
margin-right: 1px;
}
#menu > li a {
display:block;
min-width:140px;
}
You can use CSS3 child selectors to select specific properties:
ul li a { /* shared styles */ }
ul > li > a { /* parent list styles */ }
ul ul > li > a { /* child list styles */ }
https://css-tricks.com/child-and-sibling-selectors/
You say you have two lists on your page (so two ul elements). And you only want to apply certain css to the first list without using a class or id selector.
You can use the first-of-type pseudo selector, like so:
ul:first-of-type { }
And to apply the css to its children:
ul:first-of-type li { }
According to Can I use this is pretty well supported (unless you need IE8 support).

Sass only selecting parent [duplicate]

I have the following SCSS for styling links in my menu:
nav {
ul {
li {
a {
color: red
}
}
}
ul.opened {
li {
a {
color: green
}
}
}
}
Which generates the following (correct) CSS:
nav ul li a {
color: red;
}
nav ul.opened li a {
color: green;
}
I tried modifying my JavaScript to apply the class to the nav element instead, and use selector-append() in Sass to append the class. But that seems to do the appending in the wrong order (and if the arguments are reversed, the class is appended to the last element!):
nav {
ul {
li {
a {
color: red;
#at-root #{selector-append('.opened', &)} {
color: green;
}
}
}
}
}
Output (incorrect!):
nav ul li a {
color: red;
}
.openednav ul li a {
color: green;
}
Is there a way the SCSS can be rewritten so that the class can be correctly appended without having to duplicate selectors (similar to the selector-append() method)?
The short answer
Since the element we want to replace has a unique name, what we're looking for is this:
nav {
ul {
li {
a {
color: red;
#at-root #{selector-replace(&, 'ul', 'ul.opened')} {
color: green;
}
}
}
}
}
The long answer
Manipulating selectors is extremely dirty, and I would advise against it unless you absolutely had to. If you're overqualifying your selectors by specifying things like table tr td or ul li, then start by simplifying: tr and ul are both redundant in these selectors (unless you're trying to avoid styling elements under an ordered list). Adjust your nesting to be simpler, etc.
Starting with Sass version 3.4, there are 2 important features that allow you to modify selectors.
Selector functions
The parent selector can be stored in a variable
Example:
.foo ul > li a, .bar {
$sel: &;
#debug $sel;
}
You'll always get a list of list of strings because selectors can be chained together with a comma, even when you have only one selector.
.foo ul > li a, .bar { ... }
(1 2 3 4 5), (1)
You'll note that the descendant selector is being counted here (lists in Sass can be either space or comma delimited). This is extremely important to remember.
When selector-replace() doesn't work
The selector-replace() function does not work in the following cases:
The selector you want to replace is not unique (eg. ul ul li)
You want to insert one or more selectors (eg. ul ul li -> ul ul ul li)
You want to remove a selector (eg. ul > li -> ul li)
In this case, you'll need to loop over the selectors and you'll need to know which position you want to modify. The following function will take a function and apply it to a specific position in your selector using the magic of the call() function.
#function selector-nth($sel, $n, $f, $args...) {
$collector: ();
#each $s in $sel {
$modified: call($f, nth($s, $n), $args...);
$collector: append($collector, set-nth($s, $n, $modified), comma);
}
#return $collector;
}
Append a class (when the selector isn't unique or you don't know its name)
The function we need here takes 2 arguments: the original selector and the selector you'd like to append to it. Uses simple interpolation to do the job.
#function append-class($a, $b) {
#return #{$a}#{$b};
}
.foo, .bar {
ul > li a {
color: red;
#at-root #{selector-nth(&, -2, append-class, '.baz')} {
color: blue;
}
}
}
Output:
.foo ul > li a, .bar ul > li a {
color: red;
}
.foo ul > li.baz a, .bar ul > li.baz a {
color: blue;
}
Insert a selector
This function also takes 2 arguments: the original selector and the selector you'd like to insert before it.
#function insert-selector($a, $b) {
#return $b $a;
}
.foo, .bar {
ul > li a {
color: red;
#at-root #{selector-nth(&, -2, insert-selector, '.baz')} {
color: blue;
}
}
}
Output:
.foo ul > li a, .bar ul > li a {
color: red;
}
.foo ul > .baz li a, .bar ul > .baz li a {
color: blue;
}
Remove a selector
Removing a selector is as simple as replacing your selector with an empty string.
#function remove-selector($sel) {
#return '';
}
.foo, .bar {
ul > li a {
color: red;
#at-root #{selector-nth(&, -2, remove-selector)} {
color: blue;
}
}
}
Output:
.foo ul > li a, .bar ul > li a {
color: red;
}
.foo ul > a, .bar ul > a {
color: blue;
}
TL;DR
Selectors are just a lists. Any list manipulation functions will work on it and you can loop over it to modify it as necessary.
So yeah, don't do it unless you really really really need to. If you've decided you still need it, I've packaged these functions up into the selector-nth library.
I made a mixin that solves this problem.
Github: https://github.com/imkremen/sass-parent-append
Example: https://codepen.io/imkremen/pen/RMVBvq
Usage (scss):
.ancestor {
display: inline-flex;
.grandparent {
padding: 32px;
background-color: lightgreen;
.parent {
padding: 32px;
background-color: blue;
.elem {
padding: 16px;
background-color: white;
#include parent-append(":focus", 3) {
box-shadow: inset 0 0 0 8px aqua;
}
#include parent-append(":hover") {
background-color: fuchsia;
}
#include parent-append("p", 0, true) {
background-color: green;
}
}
}
}
}
Result (css):
.ancestor {
display: inline-flex;
}
.ancestor .grandparent {
padding: 32px;
background-color: lightgreen;
}
.ancestor .grandparent .parent {
padding: 32px;
background-color: blue;
}
.ancestor .grandparent .parent .elem {
padding: 16px;
background-color: white;
}
.ancestor:focus .grandparent .parent .elem {
box-shadow: inset 0 0 0 8px aqua;
}
.ancestor .grandparent .parent:hover .elem {
background-color: fuchsia;
}
.ancestor .grandparent .parent p.elem {
background-color: green;
}

CSS: Can't get multiple :nth-child selectors to work

I have a main menu and 4 colours and Id like each colour to cycle through 1-4 then start again if there are more than 4 items.
But each menu item only receives the first colour - this is my CSS (compiled from less):
.main-nav li a:nth-child(4n+1) {
background-color: #7ebdeb;
}
.main-nav li a:nth-child(4n+2) {
background-color: #abc081;
}
.main-nav li a:nth-child(4n+3) {
background-color: #f4d1a2;
}
.main-nav li a:nth-child(4n+4) {
background-color: #e96956;
}
I have no other background colours specified - I've been racking my brain and have tried several online nth-child testers to double check the specific selectors but can't work out what's going wrong sorry.
You are targeting the same element in each list item, the anchor, repeatedly. Each list item only has one child. You probably want:
.main-nav li:nth-child(4n+1) {
background-color: #7ebdeb;
}
.main-nav li:nth-child(4n+2) {
background-color: #abc081;
}
.main-nav li:nth-child(4n+3) {
background-color: #f4d1a2;
}
.main-nav li:nth-child(4n+4) {
background-color: #e96956;
}
jsFiddle example
I guess this is what you want:
JSFiddle
.main-nav li:nth-child(4n+1) a {
background-color: #7ebdeb;
}
.main-nav li:nth-child(4n+2) a {
background-color: #abc081;
}
.main-nav li:nth-child(4n+3) a {
background-color: #f4d1a2;
}
.main-nav li:nth-child(4n+4) a {
background-color: #e96956;
}

Rollover list with the first child already activated?

Sorry for my poor english, I'm french !
The first li is already in red, but I want classical rollover effect (only css)
<ul>
<li>1111</li>
<li>2222</li>
<li>3333</li>
</ul>
with
li:first-child { color: red; }
li:hover { color: red; }
ul:hover li:first-child { color: black; }
li:first-child:hover { color: red; }
The last line doesn't work : When my mouse is over 1111, he becomes black instead of stay red.
Look here please : http://jsfiddle.net/cP5rQ/3/
And thank you for advance.
You need to increase the specificity of your last rule enough so that it becomes at least equal to the specificity of the third rule; it will then override the third rule and the item will become red as it should.
Do this by writing the last rule as
ul:hover li:first-child:hover { color: red; }​
See it in action.
This does the trick. Is this what you wanted?
li:first-child { color: red; }
ul:hover li:first-child { color: black; }
li:hover { color: red; }
ul:hover li:first-child:hover { color: red; }​
http://jsfiddle.net/cP5rQ/6/

How to override CSS :hover?

I have this HTML code:
<ul>
<li>Line 1</li>
<li class="disabled">Line 2</li>
</ul>
And the corresponding CSS is:
ul li:hover {
color: red;
}
This allows for both lis to be hovered over and have their color changed. But if I want one of them to be disabled, I’d use the following:
.disabled {
color: grey;
}
But the other CSS code’s hover pseudo-class still has effect. Is there any way I can override this?
The first rule overrides it because of CSS specificity, i.e. it's more specific.
Change second rule to:
ul li.disabled, ul li.disabled:hover{
color:grey;
}
Change your CSS To:
ul li:hover{
color:red;
}
.disabled ,.disabled:hover{
color:grey;
}
See this fiddle
Updating for the 2020s, you can now use :not to your advantage
.disabled {
color:grey;
}
ul li:not(.disabled):hover{
color:red;
}
<ul>
<li>Line 1</li>
<li class="disabled">Line 2</li>
</ul>
You just need to change your css:
ul li:hover{
color:red; }
ul li.disabled,ul li.disabled:hover{
color:grey; }
You have to disable the hover effect, so you give it the same color as when it wasn't hovered.
.disabled{
color:grey !important;
}
I was trying to get a CSS "disabled" effect to be applied automatically when doing the following javascript:
document.getElementById("TheButton").disabled = true;
If "TheButton" is defined with the class "TheClass":
.TheClass { background-color: LightBlue; }
.TheClass:hover { background-color: Cyan; }
The only thing that worked for me was with this CSS:
.TheClass[disabled] { background-color: lightgrey; } /* for IE */
.TheClass[disabled='disabled'] { background-color: lightgrey; } /* for Chrome */
.TheClass[disabled]:hover { background-color: lightgrey; } /* for IE */
.TheClass[disabled='disabled']:hover { background-color: lightgrey; } /* for Chrome */
Minimum, if only need grey at every time, no need :hover on .disabled
ul li:hover{
color:red;
}
ul li.disabled{// Last rule precedence
color:grey;
}
Or for speed updating, use !important:
.disabled{
color:grey !important;
}
ul li:hover{
color:red;
}
You can just do following in the css to discard any color for disabled elements while we hover on it.
ul li:hover:not(:disabled) {
color: red;
}
This will cause the color red to be applied only when list is not disabled.

Resources