Introduction
Content switchers are very popular in web design, especially when dealing with pricing table switching from Monthly to Yearly. In this tutorial, you’ll learn how to implement a content switcher in any page builder of your choice.
The main requirement for the content switcher is a code or HTML element, as well as the two elements you wish to switch between.
Steps
Code snippet
Add the following code snippet, which is divided into HTML, CSS and JS. The HTML should ideally be added before the contents you wish to switch between. The CSS and JS can be added separately using a code snippet plugin or into the same HTML/Code widget, element or block.
HTML
<fieldset class="dd-toggle-fieldset">
<legend class="dd-legend">
Select your billing cycle
</legend>
<div class="dd-toggle-container">
<label class="dd-toggle-label active" id="dd-item1-label" for="dd-item1">
Monthly
</label>
<div class="dd-toggle-switch">
<div class="dd-switch-container">
<div class="dd-switch-option">
<input type="radio" id="dd-item1" name="dd-toggle" value="dd-item1" checked>
</div>
<div class="dd-switch-option">
<input type="radio" id="dd-item2" name="dd-toggle" value="dd-item2">
</div>
<div class="dd-switch-slider" aria-hidden="true"></div>
</div>
</div>
<label class="dd-toggle-label" id="dd-item2-label" for="dd-item2">
Yearly
</label>
</div>
</fieldset>
CSS
:root {
/* Customizable Variables */
--dd-toggle-height: 2rem;
--dd-toggle-width: 4rem;
--dd-toggle-padding: 0.25rem;
--dd-toggle-bg: #e5e7eb;
--dd-toggle-active: #2563eb;
--dd-toggle-item2-active: #bfdbfe;
--dd-toggle-handle: #ffffff;
--dd-text-inactive: #6b7280;
--dd-text-active: #141414;
--dd-focus-color: #2563eb;
}
.dd-wrapper {
font-family: system-ui, -apple-system, sans-serif;
max-width: min(800px, 90vw);
margin: 2rem auto;
padding: 0 1rem;
}
.dd-toggle-fieldset {
border: none;
padding: 0;
margin: 0 0 2rem 0;
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
}
.dd-legend {
font-weight: 600;
font-size: clamp(1rem, 2vw, 1.125rem);
color: var(--dd-text-active);
margin-bottom: 0.5rem;
text-align: center;
}
.dd-toggle-container {
display: flex;
align-items: center;
gap: 1rem;
}
.dd-toggle-label {
font-size: clamp(0.875rem, 1.5vw, 1rem);
font-weight: 500;
color: var(--dd-text-inactive);
transition: color 0.2s ease;
cursor: pointer;
}
.dd-toggle-label.active {
color: var(--dd-text-active);
}
.dd-toggle-switch {
background: var(--dd-toggle-bg);
border-radius: 100vmax;
padding: var(--dd-toggle-padding);
position: relative;
width: var(--dd-toggle-width);
height: var(--dd-toggle-height);
cursor: pointer;
transition: background-color 0.3s ease;
}
.dd-toggle-switch.item2 {
background-color: var(--dd-toggle-item2-active);
}
.dd-switch-container {
position: relative;
height: 100%;
}
.dd-switch-option input {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.dd-switch-slider {
--dd-slider-size: calc(var(--dd-toggle-height) - (var(--dd-toggle-padding) * 2));
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
width: calc(var(--dd-toggle-width) / 2 - var(--dd-toggle-padding));
height: var(--dd-slider-size);
background-color: var(--dd-toggle-handle);
border-radius: 100vmax;
transition: transform 0.3s ease, background-color 0.3s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
pointer-events: none;
}
.dd-toggle-switch.item2 .dd-switch-slider {
transform: translate(100%, -50%);
background-color: var(--dd-toggle-active);
}
.dd-toggle-switch:focus-within {
outline: 2px solid var(--dd-focus-color);
outline-offset: 2px;
}
/* Content Toggle Styles */
.dd-content-section {
display: none;
opacity: 0;
transition: opacity 0.3s ease;
}
.dd-content-section.active {
display: block;
opacity: 1;
}
/* Responsive adjustments */
@media (max-width: 480px) {
.dd-toggle-container {
gap: 0.5rem;
}
:root {
--dd-toggle-width: 3.5rem;
--dd-toggle-height: 1.75rem;
}
}
JS
<script>
document.addEventListener('DOMContentLoaded', function() {
const radioButtons = document.querySelectorAll('.dd-switch-option input');
const slider = document.querySelector('.dd-switch-slider');
const labels = document.querySelectorAll('.dd-toggle-label');
const switchElement = document.querySelector('.dd-toggle-switch');
const contentSections = document.querySelectorAll('.dd-content-section');
function toggleSwitch() {
const currentChecked = document.querySelector('.dd-switch-option input:checked');
const nextRadio = currentChecked.value === 'dd-item1'
? document.querySelector('input[value="dd-item2"]')
: document.querySelector('input[value="dd-item1"]');
nextRadio.checked = true;
nextRadio.dispatchEvent(new Event('change'));
}
function updateContent(selected) {
contentSections.forEach(section => {
section.classList.remove('active');
});
document.getElementById(`${selected}-content`).classList.add('active');
}
radioButtons.forEach(radio => {
radio.addEventListener('change', function() {
const selected = this.value;
// Update switch appearance
switchElement.classList.toggle('item2', selected === 'dd-item2');
// Update labels
labels.forEach(label => label.classList.remove('active'));
document.querySelector(`label[for="${this.id}"]`).classList.add('active');
// Update content
updateContent(selected);
// Maintain focus
this.focus();
});
});
// Handle switch click
switchElement.addEventListener('click', function(e) {
if (!e.target.matches('input')) {
e.preventDefault();
toggleSwitch();
}
});
// Handle keyboard navigation
radioButtons.forEach(radio => {
radio.addEventListener('keydown', function(e) {
if (['Space', 'Enter', 'ArrowLeft', 'ArrowRight'].includes(e.code)) {
e.preventDefault();
toggleSwitch();
}
});
});
// Handle label clicks
labels.forEach(label => {
label.addEventListener('click', function(e) {
e.preventDefault();
const radioId = this.getAttribute('for');
const radio = document.getElementById(radioId);
radio.checked = true;
radio.dispatchEvent(new Event('change'));
});
});
});
</script>
Add Elements Classes and IDs
The next step is to add the two elements that you wish to toggle between.
Give the first item the class names: “dd-content-section active” and an ID of “dd-item1-content”
Give the second item the class name: “dd-content-section” and an ID of “dd-item2-content”
Final steps
The final step is to adjust the text content in the HTML and variables in the CSS to suit your requirements.
Please do let me know if you have found a better solution or ways to improve the code. Thank you!