Reputation: 124
I made a website in which content changes when the user clicks on a toggle switch, the price changes from monthly to annual, and vice versa when a user clicks on the toggle i.e. the h2
with the class monthly
gets displayed when toggler is checked(true) and the h2
with class annual
gets displayed when toggler is unchecked(false).
function refreshPage(){
window.location.reload();
}
const toggler = document.querySelector("#switch");
const annual = document.querySelectorAll(".annual");
const monthly = document.querySelectorAll(".monthly");
window.onload = function priceChange(){
if (toggler.checked === false) {
monthly.forEach(hideMonthly);
function hideMonthly(item) {
item.style.display = "none";
}
} else if (toggler.checked === true ) {
annual.forEach(hideAnnual);
function hideAnnual(item) {
item.style.display = "none";
}
}
}
:root {
--gradient: linear-gradient(to bottom right, hsl(236, 72%, 79%), hsl(237, 63%, 64%));
--gradient-900: hsl(237, 63%, 64%);
--neutral-grey-100: hsl(240, 78%, 98%);
--neutral-grey-300: hsl(234, 14%, 74%);
--neutral-grey-600: hsl(233, 13%, 49%);
--neutral-grey-900: hsl(232, 13%, 33%);
--neutral-100: #fff;
--neutral-900: #000;
}
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-size: 15px;
font-family: 'Montserrat', sans-serif;
background: #F6F6FE url("../images/bg-top.svg") no-repeat;
background-position: top right -170px;
text-align: center;
}
.neutral-grey-100 {
color: var(--neutral-grey-100);
}
.neutral-grey-300 {
color: var(--neutral-grey-300);
}
.neutral-grey-600 {
color: var(--neutral-grey-600);
}
.neutral-grey-900 {
color: var(--neutral-grey-900);
}
h1 {
font-size: 2em;
margin-bottom: .8em;
}
h2 {
font-size: 3em;
margin: 1rem 0;
}
.container {
width: 85%;
margin: 0 auto;
}
.header {
padding: 2.4em;
}
.card {
display: flex;
flex-direction: column;
background-color: var(--neutral-100);
border-radius: .8em;
padding: 1em 2.6em;
margin-bottom: 2.5em;
box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.1);
}
.card:nth-child(odd) {
background: var(--gradient);
color: var(--neutral-100);
}
.card > div:not(:last-child) {
border-bottom: 1px solid rgba(183, 184, 194, 0.45);
}
.card-inverse > div:not(:last-child) {
border-bottom: 1px solid rgba(255, 255, 255, 0.35);
}
section div {
padding: 1em 0;
}
.button {
text-transform: uppercase;
padding: 1em 2em;
margin: 2.6em 0 1.2em 0;
background: var(--gradient);
border: 1px solid var(--neutral-100);
border-radius: 6px;
text-decoration: none;
color: var(--neutral-100);
}
.button:hover, .button:focus {
background: var(--neutral-100);
border: 1px solid hsl(237, 63%, 24%);
color: var(--gradient-900);
outline: none;
}
.button-inverse {
background: var(--neutral-100);
text-decoration: none;
color: var(--gradient-900);
}
.button-inverse:hover, .button-inverse:focus {
background: hsl(237, 63%, 64%);
border: 1px solid var(--neutral-100);
color: var(--neutral-100);
outline: none;
}
.attribution {
font-size: 11px;
text-align: center;
margin-bottom: 1rem;
}
.attribution a {
color: hsl(228, 45%, 44%);
}
/*-------- TOGGLER --------*/
.toggle {
display: flex;
justify-content: center;
align-items: center;
}
input[type=checkbox]{
height: 0;
width: 0;
visibility: hidden;
}
label {
cursor: pointer;
text-indent: -9999px;
width: 65px;
height: 35px;
background: var(--gradient);
display: block;
border-radius: 100px;
position: relative;
margin: 1.4em;
}
label:after {
content: '';
position: absolute;
top: 4px;
left: 4px;
width: 27px;
height: 27px;
background: #fff;
border-radius: 110px;
-webkit-transition: all 350ms;
-moz-transition: all 350ms;
transition: all 350ms;
}
input:checked + label {
background: var(--gradient);
}
input + label:hover, input + label:focus-within {
background: hsl(236, 72%, 81%)
}
input:checked + label:after {
transform: translate3d(114%, 0, 0);
}
@media (min-width: 1440px) {
body {
font-size: 16px;
background-image: url("../images/bg-top.svg"), url("../images/bg-bottom.svg");
background-repeat: no-repeat, no-repeat;
background-position: 100% 0%, 0% 130%;
background-size: 24%, 24%;
}
.container {
display: grid;
grid-template-areas:
"header header header"
"basic professional master"
"attribution attribution attribution";
align-items: center;
width: 65%;
}
.header {
grid-area: header;
}
h2 {
font-size: 4em;
}
h3 {
font-size: 1.3033333333333335em;
}
.card-inverse {
padding: 3em 2em;
}
.card {
margin-bottom: 0;
}
#basic {
grid-area: basic;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
#professional {
grid-area: professional;
}
#master {
grid-area: master;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.attribution {
grid-area: attribution;
margin-top: 4em;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- displays site properly based on user's device -->
<link rel="icon" type="image/png" sizes="32x32" href="./images/favicon-32x32.png">
<link rel="stylesheet" href="css/style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@700&display=swap" rel="stylesheet">
<script defer src="js/script.js"></script>
<title>Frontend Mentor | Pricing component with toggle</title>
</head>
<body>
<div class="container">
<section class="header">
<h1 class="neutral-grey-900">Our Pricing</h1>
<div class="toggle neutral-grey-300">
Annually
<input type="checkbox" id="switch" onClick="refreshPage()"/><label for="switch">Toggle</label>
<!-- <label class="switch"><input type="checkbox" name="toggler" id="toggler" onClick="refreshPage()"/> <figure></figure>
</label> -->
Monthly
</div>
</section>
<section class="card" id="basic">
<div>
<h3 class="neutral-grey-600">Basic</h3>
<h2 class="neutral-grey-900 monthly">$19.99</h2>
<h2 class="neutral-grey-900 annual">$199.99</h2>
</div>
<div class="neutral-grey-600">500 GB Storage</div>
<div class="neutral-grey-600">2 Users Allowed</div>
<div class="neutral-grey-600">Send up to 3 GB</div>
<a class="button button-main" href="">Learn More</a>
</section>
<section class="card card-inverse" id="professional">
<div>
<h3>Professional</h3>
<h2 class="monthly">$24.99</h2>
<h2 class="annual">$249.99</h2>
</div>
<div>1 TB Storage</div>
<div>5 Users Allowed</div>
<div>Send up to 10 GB</div>
<a class="button button-inverse" href="">Learn More</a>
</section>
<section class="card" id="master">
<div>
<h3 class="neutral-grey-600">Master</h3>
<h2 class="neutral-grey-900 monthly">$39.99</h2>
<h2 class="neutral-grey-900 annual">$399.99</h2>
</div>
<div class="neutral-grey-600">2 TB Storage</div>
<div class="neutral-grey-600">10 Users Allowed</div>
<div class="neutral-grey-600">Send up to 20 GB</div>
<a class="button button-main" href="">Learn More</a>
</section>
<div class="attribution">
Challenge by <a href="https://www.frontendmentor.io?ref=challenge" target="_blank">Frontend Mentor</a>.
Coded by <a href="#">Sachin Jadhav</a>.
</div>
</div>
</body>
</html>
The toggle is working in Firefox but not in Chrome, I am not able to figure out what's wrong with my javascript.
Upvotes: 0
Views: 227
Reputation: 496
You set onClick="refreshPage()"
on your switch. So the page always reloads when someone tries to change its value (en-/disable it).
The default behavior of chrome is to loose/forget all the data that was entered before a reload for a formular, while firefox normally asks (or if the user wants it without a popup, defaults) to reenter all the data the user entered after the reload.
Thats why the reload is resetting the value in chrome and keeping it in firefox.
I would recommend to just not reload the page. That also brings better usablity.
Upvotes: 1
Reputation: 1074809
Your code is relying on Firefox remembering the state of the input
and restoring it before the load
handler fires on subsequent page loads. That's not something you can rely on cross-browser.
Instead, just handle the toggle without refreshing. And instead of manually looping the items, you can use a class on their container (or even body
) to control them:
toggler.addEventListener("click", () => {
document.body.classList.toggle("show-monthly", toggler.checked);
});
(And removing refreshPage
entirely.)
With this additional CSS:
body .monthly {
display: none;
}
body.show-monthly .monthly {
display: block;
}
body.show-monthly .annual {
display: none;
}
(Note that the second argument of classList.toggle
doesn't work on obsolete browsers like IE, so you may need an if
/else
for those.)
const toggler = document.querySelector("#switch");
const annual = document.querySelectorAll(".annual");
const monthly = document.querySelectorAll(".monthly");
toggler.addEventListener("click", () => {
document.body.classList.toggle("show-monthly", toggler.checked);
});
body .monthly {
display: none;
}
body.show-monthly .monthly {
display: block;
}
body.show-monthly .annual {
display: none;
}
:root {
--gradient: linear-gradient(to bottom right, hsl(236, 72%, 79%), hsl(237, 63%, 64%));
--gradient-900: hsl(237, 63%, 64%);
--neutral-grey-100: hsl(240, 78%, 98%);
--neutral-grey-300: hsl(234, 14%, 74%);
--neutral-grey-600: hsl(233, 13%, 49%);
--neutral-grey-900: hsl(232, 13%, 33%);
--neutral-100: #fff;
--neutral-900: #000;
}
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-size: 15px;
font-family: 'Montserrat', sans-serif;
background: #F6F6FE url("../images/bg-top.svg") no-repeat;
background-position: top right -170px;
text-align: center;
}
.neutral-grey-100 {
color: var(--neutral-grey-100);
}
.neutral-grey-300 {
color: var(--neutral-grey-300);
}
.neutral-grey-600 {
color: var(--neutral-grey-600);
}
.neutral-grey-900 {
color: var(--neutral-grey-900);
}
h1 {
font-size: 2em;
margin-bottom: .8em;
}
h2 {
font-size: 3em;
margin: 1rem 0;
}
.container {
width: 85%;
margin: 0 auto;
}
.header {
padding: 2.4em;
}
.card {
display: flex;
flex-direction: column;
background-color: var(--neutral-100);
border-radius: .8em;
padding: 1em 2.6em;
margin-bottom: 2.5em;
box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.1);
}
.card:nth-child(odd) {
background: var(--gradient);
color: var(--neutral-100);
}
.card > div:not(:last-child) {
border-bottom: 1px solid rgba(183, 184, 194, 0.45);
}
.card-inverse > div:not(:last-child) {
border-bottom: 1px solid rgba(255, 255, 255, 0.35);
}
section div {
padding: 1em 0;
}
.button {
text-transform: uppercase;
padding: 1em 2em;
margin: 2.6em 0 1.2em 0;
background: var(--gradient);
border: 1px solid var(--neutral-100);
border-radius: 6px;
text-decoration: none;
color: var(--neutral-100);
}
.button:hover, .button:focus {
background: var(--neutral-100);
border: 1px solid hsl(237, 63%, 24%);
color: var(--gradient-900);
outline: none;
}
.button-inverse {
background: var(--neutral-100);
text-decoration: none;
color: var(--gradient-900);
}
.button-inverse:hover, .button-inverse:focus {
background: hsl(237, 63%, 64%);
border: 1px solid var(--neutral-100);
color: var(--neutral-100);
outline: none;
}
.attribution {
font-size: 11px;
text-align: center;
margin-bottom: 1rem;
}
.attribution a {
color: hsl(228, 45%, 44%);
}
/*-------- TOGGLER --------*/
.toggle {
display: flex;
justify-content: center;
align-items: center;
}
input[type=checkbox]{
height: 0;
width: 0;
visibility: hidden;
}
label {
cursor: pointer;
text-indent: -9999px;
width: 65px;
height: 35px;
background: var(--gradient);
display: block;
border-radius: 100px;
position: relative;
margin: 1.4em;
}
label:after {
content: '';
position: absolute;
top: 4px;
left: 4px;
width: 27px;
height: 27px;
background: #fff;
border-radius: 110px;
-webkit-transition: all 350ms;
-moz-transition: all 350ms;
transition: all 350ms;
}
input:checked + label {
background: var(--gradient);
}
input + label:hover, input + label:focus-within {
background: hsl(236, 72%, 81%)
}
input:checked + label:after {
transform: translate3d(114%, 0, 0);
}
@media (min-width: 1440px) {
body {
font-size: 16px;
background-image: url("../images/bg-top.svg"), url("../images/bg-bottom.svg");
background-repeat: no-repeat, no-repeat;
background-position: 100% 0%, 0% 130%;
background-size: 24%, 24%;
}
.container {
display: grid;
grid-template-areas:
"header header header"
"basic professional master"
"attribution attribution attribution";
align-items: center;
width: 65%;
}
.header {
grid-area: header;
}
h2 {
font-size: 4em;
}
h3 {
font-size: 1.3033333333333335em;
}
.card-inverse {
padding: 3em 2em;
}
.card {
margin-bottom: 0;
}
#basic {
grid-area: basic;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
#professional {
grid-area: professional;
}
#master {
grid-area: master;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.attribution {
grid-area: attribution;
margin-top: 4em;
}
}
<div class="container">
<section class="header">
<h1 class="neutral-grey-900">Our Pricing</h1>
<div class="toggle neutral-grey-300">
Annually
<input type="checkbox" id="switch"/><label for="switch">Toggle</label>
<!-- <label class="switch"><input type="checkbox" name="toggler" id="toggler" onClick="refreshPage()"/> <figure></figure>
</label> -->
Monthly
</div>
</section>
<section class="card" id="basic">
<div>
<h3 class="neutral-grey-600">Basic</h3>
<h2 class="neutral-grey-900 monthly">$19.99</h2>
<h2 class="neutral-grey-900 annual">$199.99</h2>
</div>
<div class="neutral-grey-600">500 GB Storage</div>
<div class="neutral-grey-600">2 Users Allowed</div>
<div class="neutral-grey-600">Send up to 3 GB</div>
<a class="button button-main" href="">Learn More</a>
</section>
<section class="card card-inverse" id="professional">
<div>
<h3>Professional</h3>
<h2 class="monthly">$24.99</h2>
<h2 class="annual">$249.99</h2>
</div>
<div>1 TB Storage</div>
<div>5 Users Allowed</div>
<div>Send up to 10 GB</div>
<a class="button button-inverse" href="">Learn More</a>
</section>
<section class="card" id="master">
<div>
<h3 class="neutral-grey-600">Master</h3>
<h2 class="neutral-grey-900 monthly">$39.99</h2>
<h2 class="neutral-grey-900 annual">$399.99</h2>
</div>
<div class="neutral-grey-600">2 TB Storage</div>
<div class="neutral-grey-600">10 Users Allowed</div>
<div class="neutral-grey-600">Send up to 20 GB</div>
<a class="button button-main" href="">Learn More</a>
</section>
<div class="attribution">
Challenge by <a href="https://www.frontendmentor.io?ref=challenge" target="_blank">Frontend Mentor</a>.
Coded by <a href="#">Sachin Jadhav</a>.
</div>
</div>
If you want to remember the setting for future visits, store it in localStorage
and use it when loading the page:
const updatePriceDisplay = () => {
document.body.classList.toggle("show-monthly", toggler.checked);
};
toggler.checked = localStorage.getItem("show-monthly") === "Y";
updatePriceDisplay();
toggler.addEventListener("click", () => {
updatePriceDisplay();
localStorage.setItem("show-monthly", toggler.checked ? "Y" : "N");
});
Upvotes: 1