nthchild nested problem property that just apply on the firt element - html

I have a problem with the nth-child proprety.
The problem is on #subnav element. I don't understand why nth-child doesn't work (suppose to change border color and width).
Here my problem and code :
<div class="container">
<!-- subnav -->
<ul id="subnav">
<li><span>Philosophie</span></li>
<li><span>Musiciens</span></li>
<li><span>Programmes</span></li>
<li><span>Médias</span></li>
<li><span>Agenda</span></li>
</ul>
and the sass
.container {
#subnav {
margin-top: 2rem;
display: flex;
justify-content: space-evenly;
li {
padding-bottom: 0.5rem;
border-bottom: 4px 0.5rem;
border-color: solid #f36e52;
}
a {
color: #fff;
text-decoration: none;
span:nth-child(1):after, span:nth-child(2):after{
content: '';
height: 4px;
text-align: right;
float:right;
margin-top: 0.3rem;
}
span:nth-child(1):after {
width: 30%;
background-color: #f36e52;
}
span:nth-child(2):after {
content: '';
width: 100%!important;
background-color: #fff555;
}
}
}
}
I would like to change the width and also the color of each links, but it only take the attributes of span:nth-child(1).
Any idea ? thanks for your help

They all spans are first-child (or nth-child(1)), you should use nth-child on li to select correctly.
And to change the color of links you should write color attribute directly on span not :after.
The final code should be like below:
#subnav {
li {
&:nth-child(1) {
span {
color: red;
&:after {
content: '';
/*some code*/
}
}
}
&:nth-child(2) {
span {
color: green;
&:after {
content: '';
/*some code*/
}
}
}
}
}

Related

Remove object if hovered away with HTML/CSS

Currently I'm working on a website with a dropdown menu.
I want, that if you click on it, it appears, but if you hover away, it disappears until you click it again.
I have the following snippet for the HTML-part (The links are not implemented yet and the dropdown menu is only on the main page at the moment):
<div class='dropdown-project' id="project">
<a class='dropbtn-project' href='#project'>Projects</a>
<div class='dropcontent-project'>
Project1
Project2
</div>
</div>
and this for the CSS-part:
.dropbtn-project {
padding: 16px;
border: none;
}
.dropdown-project {
position: relative;
display: inline-block;
}
.dropcontent-project {
display: none;
position: absolute;
background-color: var(--main-header-background);
min-width: 150px;
z-index: 1;
}
.dropcontent-project a {
padding: 5px 10px;
display: block;
}
.dropcontent-project a:hover {
color: var(--hover-fonts-color);
background: var(--main-decor-color)
}
.dropdown-project:target .dropcontent-project {display: block;}
.dropdown-project:hover .dropbtn-project {background-color: var(--main-decor-color);}
.dropdown-project:not(:hover) .dropcontent-project {display: none;}
But with this I have the problem, that the target will stay after I clicked once, so it will reappear on hover after one click.
If you want to check it out, it's on https://www.mikecraft1224.tk.
(The text is in German, so "Projekte" is "projects" and "Projekt" is "project")
add javascript functions to handle this.
Here I added two functions, one for adding class and another one for removing the class. and I give style to the class also
.active .dropcontent-project {display: block;}
when clicking on the a element, an active class is added to the project element.
On mouse leave from the project element, the added class gets removed by calling the removeClass function.
function addClass() {
var element = document.getElementById("project");
element.classList.add("active");
}
function removeClass() {
var element = document.getElementById("project");
element.classList.remove("active");
}
.dropbtn-project {
padding: 16px;
border: none;
}
.dropdown-project {
position: relative;
display: inline-block;
}
.dropcontent-project {
display: none;
position: absolute;
background-color: var(--main-header-background);
min-width: 150px;
z-index: 1;
}
.dropcontent-project a {
padding: 5px 10px;
display: block;
}
.dropcontent-project a:hover {
color: var(--hover-fonts-color);
background: var(--main-decor-color)
}
.active .dropcontent-project {display: block;}
.dropdown-project:hover .dropbtn-project {background-color: var(--main-decor-color);}
<div class='dropdown-project' id="project" onmouseleave="removeClass()">
<a class='dropbtn-project' href='#project' onclick="addClass()" >Projects</a>
<div class='dropcontent-project'>
Project1
Project2
</div>
</div>
I recommend that you make the link that you will use as a base for the dropdown in the HTML array as a container element and add the dropdown content inside it.
But if you still say you need to run it with this HTML structure, the following style codes will solve the problem.
.dropbtn-project {
padding: 16px;
border: none;
}
.dropcontent-project {
transition: 0.2s ease-out;
opacity: 0;
pointer-events: none;
background-color: var(--main-header-background);
min-width: 150px;
z-index: 1;
}
.dropcontent-project a {
padding: 5px 10px;
display: block;
}
.dropcontent-project a:hover {
color: var(--hover-fonts-color);
background: var(--main-decor-color)
}
.dropbtn-project:hover ~ .dropcontent-project,
.dropcontent-project:hover {
opacity: 1;
pointer-events: initial;
}

Expanded dropdown overlapping existing items/text

I have a dropdown, when I expand it, it's item and existing controls are getting mixed. I want to hide bg items completely and Dropdown going inside another divs. This is my code
dropdown.component.css
.parent {
display: block;
position: relative;
float: left;
line-height: 30px;
background-color: #4FA0D8;
min-width: 18em;
}
.parent a {
margin: 10px;
color: #FFFFFF;
text-decoration: none;
}
.parent.active>span>ul {
display: block;
position: absolute;
}
.child {
display: none;
}
.child li {
background-color: #E4EFF7;
line-height: 30px;
border-bottom: #CCC 1px solid;
width: 100%;
}
.child li a {
color: #000000;
}
ul {
list-style: none;
margin: 0;
padding: 0px;
min-width: 18em;
}
ul ul ul {
left: 100%;
top: 0;
margin-left: 1px;
}
li:hover {
background-color: #95B4CA;
}
.expand {
font-size: 12px;
float: right;
margin-right: 5px;
}
dropdowncomponenet.html file
<ul #dropdown [ngClass]="isChild ? 'child' : ''">
<li class="parent" *ngFor="let item of items" (click)="open(item)" [ngClass]="item.isOpen ? 'active' : ''">
{{item.name}}
<span class="expand" *ngIf="item.children.length > 0"> ❯</span>
<span dropdown *ngIf="item.children.length > 0 && item.isOpen" [items]="item.children" isChild="true"></span>
</li>
</ul>
Screenshot before and after expanding dropdown. Sorry for not providing images clear
Issue has bee fixed by adding two atribute in css style .parent
position: relative;
z-index: 10000;

How will I overwrite a text-decoration underline coming from a library?

I am using a library which provides an underline like the one below.
I would like to overwrite it and not display the underline.
My attempt:
.remove {
text-decoration: none !important;
}
.un {
display: inline-block;
}
.un:after {
content: '';
width: 0px;
height: 1px;
display: block;
background: black;
transition: 300ms;
}
.un:hover:after {
width: 100%;
}
<span class="un remove">Underlined Text - Or to be underlined</span>
It actually isn't an underline - you need to remove the :after
.un {
display: inline-block;
}
.un:after {
content: '';
width: 0px;
height: 1px;
display: block;
background: black;
transition: 300ms;
}
.un:hover:after {
width: 100%;
}
.un.remove:after { /* hide after if it has remove */
display:none;
}
<span class="un remove">Underlined Text - Or to be underlined</span>
You juste have to remove content from pseudoelement after
.un {
display: inline-block;
}
.un:after {
content: '';
width: 0px;
height: 1px;
display: block;
background: black;
transition: 300ms;
}
.un:hover:after {
width: 100%;
}
.remove:after {
content: none;
}
<span class="un remove">Underlined Text - Or to be underlined</span>
Why are you trying to reset text-decoration? The library doesn’t use text-decorations for the underline effect. You need to reset the things that the library actually changes, like the width of the ::after pseudo-element of the :hover state of the .un class:
.remove:hover::after{
width: 0 !important;
}
Other possibilities include setting content: none !important; or display: none !important; on .remove::after.

Why does media query only work when placed last in my CSS?

I'm learning css and I came across an example that has the following code:
<body>
Hearts
Clubs
Spades
Diamonds
</body>
and css:
.CardLink {
display: block;
color: #666;
text-shadow: 0 2px 0 #efefef;
text-decoration: none;
height: 2.75rem;
line-height: 2.75rem;
border-bottom: 1px solid #bbb;
position: relative;
}
#media (min-width: 300px) {
.CardLink {
padding-left: 1.8rem;
font-size: 1.6rem;
}
.CardLink:before {
display: block;
}
}
.CardLink:before {
display: none;
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 0;
}
.CardLink_Hearts:before {
content: "❤";
}
.CardLink_Clubs:before {
content: "♣";
}
.CardLink_Spades:before {
content: "♠";
}
.CardLink_Diamonds:before {
content: "♦";
}
/*#media (min-width: 300px) {
.CardLink:before {
display: block;
}
}*/
The idea is when the viewport size is below 300px then the card icons are not displayed, otherwise, it shows them.
I was playing around with the code and I can't understand why we have to define #media (min-width: 300px) twice for the code to work as expected.
Why can't we just put the code in the last paragraph of the css to the section where media screen size belongs (good code reuse instead of declaring this again ) ?
If I do this then no icons are displayed (this is the code below).
Could anyone explain ? Check the plunker, this works as expected: https://plnkr.co/edit/MJAPdkgUegpUlJnkcQHg?p=preview
Because you're working with Cascading Style Sheets.
A cascade is like a waterfall: The rendering engine starts at the top of the source document and works its way down.
In this case, it sees your media query. Then it sees the rest of your code, which takes precedence because it comes later.
For instance, let's say your stylesheet had this:
div { color: red; }
div { color: blue; }
div { color: red; }
Your text color will be red.
In this case:
div { color: red; }
div { color: blue; }
Your text color will be blue.
In both cases, CSS picks the last declaration in the stylesheet.
If you want your media query to take precedence, put it at the end of your code.
(It seems simple and often it is. Just make sure to learn about CSS specificity.)
It's about the placement, put the media query after the :before's and it will be ok
.CardLink {
display: block;
color: #666;
text-shadow: 0 2px 0 #efefef;
text-decoration: none;
height: 2.75rem;
line-height: 2.75rem;
border-bottom: 1px solid #bbb;
position: relative;
}
.CardLink:before {
display: none;
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 0;
}
.CardLink_Hearts:before {
content: "❤";
}
.CardLink_Clubs:before {
content: "♣";
}
.CardLink_Spades:before {
content: "♠";
}
.CardLink_Diamonds:before {
content: "♦";
}
#media (min-width: 300px) {
.CardLink {
padding-left: 1.8rem;
font-size: 1.6rem;
}
.CardLink:before {
display: block;
}
}
Hearts
Clubs
Spades
Diamonds

How to remove ':hover' when using a touchscreen?

When this code runs on a tablet/mobile, the user has to tap twice to reach the linked URL. Instead, is there a way to remove the hover effect when viewing on a touchscreen device without using '#media screen and (max-width: XXXpx)'? - I would really like the hover effect to remain on a desktop site, no matter what width a desktop browser is resized to.
Many thanks in advance!
a:link,
a:visited,
a:hover,
a:active {
color: white;
text-decoration: none;
}
#container {
position: absolute;
display: table;
width: 200px;
}
#one {
position: relative;
display: table-cell;
background-color: orange;
vertical-align: middle;
text-align: center;
height: 200px;
width: 200px;
}
#one:hover {
background-color: green;
}
#one:hover > #hello {
display: none;
}
#one:hover > #world {
font-size: 1.2em;
display: block;
}
#hello {
font-size: 1.2em;
display: block;
}
#world {
display: none;
}
<div id="container">
<a id="one" href="http://www.google.com">
<p id="hello">Hello</p>
<p id="world">World</p>
</a>
</div>
You can add a class on the root / html element ie:
var root = document.querySelector(":root");
if ( 'ontouchstart' in window ) {root.classList.add("touch")}
then use the negation CSS pseudo-class
:root:not(.touch) #one:hover {
background-color: green;
}
:root:not(.touch) #one:hover > #hello {
display: none;
}
:root:not(.touch) #one:hover > #world {
font-size: 1.2em;
display: block;
}
alternative
var root = document.querySelector(":root");
'ontouchstart' in window ? root.classList.add("touch") : root.classList.add("no-touch")
then
.no-touch #one:hover {
background-color: green;
}
.no-touch #one:hover > #hello {
display: none;
}
.no-touch #one:hover > #world {
font-size: 1.2em;
display: block;
}
for touch
.touch #one{
/*something else*/
}