Modern HTML includes built-in elements designed for simple interactivity, while CSS has powerful selectors and pseudo-classes that let you respond to user actions like clicks, hovers, or checkbox states.
Without writing a single line of JavaScript, you can create:
- Expandable or collapsible content sections
- Tabbed interfaces
- Toggle switches (like light/dark mode)
- Simple modal pop-ups
- Hover-based interactions
These patterns work by combining native HTML features (like <details>
and <summary>
) or clever uses of CSS (like the :checked
selector or :hover
effects).
Why Learn No-JavaScript Interactivity
Learning how to achieve interactivity with just HTML and CSS is more than just a fun challenge, it’s a valuable skill:
- It helps build faster, more accessible sites with less code.
- It keeps your components lightweight, which improves page performance.
- It gives you fallback techniques if JavaScript fails or is disabled.
Plus, mastering these patterns early strengthens your foundation as a frontend developer, making it easier to decide when you truly need JavaScript and when simpler solutions will do the job.
HTML and CSS Capabilities
HTML includes several elements designed specifically for interaction, no extra scripting needed.
<details>
and <summary>
These elements let you create expandable and collapsible sections. The <summary>
tag acts as a clickable heading, and the <details>
tag wraps the content that’s hidden or shown.
Example:
<details>
<summary>Click to expand</summary>
<p>This content is revealed when you click the summary line.</p>
</details>
Checkboxes (<input type="checkbox">
) and radio buttons (<input type="radio">
) can act as interactive triggers. While they’re usually used in forms, you can combine them with CSS to control what’s shown or hidden on the page.
CSS has powerful selectors and pseudo-classes that respond to user actions:
:checked
Selector
This selector targets any checkbox or radio button when it’s checked. You can use it to style other elements based on whether a box is selected.
Example:
input[type="checkbox"]:checked ~ .content {
display: block;
}
:hover
Selector
This lets you apply styles when a user hovers over an element with their mouse. While it’s often used for things like button highlights, you can also use it creatively for menus or tooltips.
:focus
Selector
This applies styles when an element (like a link or input) is focused, which is great for improving accessibility and user experience.
By combining selectors like ~
(general sibling) or +
(adjacent sibling), you can create relationships between input elements and the content they control.
Example 1: Collapsible Content Section
One of the easiest ways to add interactive behaviour without JavaScript is by using the <details>
and <summary>
HTML elements. These create a built-in expandable section.
Here’s a simple example:
<details>
<summary>What is included in this section?</summary>
<p>This section contains extra details that the user can reveal or hide by clicking the summary line.</p>
</details>
How It Works
<summary>
acts as the clickable heading.
When the user clicks this line, the browser automatically toggles the hidden content.
<details>
wraps the content you want to show or hide.
By default, the content inside <details>
stays hidden until the user opens it.
Most browsers handle the expand/collapse behavior natively, making this one of the simplest interactive components you can add.
Optional Styling
While you don’t need CSS to make it work, you can style it for a better look:
details summary {
cursor: pointer;
font-weight: bold;
}
details[open] summary {
color: #007acc;
}
This adds a pointer cursor and changes the colour when the section is open.
Example 2: Tabbed Interface Using CSS and Radio Buttons
You can create a simple tabbed interface using radio buttons and CSS. This works because radio buttons can control which content is visible, and CSS handles the rest.
HTML Radio Buttons for Tab Switching
Here’s an example setup with three tabs:
<div class="tabs">
<input type="radio" id="tab1" name="tab" checked>
<label for="tab1">Tab 1</label>
<input type="radio" id="tab2" name="tab">
<label for="tab2">Tab 2</label>
<input type="radio" id="tab3" name="tab">
<label for="tab3">Tab 3</label>
<div class="tab-content" id="content1">
<p>Content for Tab 1</p>
</div>
<div class="tab-content" id="content2">
<p>Content for Tab 2</p>
</div>
<div class="tab-content" id="content3">
<p>Content for Tab 3</p>
</div>
</div>
CSS to Style and Show/Hide Content
/* Hide all tab content by default */
.tab-content {
display: none;
padding: 10px;
border: 1px solid #ddd;
}
/* Show content when its radio button is checked */
#tab1:checked ~ #content1,
#tab2:checked ~ #content2,
#tab3:checked ~ #content3 {
display: block;
}
/* Style labels as tab buttons */
.tabs label {
margin-right: 10px;
padding: 5px 10px;
cursor: pointer;
background: #f0f0f0;
border: 1px solid #ccc;
}
.tabs input[type="radio"] {
display: none;
}
.tabs label:hover {
background: #e0e0e0;
}
Radio buttons group the tabs.
Because all the radio buttons share the same name
attribute (tab
), only one can be selected at a time.
Labels act as clickable tabs.
When you click a label, it selects the associated radio button.
CSS :checked
selector controls visibility.
The CSS listens for which radio button is checked and shows only the matching content section.
This approach works great for simple tabbed layouts on informational or portfolio sites.
Example 3: Toggle Switch Using a Checkbox
A toggle switch is another interactive feature you can build with just a checkbox and CSS. This works because the checkbox’s :checked
state can control the visibility, style, or behaviour of other elements.
Checkbox-Driven Toggle
Here’s a simple HTML example for a toggle switch:
<input type="checkbox" id="toggle">
<label for="toggle" class="toggle-label">Toggle Dark Mode</label>
<div class="content">
<p>This is some sample content.</p>
</div>
CSS :checked
Selector
/* Base content styles */
.content {
background: white;
color: black;
padding: 20px;
transition: background 0.3s, color 0.3s;
}
/* Style when checkbox is checked */
#toggle:checked ~ .content {
background: black;
color: white;
}
/* Style the toggle label */
.toggle-label {
display: inline-block;
cursor: pointer;
margin-bottom: 10px;
padding: 5px 10px;
background: #eee;
border: 1px solid #ccc;
}
Common Uses
- Light/Dark Mode Switchers
Toggling the color scheme of a site or section without JavaScript. - Show/Hide Content Blocks
Using a checkbox to reveal or hide extra details, forms, or settings panels. - Interactive Styling
Switching classes or styles for fun UI effects like animations or layout changes.
How It Works
- The checkbox controls the state.
When the user checks or unchecks it, the browser updates the element’s:checked
state. - CSS listens for that state.
Using the:checked
selector, you apply different styles when the box is checked.
For many simple toggles, this is a lightweight, fast solution that avoids unnecessary complexity.
Tips for Designing Without JavaScript
Building interactive components with just HTML and CSS can be surprisingly powerful, but it’s important to know when this approach works well and when it’s time to bring JavaScript into the mix.
- Simple interactions
If you only need basic toggles, tabs, or collapsible sections, HTML and CSS can handle it beautifully without the need for scripts. - Progressive enhancement
If you want your core functionality to work even if JavaScript is disabled or blocked, using HTML and CSS for simple interactivity ensures your site still functions. - Fast-loading sites
No-JavaScript solutions keep your site lightweight, which can improve performance and lower load times, especially important for mobile users or slow connections. - Accessibility
Many native HTML elements (like<details>
and<summary>
) come with built-in keyboard and screen reader support, making them more accessible than custom JS solutions you’d need to test and fine-tune yourself.
Limitations and When to Add JavaScript
- Complex state management
If you need components that remember multiple states or change dynamically based on user input (like multi-step forms or dynamic content loading), you’ll need JavaScript. - Animations and advanced transitions
CSS can handle simple animations, but for more advanced interactions (like drag-and-drop, custom sliders, or interactive maps), JavaScript is essential. - External data handling
Any time you need to fetch, send, or update data from a server (like form submissions, API requests, or dynamic search results), you can’t avoid using JavaScript. - Browser compatibility edge cases
While most modern browsers support the features we’ve covered here, some interactive patterns (especially the newer ones) may still need JavaScript fallback for older browsers.
Helpful Resources
If you’re excited to explore more ways to build interactive components without JavaScript, there’s a lot of great material out there. Here’s a curated list of trusted resources to help you deepen your skills:
- MDN Web Docs: Details and Summary Elements
A clear explanation of how<details>
and<summary>
work, straight from one of the most trusted web documentation sources. - CSS Tricks: Using the :checked Selector
This classic CSS Tricks article dives into creative ways to use checkboxes and the:checked
selector for interactivity. - CodePen: Tabbed Interface Without JavaScript (Search for “CSS-only tabs”)
A collection of live demos you can fork, study, and remix to understand how radio buttons + CSS can build interactive tab layouts. - Accessible CSS-Only Components
This site explores how to create accessible, inclusive components, including many no-JavaScript techniques, with practical examples.
JavaScript is an amazing tool (and essential for many advanced features), but it’s not always the first or only solution.