I wrote a list item hover effect today, but the result behavior is quite strange:
When hover from Item6 to Item2, everything's ok, but when hover from Item2 to Item6 & hover the blank area (inside<li>, outside of <p>), it seems something is blocking the hovering.
Feels like something's wrong with the pseudo element.
Can anyone help me with it? Thanks!
Here is my code:
var li = document.querySelectorAll('li')
li.forEach((e) => {
e.addEventListener('click', (event) => {
li.forEach((l) => {
l.classList.remove('active')
})
e.classList.add('active')
})
})
:root {
--el-color-primary: #409eff;
--el-color-info: #909399;
--el-color-primary-rgb: 64, 158, 255;
}
.categories {
width: 200px;
}
li {
list-style-type: none;
box-sizing: border-box;
height: 2.2rem;
cursor: pointer;
color: var(--el-color-info);
z-index: 0;
border-radius: .5rem;
}
li {
margin: .3rem;
}
li p {
font-size: 1rem;
line-height: 1rem;
padding: .6rem 0 .6rem .8rem;
margin: 0;
color: var(--el-color-info);
}
li.active p {
font-weight: 600;
color: var(--el-color-primary);
}
li.active {
background-color: rgba(var(--el-color-primary-rgb), .2);
}
li:not(.active)::after {
content: "";
display: inline-block;
width: 0;
height: 2.2rem;
position: relative;
top: -2.2rem;
left: 0;
border-radius: .5rem;
background-color: rgba(var(--el-color-primary-rgb), .1);
z-index: -99;
transition: width .4s ease-out;
}
li:not(.active):hover p {
color: var(--el-color-primary);
}
li:not(.active):hover::after {
width: 100%;
}
<ul >
<li >
<p>Item 1</p>
</li>
<li>
<p>Item 2</p>
</li>
<li>
<p>Item 3</p>
</li>
<li>
<p>Item 4</p>
</li>
<li>
<p>Item 5</p>
</li>
<li>
<p>Item 6</p>
</li>
</ul>
CodePudding user response:
The problem is solved by modifying putting a display: block at li:not(.active)::after instead of an inline-block
var li = document.querySelectorAll('li')
li.forEach((e) => {
e.addEventListener('click', (event) => {
li.forEach((l) => {
l.classList.remove('active')
})
e.classList.add('active')
})
})
:root {
--el-color-primary: #409eff;
--el-color-info: #909399;
--el-color-primary-rgb: 64, 158, 255;
}
.categories {
width: 200px;
}
li {
list-style-type: none;
box-sizing: border-box;
height: 2.2rem;
cursor: pointer;
color: var(--el-color-info);
z-index: 0;
border-radius: .5rem;
}
li {
margin: .3rem;
}
li p {
font-size: 1rem;
line-height: 1rem;
padding: .6rem 0 .6rem .8rem;
margin: 0;
color: var(--el-color-info);
}
li.active p {
font-weight: 600;
color: var(--el-color-primary);
}
li.active {
background-color: rgba(var(--el-color-primary-rgb), .2);
}
li:not(.active)::after {
content: "";
display: block;
width: 0;
height: 2.2rem;
position: relative;
top: -2.2rem;
left: 0;
border-radius: .5rem;
background-color: rgba(var(--el-color-primary-rgb), .1);
z-index: -99;
transition: width .4s ease-out;
}
li:not(.active):hover p {
color: var(--el-color-primary);
}
li:not(.active):hover::after {
width: 100%;
}
<ul >
<li >
<p>Item 1</p>
</li>
<li>
<p>Item 2</p>
</li>
<li>
<p>Item 3</p>
</li>
<li>
<p>Item 4</p>
</li>
<li>
<p>Item 5</p>
</li>
<li>
<p>Item 6</p>
</li>
</ul>
CodePudding user response:
The problem is in top: -2.2rem
because it is relative and relative
position doesn't remove the element from the normal document flow (
The whole selected area shows "item 2" li
element and the light-blue box is actually a part of that element and we bring it up by negative top value. That's why when we enter mouse from item 2 to 3, we think we would be on item 3 but in fact we are still hovering item 2.
I guess the better way to do this is using absolute
:
var li = document.querySelectorAll('li')
li.forEach((e) => {
e.addEventListener('click', (event) => {
li.forEach((l) => {
l.classList.remove('active')
})
e.classList.add('active')
})
})
:root {
--el-color-primary: #409eff;
--el-color-info: #909399;
--el-color-primary-rgb: 64, 158, 255;
}
.categories {
width: 200px;
}
li {
list-style-type: none;
box-sizing: border-box;
height: 2.2rem;
cursor: pointer;
color: var(--el-color-info);
z-index: 0;
border-radius: .5rem;
position: relative; /* <----- new */
}
li {
margin: .3rem;
}
li p {
font-size: 1rem;
line-height: 1rem;
padding: .6rem 0 .6rem .8rem;
margin: 0;
color: var(--el-color-info);
}
li.active p {
font-weight: 600;
color: var(--el-color-primary);
}
li.active {
background-color: rgba(var(--el-color-primary-rgb), .2);
}
li:not(.active)::after {
content: "";
display: block;
width: 0;
height: 2.2rem;
position: absolute; /* <----- new */
top: 0; /* <----- new */
left: 0;
border-radius: .5rem;
background-color: rgba(var(--el-color-primary-rgb), .1);
z-index: -99;
transition: width .4s ease-out;
}
li:not(.active):hover p {
color: var(--el-color-primary);
}
li:not(.active):hover::after {
width: 100%;
}
<ul >
<li >
<p>Item 1</p>
</li>
<li>
<p>Item 2</p>
</li>
<li>
<p>Item 3</p>
</li>
<li>
<p>Item 4</p>
</li>
<li>
<p>Item 5</p>
</li>
<li>
<p>Item 6</p>
</li>
</ul>