Frontend Masters Boost RSS Feed https://frontendmasters.com/blog Helping Your Journey to Senior Developer Wed, 27 Aug 2025 00:15:24 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.3 225069128 Opening a Details Element from the URL https://frontendmasters.com/blog/opening-a-details-element-from-the-url/ https://frontendmasters.com/blog/opening-a-details-element-from-the-url/#comments Wed, 27 Aug 2025 00:15:23 +0000 https://frontendmasters.com/blog/?p=7019 element, it'll open. No other fancy code required.]]> Say you’ve got a page with a bunch of <details> elements on it.

Your goal is to be able to send someone to that page with one particular details element open.

I was doing just this recently, and my first thought was to do it server-side. If the URL was like website.com/#faq-1 I’d see if faq-1 matches an ID of the details element and I’d put the open attribute on it like <details id="faq-1" open>. But no, you don’t get to have the #hash as part of the URL server side (for whatever reason 🤷‍♀️).

Then I started writing JavaScript to do it, where you definitely can access the hash (window.location.hash). I’d just querySelector for the hash and if I found a matching details element, I’d open it up.

Then I was reminded you don’t need to do this at all. What you need is (drumroll)… HTML.

The trick is hash-linking to an element inside the <details>. So like:

<details>
  <summary>What was Rosebud in Citizen Kane?</summary>
  <div id="faq-1">A sled.</div>
</details>

Now, if you hash-link to #faq-1, the browser will know that it has to open that <details> in order for it to be seen, so it does. You don’t normally need a <div> wrapper or anything inside the details element, but we’re doing it here as it’s obviously handy.

Here’s a demo of a page that is set up in this way:

It’s probably more interesting to just visit this hash-link URL and see it open right up and work.

This came up for me while working on this documentation page where I wanted to be able to link to specific things that were otherwise “buried” in details elements.

As a bit of an enhancement, you might want to consider CSS like this:

:target {
  background: yellow;
  scroll-margin-block-start: 4rem;
}

That will apply some styling to the element that matches the hash in the URL, as well as push it away from the top edge of the browser window a little bit. In this case, it helps make sure the FAQ question is actually visible, not just the answer.

]]>
https://frontendmasters.com/blog/opening-a-details-element-from-the-url/feed/ 8 7019
Relatively New Things You Should Know about HTML Heading Into 2025 https://frontendmasters.com/blog/bone-up-html-2025/ https://frontendmasters.com/blog/bone-up-html-2025/#comments Mon, 06 Jan 2025 15:42:42 +0000 https://frontendmasters.com/blog/?p=4732 Not all of this is like absolutely brand spanking new just-dropped-in-2024 stuff. Some of it is, but generally it’s relatively new stuff that’s all pretty great. I’m pointing things out that I think are really worth knowing about. It’s possible you haven’t kept up too much with HTML developments as it tends to, rightfully, move a lot slower than CSS or JavaScript.

A group of details elements can behave like an accordion, among other improvements, but still have accessibility limitations.

We’ve had cross-browser <details> / <summary> support since 2016, but only recently have the abilities started to expand and clean up.

For one, you can make an “exclusive” accordion by grouping them together via the name attribute:

<details name="group"><summary>One</summary> ... </details>
<details name="group"><summary>At</summary> ... </details>
<details name="group"><summary>A</summary> ... </details>
<details name="group"><summary>Time</summary> ... </details>

Me, I mostly think the only-one-open-at-a-time thing is an anti-pattern (as do others), mostly because it’s weird to close something a user may have intentionally opened via side effect. But the web is a big place and certain specific designs I can see needing it to be effective so I don’t hate that it exists. At least I think using the term “accordion” is now appropriate in this context, but that there are still potential accessibility issues. Like imagine using this for a FAQ section where each question would normally be a header like <h3>, well, the semantics of that <h3> is wiped out by the <summary>, which is a “button”, so that’s not great.

Here’s an example of the accordion pattern being used with a group of horizontally laid out details elements. If more could be opened, it could cause horizontal scroll which I sure we can all imagine also sucks.

Note that those <details> elements are in a flexbox layout and are themselves display: flex; and only recently has that improved. (See Stephanie Stimac’s article on recent improvements.)

Ya know how the inside of a <details> is:

  1. <summary>
  2. … and whatever else

The “whatever else” can be one or more elements, and there isn’t any particularly clean way of selecting them. This is a CSS thing, but now we’ve got a ::details-content pseudo-element selector to get our hands on all that HTML in case it needs similar treatment (imagine fading it all in or out).

Here’s a great demo of using that, as well as other brand new CSS features, to make honest-to-god animating open/close details elements with arbitrary content in just HTML and CSS.

Styleable Selects are Coming

Browsers can’t just all the sudden make every aspect of a <select> and <option>s styleable, otherwise historical CSS that didn’t apply to them all the sudden does and it would wreak untold havoc on websites. The web doesn’t like to roll like that, and I applaud it for that backwards compatibility.

So… there needed to be an opt-in to make it work. A new element can work for that, which for a hot minute seemed like it would be <selectmenu>. But the progressive enhancement story for that basically sucked. So the new opt-in looks like it will be CSS triggered:

select,
::picker(select) {
  appearance: base-select;
}
Demo

Once you’ve opted in, you can apply styling to elements inside the <select> pretty freely, opening up huge doors to designing that experience.

There is some other funky things to know so I’d suggest reading this whole article. Even some new (tricky) HTML!

<select class="country-select">
  <button>
    <selectedoption></selectedoption>
  </button>
  <option value="" hidden>
    <figure></figure>
    <span>Select a country</span>
  </option>
  <option value="andorra">
    <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Flag_of_Andorra.svg/120px-Flag_of_Andorra.svg.png" alt="" />
    <span>Andorra</span>
  </option>
  ...
</select>

My favorite episode of Off the Main Thread this year was about styleable selects and all the interesting details behind them that will have knock-on effects.

Oh — also you can slap a line into a select menu

I kinda love how the old school name attribute was used with <details> for the accordion behavior.

And speaking of old school elements, you can put an <hr> within a <select> to just draw a line there (a “horizontal rule” as it were). You’ve still got <optgroup label="label"> for more emphatic grouping, but sometimes a line is all you need.

<select>
   <option>apple</option>
   <option>orange</option>
   <option>banana</option>
   <hr>
   <option>pepper</option>
   <option>squash</option>
   <option>broccoli</option>
</select>

You Can Open/Close a Popover with a Button Alone

No JavaScript is required to make the opening and closing of a popover work.

<button popovertarget="the-popover">Open Popover</button>

<div popover id="the-popover">
  I'm a popover.
  
  <button popovertarget="the-popover">Close Popover</button>
</div>

If you’d prefer that the popover be closed by just a click anywhere outside of it (that’s called a “light dismiss”) then update the popover attribute to popover="auto" and that’ll do it.

The “targetting” you can see happening with those buttons is an example of an “Invoker”, which is poised bring great power to HTML in coming years.

You can’t close a popover with a form submission like you can a <dialog>, but a popover probably isn’t a great place for a form anyway so that’s fine. Another interesting sidenote is you can make a <dialog popover> if you like, getting you this button behavior for free.

There are quite a few differences between dialogs and popovers, and both are awfully useful. Perhaps the most important two features being the focus trap potential and the fact they are promoted to the “top layer” of the rendered site, meaning no futzing with z-index.

The situation we’re in with popovers is that you pretty much need to be OK with either centered or edge-based positioning for them for now, like dialogs. They are just begging for anchor positioning, but the current guess is 2026 for interop on that.

Checkboxes can be Toggle Switches

It’s as easy as:

<input type="checkbox" switch>

Although only Safari supports it for now and it’s not actually specced yet so it could be said they jumped the gun a bit. Main discussion here. And I guess we should call it a “switch” to be proper.

I’m a fan here because the absolutely correct implementation of a toggle/switch was easy to get wrong from an accessibility standpoint, and this seems… hard to get wrong.

Daniel Yuschick has an article digging into the details. I like the idea that pseudo elements specific to this UI will be exposed, like ::thumb and ::track, but I can’t tell you what the status of that is right now. Even the official demos in Safari Nightly Preview with the flag turned on aren’t rendering properly for me.

Wrap your Search

This will be easy to remember. Got an area of your site that is meant for searching? Wrap it.

<search>

</search>

It’s the same as doing <div role="search">, but my bet is that you’ll actually remember to do it.

You probably don’t need noopener noreferrer on links anymore

I’ve used linters on projects that help ensure that a link like:

<a 
  href="https://google.com" 
  target="_blank"
>

Has attributes like this as well:

<a 
  href="https://google.com" 
  target="_blank"
  rel="noopener noreferrer"
>

The problem was, that actually gave the opened pages rights to their referrer: it opened a security hole that could potentially have leaked user information or opened the door to phishing.

Ben Werd

This is not new “2025” information, but I’m only just learning that this isn’t really needed anymore. Chrome was the last to automatically apply this behavior to _blank links and that was 2021. I’ve been doing it as I have a linter that always warns me about it, so in case your browser support targets agree, you might want to check those linter settings.

Declarative Shadow DOM Paves the Way for Better Web Component Frameworks

It used to be that if you wanted a Web Component to use Shadow DOM, the only way to do it was for it to be rendered by JavaScript. This meant that Web Components that wanted or needed to use Shadow DOM had no Server Side Rendering (SSR) story at all. That was a big gap, as all the major UI frameworks have coalesced on the idea that SSR is a good idea for many reasons (performance (perceived and actual), resilience, SEO, hosting options, etc).

Now we’ve got Declarative Shadow DOM and the gap has closed.

I think it’s cool to see the Shadow DOM at work with no JavaScript at all:

Demo

What I hope we’ll see in 2025 and beyond is frameworks actually help use this. It feels like foundational technology that mostly isn’t expected to be written by hand by authors, but instead used by libraries/frameworks to build great authoring experiences around.

React 19 was the last framework to fully correctly support Web Components, so perhaps we’ll see frameworks do more than support them now but embrace them. I would expect to see a “Next.js of Web Components” at some point.

Import Maps

I used to be fond of point out that a line like this isn’t standard JavaScript.

import React from "react";

That looks like ES Modules code, but the fact that the value in quotes doesn’t start with an absolute URL or a . (a relative path) means it’s… not. It’s just a convention that we all got used to writing because JavaScript bundlers understand it to mean “that’s a thing from npm so I should go look for it in the node_modules folder.

That’s changed now, since you can, via HTML Import Maps, map the value “react” to something else via Import Maps.

So if you executed that JavaScript above from an HTML file that included an import map like this:

<script type="importmap">
  {
    "imports": {
      "react": "https://esm.sh/react@18",
      "reactdom": "https://esm.sh/react-dom@18"
    }
  }
</script>

(Basic demo.)

It would work and import the JavaScript from those locations instead. This opens up the door for not needing to use a bundler and still having the benefit of an abstraction for importing dependencies. Having the possibility to avoid tooling can be huge for long term maintenance of projects.

Don’t Sleep on the inert Attribute

You can make an element, and the entire chunk of DOM under it, ignored completely from an interactivity perspective, just by by using the inert attribute. It’s quite powerful. No clicks, no focus, the element(s) are gone from the accessibility tree, nothing can be selected, heck, the on-page “find” command won’t even find text within there.

If you’ve got any reason at all to put stuff in the DOM but have it essentially behave as if it isn’t there, make it inert until you are ready for it not to be. Imagine a multi-step form that is all in the DOM right away, but only one step at a time is not inert, so future or previous form controls aren’t accidentally used until ready.

I’d tell you this is ideal for implementing modals, but you get this behavior for free, and easier because it can be placed anywhere, just by using <dialog>.

Keep your find-on-page working properly

Another interesting attribute here. We’ve long had hidden as an attribute (even though it’s kinda weak). The change here is it taking a value, like hidden="until-found". That will hide the element as hidden does, but the content within it will still be findable with on-page text search. When it is found, it’s on you to react to the DOM event beforematch to un-hide (by removing the attribute) the content so it can be seen the hidden attribute is removed automatically, plus you’ve got the beforematch event to hook into if you need to do additional work (thx Nathan).

Here’s the demo from chrome for developers, which you might need to try in Debug View for it to trigger properly.

You’d think this would be useful for <details> elements in how they hide content, but this behavior is baked into them. This is more solid evidence for using native features — because they get the details right (generally) rather than you needing to replicate them.

Multi-Page View Transitions

You have to opt-in to this via CSS like:

@view-transition {
  navigation: auto;
}

Then once you have, regular ol’ clicked links that move to a new page (on the same domain) can have view transitions. That is, you’ll see the page use a fade effect by default. But this unlocks an amazing amount of animation control over the transition between those two page loads.

I’m listing this as an HTML feature, because I find most of the useful-ness of multi-page view transitions are unlocked in the HTML. For instance…

<!-- homepage -->
<div class="card">
  <h3 
    style="view-transition-name: post-title-087afd;"
  >Blog Post Title</h3>
  <p>...</p>
  <a href="/blog-post">Read the article Blog Post Title</a>
</div>

<!-- blog post -->
<article>
  <h1 
    style="view-transition-name: post-title-087afd;"
  >Blog Post Title</h1>
  <p>...</p>
</article>

Above, I’m imagining the “card” as a component that is generated from data and is likely one of many on the page. So it requires having a unique view-transition-name, and really the only good opportunity to apply that is in HTML.

Responsive Video is catching up to Responsive Images

With the <picture> element in HTML we get the ability to use the <source> element within and control exactly when we swap out to different source images. It’s a powerful concept that can offer big performance wins.

That idea actually originally came from a concept with the <video> tag, but then that was bizarrely removed from (most) browsers. But now it’s back thanks to some serious work by Scott Jehl and others he convinced to help the revival along.

You can do media attribute control the sources, which will probably mostly be used for width query stuff, but it can do anything media can do. Scott wrote up some examples here, like:

<video autoplay controls playsinline muted loop>
  <source media="(orientation: landscape)" src="sunset-landscape-1080.mp4">
  <source src="sunset-portrait-1080.mp4">
</video>

HTML Imports are Coming Back

Just kidding they totally aren’t.

Did we miss anything?

Any newfangled HTML out there you’ve been eyeing up or using?

]]>
https://frontendmasters.com/blog/bone-up-html-2025/feed/ 17 4732
::details-content Looks Helpful https://frontendmasters.com/blog/details-content-looks-helpful/ https://frontendmasters.com/blog/details-content-looks-helpful/#comments Thu, 18 Jul 2024 15:23:44 +0000 https://frontendmasters.com/blog/?p=3059 The HTML for a <details> element is generally something like:

<details>
  <summary>Spoiler alert!</summary>

  <p>Rosebud was a sled.</p>
  <p>It's true!</p>
</details>

See how I put two <p> elements in there? That’s totally fine. Everything that isn’t the <summary> is visually hidden until the <details> is open, either via the open attribute or the summary is clicked/tapped.

So if you’re trying to select “all the content”, you’re either forced to use a wrapper or use an awkward selector like details > *:not(summary). The newly-specced ::details-content looks like a nice fix for this. (hat tip).

]]>
https://frontendmasters.com/blog/details-content-looks-helpful/feed/ 4 3059