Why does selecting multiple elements CSS work differently? [duplicate] - css

This question already has answers here:
Understanding CSS selector priority / specificity
(4 answers)
Closed 3 years ago.
I was trying to create a responsive menu but selecting a specific element worked out differently.
For example, when I selected "nav ul li" for list styles in the default size and selected "ul li" for list style in the breakpoint, it didn't work as I intended.
It was fixed when I selected "ul li" for both the default size and the breakpoint but I don't know why it fixed the issue because as far as I know, selecting "nav ul li" and "ul li" are the same thing. Could somebody help me with this?
nav {
width: 100%;
background-color: darkblue;
}
ul {
width: 80%;
margin: 0 auto;
padding: 0;
}
nav ul li {
list-style-type: none;
display: inline-block;
padding: 20px;
}
ul li:hover {
background-color: orange;
}
ul li a {
color: #ffffff;
text-decoration: none;
}
.toggle {
width: 100%;
padding: 10px 20px;
background-color: #001f44;
text-align: right;
box-sizing: border-box;
color: #ffffff;
font-size: 30px;
/* to hide toggle */
display: none;
}
/* Break Point for the toggle */
#media screen and (max-width:768px) {
.toggle {
display: block;
}
ul {
width: 100%;
}
ul li {
display: block;
text-align: center;
}
}
<div class="toggle">
<i class="fa fa-bars"></i>
</div>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Resume</li>
</ul>
</nav>

You are running into specificity issues. In CSS, if two different rules target the same element with same attributes, the rule with the more specific selector will win and cancel out the less specific rule.
Reading: https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
nav ul li {/* more specific rule wins */
color: blue;
}
ul li {
color: red;
}
<nav>
<ul>
<li>The first list example</li>
</ul>
</nav>
<nav>
<ul>
<li>The second list example</li>
</ul>
</nav>

What is happing is that you are not overriding your selection in the media query.
For instance lets say you got:
CSS:
p a{
color: red
}
#media screen and (max-width:768px) {
a {
color: blue;
}
}
html:
<p> <a>Some Url </a> </p>
The media query wont override the selection for is not as specific as the prior selection.
CSS is about priorities for the more specific the higher the priority of style.
So as:
p a { some style} is more specific than a {some style} then the priority stands for the first one.
In your example, ul li is less specific than nav ul li, thats why you are not overriding the style with the media query.
Hope this answer your question.
Go to w3schools.com for CSS selection rules.

CSS is easy to start writing and really hard to maintain.
One approach to simplify maintainability and avoid specificity conflicts is BEM (Block, Element, Modifier) in which every element has a class and that class describes the element as either:
a Block
a Block Element
a Modified Block
a Modified Block Element
Eg.
<nav class="navigation">
<ul class="navigation__list">
<li class="navigation__list-item">The first list example</li>
</ul>
</nav>
<nav class="navigation">
<ul class="navigation__list">
<li class="navigation__list-item">The second list example</li>
</ul>
</nav>
This will help you entirely avoid any specificity conflicts.
N.B.
BEM is just one approach to writing CSS. Others which similarly seek to simplify maintainability and extendability are OOCSS and SMACSS.
You will find on the web nearly a decade's worth of blog posts and tutorials on any of these approaches to writing CSS.

Related

How to discard global selector rule inside certain tag?

I have global css rule:
li *:last-child {
margin-bottom: 0;
}
Inside <nav> tag I need to make this role do not work. For example I have the code:
<nav>
<ul>
<li>
<span class='foo'>Foo</span>
</li>
</ul>
</nav>
.foo {
margin: 1rem;
}
I want the role for class foo to work. I tried:
nav li *:last-child {
margin-bottom: unset;
}
It does not work. To declare rule for class foo with another selector together is not an option for my case:
.foo, nav li .foo:last-child {
margin: 1rem;
}
It is because I am defining rules in js framework emotion.
I know I can add !important to .foo rule but it is not a good practice. What can I do to resolve my question?
UPD. I found that in emotion I can use & placeholder for the name of the class. And I can define the property of margin:
&, nav li &:last-child {
margin: 1rem;
}
You can't have a global selector not target an individual element - you'll have to overwrite the global rule with a secondary rule which applies the behaviour that you want to only apply to the specific element. Note that this secondary rule should have higher specificity.
The simplest way to do this would be with the selector li .foo, which has more specificity than the li *:last-child selector, and thus overwrites it:
This can be seen in the following:
li *:last-child {
margin-bottom: 0;
}
li .foo {
margin: 1rem;
}
<nav>
<ul>
<li>
<span class='foo'>Foo</span>
</li>
</ul>
</nav>

Display info on hover SCSS/CSS

I'm making a hoverable ul that displays a p element in another div.
As there is no parent selector to be had in pure CSS, I'm stuck and cannot figure out how this is supposed to work.
Fiddle won't work for some reason(for me), so here is a bin:
https://jsbin.com/yohapudimo/edit?html,css,output
My best effort was:
#infoDrop > li:hover ~ #aboutPara > p{
display: inline;
}
while trying to target a sibling div
I think it might be possible without JS... this is untested though so bear with me -- it also has to be an adjacent element, which I'm not sure is a problem or not for you?
If this doesn't work for you, then I'm afraid you'll need JS.
#myPCont p {
display: none;
color: #fff;
}
.myCont:hover+#myPCont p {
display: block;
}
#myPCont {
background: #333;
height: 300px;
width: 300px;
}
<div class="myCont">
<ul class="hoverShowP">
<li>This is my first list item</li>
<li>This is my second..</li>
<li>And this is my third.</li>
</ul>
</div>
<div id="myPCont">
<p>Heyooo!</p>
</div>

How to color specifics parts (letters) of menu?

Firstly, happy new year to you all! :)
Ok let's get to it. I have 5 items in my menu, and i would like to color "+" part of the word to red, choosing 2nd,3rd and 4th item of menu.
This is what menu looks like right now.
This is how the menu should look like, when its done.
I might have given a bad picture, but i think you can see the red "+" on 2nd,3rd and 4th item of menu.
This is what i've tried so far, but i can't seem to figure out the nth-child method.
#menu li:nth-child(2):first-letter a{color:red;}
Also tried this, but it colors every first letter in all 5 elements :S
#menu .nav > li > a:first-letter{color:red;}
Any help will be appreciated!
Thank you all!
I've managed to find the solution. Not sure if it's the best one, but im posting it below, so that any1 in the future can use it too, if no other solution is found
#menu .nav > li:nth-child(2) > a:first-letter
{
color:red;
}
#menu .nav > li:nth-child(3) > a:first-letter
{
color:red;
}
#menu .nav > li:nth-child(4) > a:first-letter
{
color:red;
}
Use the :not() selector to have all but one selected like this:
#menu{
background: rgb(83,83,83);
width: 100vw;
height: 40px;
}
ul{
text-align: center;
line-height: 40px;
vertical-align: central;
}
ul li{
display: inline-block;
color: white;
list-style: none;
margin-left: 25px;
}
a{
color: white;
display: block;
}
#menu ul li:not(:first-child):not(:last-child) a::first-letter{
color: red;
}
<div id="menu">
<ul>
<li>+option</li>
<li>+option</li>
<li>+option</li>
<li>+option</li>
<li>+option</li>
</ul>
</div>
I know this question already has an accepted answer, but I think there is a semantically better way of doing this. Instead of having the + symbol inside the link's markup, why not add it as a pseudo :before element? Easier to style and not dependent on your markup.
<nav>
<ul>
<li>Domov</li>
<li class="with-symbol">Naravni kamen</li>
<li class="with-symbol">Dekorativni kamen</li>
<li class="with-symbol">Keramika</li>
<li>Kontakt</li>
</ul>
</nav>
And the respective CSS:
.with-symbol:before {
content: '+';
color: red;
}
Then position it with either position: absolute; or negative left margin.
From the docs (https://developer.mozilla.org/en-US/docs/Web/CSS/%3A%3Afirst-letter): A first line has meaning only in a block-container box, therefore the ::first-letter pseudo-element has an effect only on elements with a display value of block, inline-block, table-cell, list-item or table-caption. In all other cases, ::first-letter has no effect. So you will need to add display: block to your anchor tags.
I would also change the selector to:
ul li a:first-letter {
color:red;
}
as you need to select the first letter of the anchor tag, not the list item.
As a side note, it might be a better solution to use a span as suggested above or pseudo elements to insert the plus character and use a class to determine if it should be displayed or no.

CSS - Change State of 2 elements on hover

<li class="red">
<p>Home</p>
</li>
In the CSS, I'd like the bg color of the li element to change, BUT the color of the text has to change too. The problem is, even after I hover of ther li element, I have to go further and actually touch the text in order for it's color to change.
I'll be amazed if this can work.
First remove <p> tag
li.red > a:hover {
color: red;
}
li:hover {
background-color: blue;
}
li:hover p,
li:hover a {
color: yellow;
}
There are 2 things you should take into account:
<p></p> is a block level element. It is not used inside inline-element, in this case, <li></li>
Simply make your <a></a> tag to be a block level element.
So your code should be like this:
<ul>
<li class="red">
Home
</li>
</ul>
Then you could come up with the CSS like this:
.red a:hover {
padding: 10px 20px;
display: block;
background-color: #9900;
color: #FFFFFF;
}

Use CSS class in span to set current menu state?

I'm learning CSS and html and am stuck on retaining the look of the hover/active state after an item has been clicked. I've looked at several posts on this site and haven't been able to apply the lesson to my application. I also found a solution here http://www.456bereastreet.com/archive/200503/setting_the_current_menu_state_with_css/ but it didn't work for me (I'll assume it's my fault).
Another source suggested using a span class which is what I'm currently trying. I want to have the same hover color (#fff), weight (bold), and background image in use when a menu item is selected to show the user exactly where they are (this is in the secondary sidebar nav and comes in to use on those pages where the main nav has a dropdown with multiple otions). The only characteristic that's working for me is the bold text. You can see the work in progress here:
http://www.mentalwarddesign.net/dynamec/About/index.html
I'm assuming the class I've created in the span is being overridden, but I'm at a loss as to the remedy. Any and all help would be greatly appreciated.
Following is the code for the li and then the corresponding CSS. Thanks in advance!
<ul class="nav">
<span class="chosen"><li>What We Do</li></span>
<li>How It Started</li>
<li>Who We Are</li>
<li>What We Know</li>
</ul>
.chosen {
font-weight: bold;
color: #ffffff;
background-image: url(../imgGlobal/bulletRight.jpg);
background-repeat: no-repeat;
display: block;
padding-left: -12px;
background-position: 168px;
}
.content ul, .content ol {
padding: 0 15px 15px 40px;
background-color: #fff;
}
ul.nav {
list-style: none;
}
ul.nav li {
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #464646;
height: 50px;
background-color: #000;
}
ul.nav a, ul.nav a:visited {
display: block;
width: 160px;
text-decoration: none;
padding-top: 12px;
padding-right: 5px;
padding-left: 15px;
}
ul.nav a:hover, ul.nav a:active, ul.nav a:focus {
color: #ffffff;
font-weight: bold;
height: 38px;
background-image: url(../imgGlobal/bulletRight.jpg);
background-repeat: no-repeat;
background-position: 168px;
}
Ed, the CSS selector :active means "Being activated (e.g. by being clicked on)", not "Having an href attribute that resolves to the URL of the current page". You can use server-side logic to insert a class=”chosen” or similar. E.g:
<li class="chosen">What We Do</li>
And, CSS style: ul.nav li.chosen a { }
There is another way to do it as mentioned on the tutorial link you gave, however it is not a good example.
Well first of all, you cannot wrap an li inside of a span. The only direct descendent of a ul is a li. You can put the class chosen directly on to the li and it works just fine.
<ul class="nav">
<li class="chosen">What We Do</li>
<li>How It Started</li>
<li>Who We Are</li>
<li>What We Know</li>
</ul>
Put the chosen class in the li element itself. Drop the span altogether.
EDIT:
Sorry, in the a element, i meant to say.
A span is a tag, a class is just an identifier. They don't really have anything to do with one another except a class can be used to apply a style to a span but that's true of any tag.
In your case you're trying to put a span (an inline element) around an li (a block level element). In HTML inline elements should not contain block elements.
You should be able to just do it like this: EDIT fixed based on the actual CSS
<li>What We Do</li>

Resources