PointyKone
PointyKone

Reputation: 183

How to make transparent html elements unclickable?

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

Answers (4)

matvs
matvs

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

Always Learning
Always Learning

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

Mohsen007
Mohsen007

Reputation: 285

add visibility: hidden; to ul wrap with class dropdown

Upvotes: 0

Suhirthan
Suhirthan

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

Related Questions