Settings Panel — Free HTML CSS JS Snippet

Settings Panel · Layouts · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Two-panel flex layout: fixed sidebar + flex-1 scrollable content area
showTab() tab switching: display:none/block toggle via .active class
CSS toggle switch: input:checked + .track pseudo-element sliding animation
Profile form: 2-column CSS Grid with full-width Bio and avatar row
Theme picker: 3-button group with .active border highlight
Accent color picker: circle buttons with active border + white outline ring
Font size slider: native range input with accent-color CSS tint
Danger zone: red border section with delete account CTA

About this UI Snippet

Settings Panel — Sidebar Nav, Profile Form, Notification Toggles & Appearance Controls

Screenshot of the Settings Panel snippet rendered live

A settings panel is a fundamental page in any web application — it centralises user preferences, account management, privacy controls, and appearance customisation. This snippet delivers a complete settings page layout with a left sidebar navigation, four content tabs (Profile, Notifications, Privacy, Appearance), a profile form with avatar, notification toggles, a privacy section with a danger zone, and an appearance tab with theme, accent color, and font size controls.

The two-panel layout

The .panel container uses display: flex with a fixed-width .sidebar (220px) and a flex: 1 .content area. The sidebar has position: relative with border-right separator. The content area uses overflow-y: auto so tall tab content scrolls without the sidebar scrolling. On mobile, this can be adapted to a stacked layout by setting flex-direction: column and giving the sidebar a horizontal scrollable nav row.

Tab switching without a framework

showTab(btn, id) removes .active from all .nav-item and .tab elements, then adds .active to the clicked button and the corresponding tab panel (by ID: tab-profile, tab-notifications, etc.). All tabs are in the DOM simultaneously — only the .active one has display: block via CSS. This keeps tab content persistent between switches, preserving any unsaved form input.

The CSS toggle switch

The notification and privacy toggles use the same CSS-only toggle switch pattern: a hidden checkbox input overlaid by a .track span. When the checkbox is checked, input:checked + .track changes background to indigo, and the ::after pseudo-element (the white circle) translates 20px to the right. The transition on both the background and transform creates the sliding animation.

The appearance controls

The theme selector uses three buttons with .active toggling (setTheme). The accent color picker uses circular buttons; the active one gets a border and an outline ring (outline: 2px solid white, outline-offset: 1px). The font size slider uses a native range input with accent-color: #6366f1 for cross-browser tinted track/thumb styling.

Applying appearance changes to the whole page

To make the accent color and font size controls apply globally, define CSS custom properties on :root: --accent: #6366f1 and --font-size: 14px. In the color picker's onclick handler, call document.documentElement.style.setProperty("--accent", chosenColor). In the font size slider oninput, call document.documentElement.style.setProperty("--font-size", value + "px"). All component CSS that references var(--accent) updates immediately across the page without a reload. Persist the chosen values to localStorage so they survive navigation: localStorage.setItem("accent", color) and localStorage.setItem("fontSize", value). On DOMContentLoaded, read these stored values and apply them before the page renders to avoid a flash of default styles.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't need to work out how showTab keeps every tab's content alive in the DOM by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why all four tab panels stay mounted with only display toggled rather than being created and destroyed on switch, or how the input:checked plus .track sibling selector drives the toggle switch animation with zero JavaScript. The same assistant can help optimize it, for example checking whether keeping unsaved form state across tab switches (a deliberate feature here) could leak stale values if the panel is ever reset externally. It's also useful for extending the feature: ask it to sync the active tab to the URL hash so links to a specific settings section are shareable, wire the appearance controls to real CSS custom properties with a localStorage-backed theme, or add per-field validation before Save Changes submits. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a settings panel with sidebar navigation and multiple tabs in plain HTML, CSS, and JavaScript, no framework, no libraries.

Requirements:
- A two-panel flex layout: a fixed-width sidebar with nav buttons on the left, and a flexible content area on the right that scrolls independently (overflow-y: auto) if a tab's content is tall.
- At least four tab panels (for example Profile, Notifications, Privacy, Appearance), all present in the DOM simultaneously. Switching tabs must only toggle a CSS class that controls display none versus block — do not remove or recreate tab content from the DOM on switch, so any unsaved form input in an inactive tab is preserved.
- A single tab-switching function must, in one call, remove the active class from every nav button and every tab panel, then add it back to only the clicked button and its matching panel (matched by an id convention, not a hardcoded lookup table).
- Implement at least one toggle switch using only a hidden checkbox input and a sibling span styled with the input:checked plus sibling CSS selector — the on/off animation (a sliding circle via a pseudo-element transform) must require no JavaScript at all.
- Add a theme picker (System/Light/Dark buttons) and an accent color picker (a row of color swatch buttons) where clicking any option removes the active class from its sibling options and adds it only to the clicked one.
- Add a font-size range slider whose oninput handler updates a live pixel-value label next to it in real time as it is dragged.
- As a documented extension in a code comment, show how the accent color and font size could be applied globally by writing them to CSS custom properties on the document root via style.setProperty, and persisted with localStorage so they survive a reload.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Click the sidebar nav items to switch tabsClick Profile, Notifications, Privacy, or Appearance in the sidebar to switch the content panel. The active item is highlighted in blue.
  2. 2
    Edit the profile formUpdate name, email, and bio fields. Click Save Changes to trigger a save action. The form uses a 2-column CSS Grid with a full-width row for the bio textarea.
  3. 3
    Toggle notifications and privacy settingsClick any toggle switch in the Notifications or Privacy tabs to toggle the setting on or off. Add API calls in the toggleSwitch() function to persist changes to the server.
  4. 4
    Change theme, accent color, and font sizeIn the Appearance tab, click System/Light/Dark theme buttons, choose an accent color circle, or drag the font size slider. Wire these to a CSS custom property (--accent-color) to apply changes site-wide.
  5. 5
    Wire Save Changes to an APIIn the tab-actions Save button click handler, collect form values with FormData or individual input reads, then POST to /api/user/profile. Show a success toast on resolve.
  6. 6
    Export for your frameworkClick "JSX" for a React component with useState for the active tab and toggle states. Click "Vue" for a Vue 3 SFC with ref-based tab switching.

Real-world uses

Common Use Cases

SaaS application user account settings page
The most common use case. Wire each tab to a separate API endpoint: PATCH /api/profile for profile, PUT /api/notifications for notification prefs, DELETE /api/account for the danger zone. Show a toast notification after each successful save.
Dashboard admin panel user management settings
Repurpose the sidebar for admin sections: General, Team Members, Billing, Integrations, API Keys. Each tab becomes an admin control panel. The same two-panel layout scales to 10+ sidebar items with a scrollable nav.
Mobile app settings page on a responsive web view
On small screens, collapse the sidebar into a horizontal tab bar at the top (flex-direction: column on .panel, then row direction on sidebar). The content panel scrolls vertically below the tabs.
Persist settings to localStorage or a REST API
Read all toggle states and form values in a saveSettings() function. Store in localStorage for client-only persistence: localStorage.setItem("settings", JSON.stringify(settings)). For multi-device sync, POST to an API endpoint on every change.
Study the CSS toggle switch implementation
The notification toggle uses no JavaScript for its visual state — just input:checked + .track CSS selector and a ::after pseudo-element transform. This is the standard accessible toggle pattern: the hidden checkbox carries the semantic state, the visible track is purely presentational.
Developer tool or IDE settings/preferences panel
Adapt for a code editor settings page: Appearance tab for theme/font/indentation, Keybindings tab, Extensions tab. The sidebar nav cleanly organises 8–12 settings sections without visual clutter.

Got questions?

Frequently Asked Questions

showTab(btn, id) removes .active from all .nav-item and .tab elements (querySelectorAll + forEach), then adds .active to the clicked nav button and the tab div with id="tab-" + id. In CSS, .tab { display: none } and .tab.active { display: block }. All tab content stays in the DOM, so unsaved form values are preserved when switching between tabs.

The toggle is a label containing a hidden checkbox and a .track span. The checkbox handles the checked state natively. The CSS rule input:checked + .track changes background to indigo. The .track::after pseudo-element is the white circle, positioned left: 3px by default. input:checked + .track::after uses transform: translateX(20px) to slide it right. The transition on both properties creates the animation.

Define CSS custom properties on :root: --accent: #6366f1; --font-size: 14px. In setColor(), read the button's background color and set document.documentElement.style.setProperty("--accent", color). In the font size slider oninput, set document.documentElement.style.setProperty("--font-size", value + "px"). Reference these in all component CSS.

In React, manage the active tab with const [tab, setTab] = useState("profile"). Render each tab section conditionally: {tab === "profile" && <ProfileTab />}. For toggle switches, use const [prefs, setPrefs] = useState({ analytics: true, marketing: false }) and pass values/setters as props. In Vue 3, use ref("profile") for the active tab and a reactive() object for toggle states. The sidebar nav items call setTab / tab.value on click. For URL-based tab persistence (so the back button works and links to specific tabs are shareable), sync the active tab with the URL hash: on mount, read window.location.hash to set the initial tab; in setTab(), update window.location.hash = tab so the URL reflects the current section. Listen to the hashchange event to handle browser back/forward navigation between tabs without a full route change.