Reputation: 183
I'm following a tutorial on a theme switcher. Here is the code:
// DOM Elements
const darkButton = document.getElementById("dark");
const lightButton = document.getElementById("light");
const solarButton = document.getElementById("solar");
const body = document.body;
// Apply the cached theme on reload
const theme = 'light';
const isSolar = false;
if (theme) {
body.classList.add(theme);
isSolar && body.classList.add("solar");
}
// Button Event Handlers
darkButton.onclick = () => {
body.classList.replace("light", "dark");
};
lightButton.onclick = () => {
body.classList.replace("dark", "light");
};
solarButton.onclick = () => {
if (body.classList.contains("solar")) {
body.classList.remove("solar");
} else {
body.classList.add("solar");
}
};
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a {
color: currentColor;
text-decoration: none;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
main {
background-color: var(--bg);
height: 90vh;
color: var(--text);
padding: 30px 25px 0px 25px;
}
#featured {
text-align: center;
margin-bottom: 30px;
}
.grid-container {
height: auto;
width: 75%;
margin: 0 auto;
}
.basic-grid {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.card {
background: var(--bg-card);
padding: 7px 13px;
color: var(--card-text);
border-radius: 5px;
transition: all 0.2s ease-in-out;
}
.card p {
color: var(--card-text);
}
.card:hover {
cursor: pointer;
transform: scale(1.05);
}
:root {
--gray0: #f8f8f8;
--gray1: #dbe1e8;
--gray2: #b2becd;
--gray3: #6c7983;
--gray4: #454e56;
--gray5: #2a2e35;
--gray6: #12181b;
--blue: #0084a5;
--purple: #a82dd1;
--yellow: #fff565;
}
.light {
--bg: var(--gray0);
--bg-nav: linear-gradient(to right, var(--gray1), var(--gray3));
--bg-dropdown: var(--gray0);
--text: var(--gray6);
--border-color: var(--blue);
--bg-solar: var(--yellow);
--bg-card: var(--gray4);
--card-text: var(--gray1);
}
.dark {
--bg: var(--gray5);
--bg-nav: linear-gradient(to right, var(--gray5), var(--gray6));
--bg-dropdown: var(--gray6);
--text: var(--gray0);
--border-color: var(--purple);
--bg-solar: var(--blue);
--bg-card: var(--gray2);
--card-text: var(--gray5);
}
.solar {
--gray0: #fbffd4;
--gray1: #f7f8d0;
--gray2: #b6f880;
--gray3: #5ec72d;
--gray4: #3ea565;
--gray5: #005368;
--gray6: #003d4c;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
nav {
display: flex;
justify-content: space-around;
align-items: center;
height: 10vh;
background: var(--bg-nav);
font-family: "Poppins", sans-serif;
}
.logo {
color: var(--text);
text-transform: capitalize;
letter-spacing: 5px;
font-weight: 500;
font-size: 20;
}
.nav-links {
align-items: center;
display: flex;
justify-content: space-around;
width: 50%;
}
.nav-links a {
text-decoration: none;
color: var(--text);
font-weight: 300;
letter-spacing: 3px;
font-size: 14px;
}
.nav-links li {
list-style: none;
}
.burger {
display: none;
}
.burger div {
width: 25px;
height: 2px;
background-color: var(--burger-color);
margin: 6px;
transition: all 0.3s ease;
}
.contact {
background-color: rgb(37, 192, 192);
padding: 8px 30px;
border-radius: 25px;
color: var(--text);
border: none;
cursor: pointer;
font-size: 14px;
}
.contact:hover {
opacity: 0.8;
}
.dropdown {
position: absolute;
width: 500px;
opacity: 0;
z-index: 2;
background: var(--bg-dropdown);
border-top: 2px solid var(--border-color);
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
display: flex;
align-items: center;
justify-content: space-around;
height: 3rem;
margin-top: 1.22rem;
padding: 0.5rem;
box-shadow: rgba(2, 8, 20, 0.1) 0px 0.175em 0.5em;
transform: translateX(-40%);
transition: opacity 0.15s ease-out;
}
.hasDropdown:focus-within .dropdown {
opacity: 1;
pointer-events: auto;
}
.dropdown-item a {
width: 100%;
height: 100%;
size: 0.7rem;
padding-left: 10px;
font-weight: bold;
}
.dropdown-item a::before {
content: " ";
border: 2px solid var(--border-color);
border-radius: 50%;
width: 2rem;
height: 2rem;
display: inline-block;
vertical-align: middle;
margin-right: 10px;
}
<nav>
<div class="logo">
Jeno
</div>
<ul class="nav-links">
<li><a href="#">About</a></li>
<li class="hasDropdown">
<a href="#">Theme</a>
<ul class="dropdown">
<li class="dropdown-item">
<a id="light" href="#">light</a>
</li>
<li class="dropdown-item">
<a id="dark" href="#">dark</a>
</li>
<li class="dropdown-item">
<a id="solar" href="#">solarize</a>
</li>
</ul>
</li>
<button class="contact">Contact</button>
</ul>
<div class="burger">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
</nav>
<main>
</main>
I thought the position: absoloute;
fixed this, but it doesn't
Under the theme drop down, you can still click the theme buttons even when it is closed. Is there anyway to fix this?
It doesn't work properly in the snippet, but it works on codepen: https://codepen.io/ksaeidnia0/pen/VwvrEBr.
Upvotes: 0
Views: 661
Reputation: 1873
You are hiding dropdown elements with opacity
, which only makes these HTML elements transparent and they remain interactive.
Instead of opacity you may use display
or visibility
, but then you lose your animation.
Display
is not an animatable CSS property, so you could use height
or visibility
.
The latter has discrete, rather than continuous values, therefore you cannot animate it smoothly.
What you can do is to animate height
with delay. This way the bug is gone, but behaviour is still the same.
I increased animation time, so that it is more noticeable.
Changes:
.dropdown {
transition-delay: 1s;
transition-property: height;
transition: opacity 1s ease-out, height 0s;
opacity:0;
height: 0;
padding: 0;
display: flex;
overflow: hidden;
}
.hasDropdown:focus-within .dropdown {
opacity: 1;
padding: 0.5rem;
height: 3rem;
pointer-events: auto;
}
// DOM Elements
const darkButton = document.getElementById("dark");
const lightButton = document.getElementById("light");
const solarButton = document.getElementById("solar");
const body = document.body;
// Apply the cached theme on reload
const theme = 'light';
const isSolar = false;
if (theme) {
body.classList.add(theme);
isSolar && body.classList.add("solar");
}
// Button Event Handlers
darkButton.onclick = () => {
body.classList.replace("light", "dark");
};
lightButton.onclick = () => {
body.classList.replace("dark", "light");
};
solarButton.onclick = () => {
if (body.classList.contains("solar")) {
body.classList.remove("solar");
} else {
body.classList.add("solar");
}
};
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a {
color: currentColor;
text-decoration: none;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
main {
background-color: var(--bg);
height: 90vh;
color: var(--text);
padding: 30px 25px 0px 25px;
}
#featured {
text-align: center;
margin-bottom: 30px;
}
.grid-container {
height: auto;
width: 75%;
margin: 0 auto;
}
.basic-grid {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.card {
background: var(--bg-card);
padding: 7px 13px;
color: var(--card-text);
border-radius: 5px;
transition: all 0.2s ease-in-out;
}
.card p {
color: var(--card-text);
}
.card:hover {
cursor: pointer;
transform: scale(1.05);
}
:root {
--gray0: #f8f8f8;
--gray1: #dbe1e8;
--gray2: #b2becd;
--gray3: #6c7983;
--gray4: #454e56;
--gray5: #2a2e35;
--gray6: #12181b;
--blue: #0084a5;
--purple: #a82dd1;
--yellow: #fff565;
}
.light {
--bg: var(--gray0);
--bg-nav: linear-gradient(to right, var(--gray1), var(--gray3));
--bg-dropdown: var(--gray0);
--text: var(--gray6);
--border-color: var(--blue);
--bg-solar: var(--yellow);
--bg-card: var(--gray4);
--card-text: var(--gray1);
}
.dark {
--bg: var(--gray5);
--bg-nav: linear-gradient(to right, var(--gray5), var(--gray6));
--bg-dropdown: var(--gray6);
--text: var(--gray0);
--border-color: var(--purple);
--bg-solar: var(--blue);
--bg-card: var(--gray2);
--card-text: var(--gray5);
}
.solar {
--gray0: #fbffd4;
--gray1: #f7f8d0;
--gray2: #b6f880;
--gray3: #5ec72d;
--gray4: #3ea565;
--gray5: #005368;
--gray6: #003d4c;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
nav {
display: flex;
justify-content: space-around;
align-items: center;
height: 10vh;
background: var(--bg-nav);
font-family: "Poppins", sans-serif;
}
.logo {
color: var(--text);
text-transform: capitalize;
letter-spacing: 5px;
font-weight: 500;
font-size: 20;
}
.nav-links {
align-items: center;
display: flex;
justify-content: space-around;
width: 50%;
}
.nav-links a {
text-decoration: none;
color: var(--text);
font-weight: 300;
letter-spacing: 3px;
font-size: 14px;
}
.nav-links li {
list-style: none;
}
.burger {
display: none;
}
.burger div {
width: 25px;
height: 2px;
background-color: var(--burger-color);
margin: 6px;
transition: all 0.3s ease;
}
.contact {
background-color: rgb(37, 192, 192);
padding: 8px 30px;
border-radius: 25px;
color: var(--text);
border: none;
cursor: pointer;
font-size: 14px;
}
.contact:hover {
opacity: 0.8;
}
.dropdown {
transition-delay: 1s;
transition-property: height;
transition: opacity 1s ease-out, height 0s;
position: absolute;
width: 500px;
opacity:0;
z-index: 2;
background: var(--bg-dropdown);
border-top: 2px solid var(--border-color);
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
height: 0;
display: flex;
align-items: center;
justify-content: space-around;
margin-top: 1.22rem;
padding: 0;
overflow: hidden;
box-shadow: rgba(2, 8, 20, 0.1) 0px 0.175em 0.5em;
transform: translateX(-40%);
}
.hasDropdown:focus-within .dropdown {
border-top: 2px solid var(--border-color);
opacity: 1;
padding: 0.5rem;
height: 3rem;
pointer-events: auto;
}
.dropdown-item a {
width: 100%;
height: 100%;
size: 0.7rem;
padding-left: 10px;
font-weight: bold;
}
.dropdown-item a::before {
content: " ";
border: 2px solid var(--border-color);
border-radius: 50%;
width: 2rem;
height: 2rem;
display: inline-block;
vertical-align: middle;
margin-right: 10px;
}
<nav>
<div class="logo">
Jeno
</div>
<ul class="nav-links">
<li><a href="#">About</a></li>
<li class="hasDropdown">
<a href="#">Theme</a>
<ul class="dropdown">
<li class="dropdown-item">
<a id="light" href="#">light</a>
</li>
<li class="dropdown-item">
<a id="dark" href="#">dark</a>
</li>
<li class="dropdown-item">
<a id="solar" href="#">solarize</a>
</li>
</ul>
</li>
<button class="contact">Contact</button>
</ul>
<div class="burger">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
</nav>
<main>
</main>
Upvotes: 0
Reputation: 5591
Using the display
attribute you can control whether elements are shown. What you had just changed the ul
lists's opacity which doesn't remove it from the page - it just makes it invisible but still there. Try this in your css:
.hasDropdown .dropdown {
display: none;
}
.hasDropdown:focus-within .dropdown {
display: flex;
}
This tells it to not display when there's no focus and to display if there is.
Upvotes: 0
Reputation: 116
Try using the display
property. When you hide the .dropdown
class display: none;
when you show it again use display: block;
or something.
Upvotes: 2