October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
Frontend Development

How to Store Web Design Variants in a URL

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Store a shareable design choice in a named query parameter, such as ?variant=compact or ?theme=dark. Read and validate it when the page loads, render the interface from that value, and listen for popstate so Back and Forward restore the corresponding design. Use pushState() when a user’s choice should create a history step, and replaceState() when correcting or normalizing the current URL without adding one.

Why put a design variant in the URL?

A URL is the durable, visible representation of a page state that someone should be able to copy, bookmark, reload, or send to another person. For example, https://example.com/gallery?variant=compact communicates which layout the recipient should see without requiring the recipient’s browser to have saved a preference.

This works well for bounded, public choices: a gallery layout, a light or dark theme, a density setting, or a preview mode. It also gives the browser a useful navigation model: when a user changes variants, the page can add a history entry, and Back can return to the previous variant.

Keep the URL state small and serializable. Do not put credentials, secrets, or a large design document in a query string. For larger client-only configuration, store the data in sessionStorage or localStorage and put only a short lookup key in the URL. A URL key alone is not enough to restore the configuration on another device unless the referenced data is available there too.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Choose a representation for the state

Representation Best fit Trade-off
Query parameter with the History API Shareable variants, filters, themes, and density controls Your app must parse and validate the parameter and handle popstate.
Path segment with the History API A variant that behaves like a distinct route or page The server or client router must handle direct requests to that path.
URL fragment In-page anchors or legacy client-only state Fragments are a poor choice for content-changing UI state when crawlability matters.
History state only Ephemeral navigation metadata It is not a durable share link and does not, by itself, let a pasted URL reconstruct the variant.
Web storage plus a short URL key A larger client-side configuration Storage is scoped to a browser and device; handle a missing or cleared saved value.

For most design controls, use a human-readable query parameter with a bounded vocabulary. Separate parameters such as ?theme=dark&density=compact are straightforward when readers may inspect or change each choice. A single versioned parameter such as ?design=v2 can make sense when the choices are tightly coupled, but it is less self-explanatory and needs a stable decoding rule.

Google Search Central advises against using URL fragments to change page content and recommends the History API for JavaScript-driven changes. If a variant needs to be understood as a distinct crawlable page, a query parameter alone does not guarantee that outcome: ensure the page’s rendering and site architecture expose the intended content appropriately.

Implement a shareable variant with JavaScript

The following example allows only three known values. Unknown values fall back to the default rather than being copied into the document or applied as arbitrary styles. The URL is the canonical source for the variant; the object passed to the History API is only a small convenience.

const allowedVariants = new Set(["default", "compact", "spacious"]);

function readVariant() {
  const value = new URL(location.href).searchParams.get("variant");
  return allowedVariants.has(value) ? value : "default";
}

function renderVariant() {
  const variant = readVariant();
  document.documentElement.dataset.variant = variant;
}

function selectVariant(variant) {
  if (!allowedVariants.has(variant)) return;

  const url = new URL(location.href);
  url.searchParams.set("variant", variant);
  history.pushState({ variant }, "", url);
  renderVariant();
}

addEventListener("popstate", renderVariant);
renderVariant();

Connect each control to selectVariant(), for example with a button click handler. Then style the page against the document attribute:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
document.querySelector("[data-variant-option='compact']")
  ?.addEventListener("click", () => selectVariant("compact"));
:root[data-variant="compact"] .card-grid {
  gap: 0.75rem;
}

:root[data-variant="spacious"] .card-grid {
  gap: 2rem;
}

Calling renderVariant() immediately handles a direct visit, refresh, or pasted link. Calling it again on popstate handles a history traversal. The URL parsing uses the current location rather than trusting the event’s state object, because the URL must remain sufficient to reconstruct the shareable choice.

Preserve other query parameters

Constructing a URL from the current location and changing only searchParams retains unrelated query parameters and the existing path. For example, selecting a theme on /gallery?sort=recent produces /gallery?sort=recent&theme=dark, rather than replacing the rest of the address.

Use URLSearchParams.set() when there should be one authoritative value for a parameter. If your application intentionally supports repeated parameters, define and validate that behavior explicitly; calling get() reads one value, while repeated-value semantics can otherwise become ambiguous.

Decide when to use pushState and replaceState

Use pushState for an intentional user choice

history.pushState(state, "", url) adds a session-history entry without loading the new URL as a fresh document. Use it when changing the variant is a meaningful action that a user may want to undo with Back. A sequence from compact to spacious then creates a sequence Back can traverse.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use replaceState for corrections and silent updates

history.replaceState(state, "", url) changes the current history entry instead of adding another one. Use it when normalizing an invalid value, applying a default to the address, or making a URL correction that should not create a surprising Back-button step.

const url = new URL(location.href);
url.searchParams.set("variant", "default");
history.replaceState({ variant: "default" }, "", url);

Do not call pushState() for every incidental render or small internal adjustment. Doing so can make Back feel like it is undoing a long sequence of implementation details instead of navigating between meaningful states. Conversely, replacing the entry for every user-selected variant prevents Back from returning to the previous selection.

The URL passed to either method must be valid and same-origin. These methods update the displayed address without immediately loading the URL. pushState() does not fire hashchange; use popstate to respond when the active history entry changes through browser navigation.

Validate, normalize, and handle defaults

A query string is input, not a guarantee that the value is one your application supports. Define the permitted vocabulary in one place and use it both when reading the URL and when handling user actions. Falling back to a known default prevents an unknown parameter from selecting an unintended design.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Missing parameter: render the default variant. Decide whether to leave the URL clean or add the explicit default with replaceState().
  • Unknown parameter: render the default or another documented fallback. If you normalize the address, use replaceState() so the correction does not add a history step.
  • Repeated parameter: define whether the first value, last value, or invalid input wins. Do not leave the result accidental.
  • Case and spelling: choose whether values are case-sensitive. Human-readable values are easier to share when their spelling is stable.
  • Version changes: if a saved link may outlive the current design system, preserve old names with a mapping or deliberately fall back when a former value is no longer supported.

Validation is also useful for accessibility and predictable control state: after rendering, update the selected control to match the resolved variant, not merely the raw query string.

When storage or routes are a better fit

Use sessionStorage or localStorage for larger local data

Browser storage can hold more than a compact URL state object, but it is scoped to the browser and device. A stored layout may be absent in a private session, after storage has been cleared, or when a link is opened on another device. If a link uses a short key that points to saved state, define a usable fallback for a missing record. Do not assume that a storage key makes the full design shareable.

Use a route when the variant is effectively a page

A path such as /gallery/compact can be clearer when a variant has distinct content, metadata, or server-rendered output. In return, direct navigation to that path must work through the application router or server. Choose a route for page-like states; choose a query parameter for a setting layered on the same page.

Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

Use a fragment for navigation, not as a substitute for URL state

A fragment remains useful for jumping to a section. It is less suitable for changing what the page means or displays: Google says fragments generally do not change crawlable content. For JavaScript-driven variant changes, use the History API and a query parameter or route instead.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Performance, reliability, and privacy

Reading a short query parameter and updating a document attribute is generally a small amount of client-side work; the more important reliability requirement is that the page derive the same variant on initial load and after history navigation. Keep rendering deterministic and avoid treating the History API’s state object as the only copy of a shareable choice.

  • Keep the set of URL values bounded and stable; avoid serializing a whole component tree or design document into the address.
  • Never place secrets, access tokens, or private user data in a URL. Addresses can be copied and exposed wherever URLs are shared or logged.
  • Ensure direct loads and refreshes preserve the selected state. For path-based variants, verify server/router behavior as well.
  • Test Back and Forward in a real browser flow, including links opened directly and parameters that are absent or invalid.
  • For pages whose content is meant to be indexed, do not assume that client-side URL changes alone guarantee search indexing of every state.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting common URL-state problems

The address changes but the design does not

Changing a URL with pushState() does not automatically re-render the page. Call the render function after the user action, and call it on initial load. Keep the render function responsible for reading the active URL and applying the interface state.

Back changes the URL but leaves the old design on screen

Register a popstate listener and re-read the query parameter there. A History API traversal is not a new document load; without that listener, your UI can remain out of sync with the address.

Back skips a selection or takes too many presses

Check where history entries are created. Use pushState() for meaningful user selections and replaceState() for normalization or silent corrections. Avoid pushing duplicate entries during initialization or routine rendering.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The variant disappears after refresh

Make sure the selected value is in the URL, not only in the History API state object or browser storage. Parse the current location during initialization and ensure your code writes the correct parameter name and value.

A link produces an unexpected variant

Inspect the query string for misspellings, unsupported values, and repeated parameters. Validate against the allowed set and make the fallback explicit. Also confirm that the UI controls reflect the resolved fallback rather than showing a stale selection.

pushState throws an error

Check that the URL is valid and same-origin with the current page. A History API URL update does not navigate to a different origin; use normal navigation when the destination is another origin.

hashchange does not run

pushState() does not emit hashchange. Listen for popstate to restore a history entry, and invoke rendering directly after the code that changes the URL.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Or skip the browser setup

If you need a screenshot of a page showing a particular variant, set that state in the URL and capture it with ScreenshotNeo. Its screenshot API can capture a URL as an image or PDF; the URL parameter still needs to be implemented by your page.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/gallery?variant=compact -o shot.webp

See the ScreenshotNeo API documentation for request options. Cookie banners, newsletter popups, and chat widgets can be removed before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card required.

Test the behavior before shipping

  1. Open the page with no variant parameter and confirm that the default design and controls appear.
  2. Choose a non-default design and confirm that the URL updates with the intended named value.
  3. Copy that URL into a fresh tab or browser session and confirm that it reconstructs the same design.
  4. Choose a second design, then use Back and Forward; both address and rendered UI should track each history entry.
  5. Try an unknown value and any repeated-parameter case your app may receive, and confirm the documented fallback.
  6. Refresh the page and verify that the address continues to determine the selected variant.

Frequently Asked Questions

Should the selected variant be stored in the URL or browser storage?

Use the URL for a small state that should travel with a shared link. Use browser storage for larger, browser-local preferences that need not be portable.

Does changing a query parameter with pushState reload the page?

No. It updates the displayed same-origin URL and history entry without immediately loading a new document, so your code must render the corresponding state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can a URL fragment make a design variant shareable?

It can be copied, but fragments are not the recommended way to represent content-changing UI state when crawlability matters; use a query parameter or route with the History API.

Quick Recap

SaleBestseller No. 1
HTML and CSS: Design and Build Websites
HTML and CSS: Design and Build Websites
HTML CSS Design and Build Web Sites; Comes with secure packaging; It can be a gift option
$14.18
SaleBestseller No. 3
SaleBestseller No. 4
Web Design with HTML, CSS, JavaScript and jQuery Set
Web Design with HTML, CSS, JavaScript and jQuery Set
Brand: Wiley; Set of 2 Volumes
$35.05

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.