{"id":4732,"date":"2025-01-06T10:42:42","date_gmt":"2025-01-06T15:42:42","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=4732"},"modified":"2025-01-07T11:40:42","modified_gmt":"2025-01-07T16:40:42","slug":"bone-up-html-2025","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/bone-up-html-2025\/","title":{"rendered":"Relatively New Things You Should Know about HTML Heading Into 2025"},"content":{"rendered":"\n<p>Not all of this is like <em>absolutely brand spanking new<\/em> just-dropped-in-2024 stuff. Some of it is, but generally it&#8217;s <em>relatively<\/em> new stuff that&#8217;s all pretty great. I&#8217;m pointing things out that I think are really worth knowing about. It&#8217;s possible you haven&#8217;t kept up too much with HTML developments as it tends to, rightfully, move a lot slower than CSS or JavaScript. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A group of details elements can behave like an accordion, among other improvements, but still have accessibility limitations.<\/h2>\n\n\n\n<p>We&#8217;ve had cross-browser <code>&lt;details&gt;<\/code> \/ <code>&lt;summary&gt;<\/code> support since 2016, but only recently have the abilities started to expand and clean up. <\/p>\n\n\n\n<p>For one, you can make an &#8220;exclusive&#8221; accordion by grouping them together via the <code>name<\/code> attribute:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">details<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"group\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">summary<\/span>&gt;<\/span>One<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">summary<\/span>&gt;<\/span> ... <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">details<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">details<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"group\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">summary<\/span>&gt;<\/span>At<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">summary<\/span>&gt;<\/span> ... <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">details<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">details<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"group\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">summary<\/span>&gt;<\/span>A<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">summary<\/span>&gt;<\/span> ... <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">details<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">details<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"group\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">summary<\/span>&gt;<\/span>Time<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">summary<\/span>&gt;<\/span> ... <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">details<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Me, I mostly think the only-one-open-at-a-time thing is an anti-pattern (<a href=\"https:\/\/yatil.net\/blog\/exclusive-accordions\">as do others<\/a>), mostly because it&#8217;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&#8217;t hate that it exists. At least I think <a href=\"https:\/\/daverupert.com\/2019\/12\/why-details-is-not-an-accordion\/\">using the term &#8220;accordion&#8221;<\/a> 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 <code>&lt;h3&gt;<\/code>, well, the semantics of that <code>&lt;h3&gt;<\/code> is wiped out by the <code>&lt;summary&gt;<\/code>, which is a &#8220;button&#8221;, so that&#8217;s not great.<\/p>\n\n\n\n<p>Here&#8217;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.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_bGZbGZP\" src=\"\/\/codepen.io\/anon\/embed\/bGZbGZP?height=450&amp;theme-id=47434&amp;slug-hash=bGZbGZP&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed bGZbGZP\" title=\"CodePen Embed bGZbGZP\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>Note that those <code>&lt;details&gt;<\/code> elements are in a flexbox layout and are themselves <code>display: flex;<\/code> and only recently has that improved. (See <a href=\"https:\/\/blog.stephaniestimac.com\/posts\/2024\/10\/html-details-and-summary-update\/\">Stephanie Stimac&#8217;s article<\/a> on recent improvements.)<\/p>\n\n\n\n<p>Ya know how the inside of a <code>&lt;details&gt;<\/code> is:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><code>&lt;summary&gt;<\/code><\/li>\n\n\n\n<li>&#8230; and whatever else<\/li>\n<\/ol>\n\n\n\n<p>The &#8220;whatever else&#8221; can be one or more elements, and there isn&#8217;t any particularly clean way of selecting them. This is a CSS thing, but now we&#8217;ve got a <code>::details-content<\/code> pseudo-element selector to get our hands on <em>all<\/em> that HTML in case it needs similar treatment (imagine fading it all in or out).<\/p>\n\n\n\n<p>Here&#8217;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.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_jOorzPv\" src=\"\/\/codepen.io\/anon\/embed\/jOorzPv?height=450&amp;theme-id=47434&amp;slug-hash=jOorzPv&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed jOorzPv\" title=\"CodePen Embed jOorzPv\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Styleable Selects are Coming<\/h2>\n\n\n\n<p>Browsers can&#8217;t just all the sudden make every aspect of a <code>&lt;select&gt;<\/code> and <code>&lt;option&gt;<\/code>s styleable, otherwise historical CSS that <em>didn&#8217;t<\/em> apply to them all the sudden <em>does<\/em> and it would wreak untold havoc on websites. The web doesn&#8217;t like to roll like that, and I applaud it for that backwards compatibility. <\/p>\n\n\n\n<p>So&#8230; 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 <code>&lt;selectmenu&gt;<\/code>. But the progressive enhancement story for that basically sucked. So <a href=\"https:\/\/developer.chrome.com\/blog\/rfc-customizable-select#opting-in_to_the_new_select\">the new opt-in<\/a> looks like it will be CSS triggered:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">select<\/span>,\n<span class=\"hljs-selector-pseudo\">::picker(select)<\/span> {\n  <span class=\"hljs-attribute\">appearance<\/span>: base-select;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"570\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/12\/select-fallback_1920.png?resize=1024%2C570&#038;ssl=1\" alt=\"\" class=\"wp-image-4875\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/12\/select-fallback_1920.png?resize=1024%2C570&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/12\/select-fallback_1920.png?resize=300%2C167&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/12\/select-fallback_1920.png?resize=768%2C428&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/12\/select-fallback_1920.png?w=1218&amp;ssl=1 1218w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><figcaption class=\"wp-element-caption\"><a href=\"https:\/\/codepen.io\/web-dot-dev\/pen\/LYKqgXZ\">Demo<\/a><\/figcaption><\/figure>\n\n\n\n<p>Once you&#8217;ve opted in, you can apply styling to elements inside the <code>&lt;select&gt;<\/code> pretty freely, opening up huge doors to designing that experience. <\/p>\n\n\n\n<p>There is some other funky things to know so I&#8217;d suggest reading <a href=\"https:\/\/developer.chrome.com\/blog\/rfc-customizable-select\">this whole article<\/a>. Even some new (<a href=\"https:\/\/jakearchibald.com\/2024\/how-should-selectedoption-work\/\">tricky<\/a>) HTML! <\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">select<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"country-select\"<\/span>&gt;<\/span>\n<\/span><\/span><mark class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n<\/span><\/mark><mark class='shcb-loc'><span>    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">selectedoption<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">selectedoption<\/span>&gt;<\/span>\n<\/span><\/mark><mark class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n<\/span><\/mark><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"\"<\/span> <span class=\"hljs-attr\">hidden<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">figure<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">figure<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>Select a country<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"andorra\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/thumb\/1\/19\/Flag_of_Andorra.svg\/120px-Flag_of_Andorra.svg.png\"<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"\"<\/span> \/&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>Andorra<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  ...\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">select<\/span>&gt;<\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>My favorite episode of Off the Main Thread this year was <a href=\"https:\/\/offthemainthread.tech\/episode\/stylable-select-element\/\">about styleable selects<\/a> and all the interesting details behind them that will have knock-on effects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Oh \u2014 also you can slap a line into a select menu<\/h2>\n\n\n\n<p>I kinda love how the old school <code>name<\/code> attribute was used with <code>&lt;details&gt;<\/code> for the accordion behavior. <\/p>\n\n\n\n<p>And speaking of old school elements, you can put an <code>&lt;hr&gt;<\/code> within a <code>&lt;select&gt;<\/code> to just draw a line there (a &#8220;horizontal rule&#8221; as it were). You&#8217;ve still got <code>&lt;optgroup label=\"label\"&gt;<\/code> for more emphatic grouping, but sometimes a line is all you need.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">select<\/span>&gt;<\/span>\n   <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span>&gt;<\/span>apple<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n   <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span>&gt;<\/span>orange<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n   <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span>&gt;<\/span>banana<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n   <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">hr<\/span>&gt;<\/span>\n   <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span>&gt;<\/span>pepper<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n   <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span>&gt;<\/span>squash<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n   <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span>&gt;<\/span>broccoli<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">select<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_OPLxpMV\" src=\"\/\/codepen.io\/anon\/embed\/OPLxpMV?height=450&amp;theme-id=47434&amp;slug-hash=OPLxpMV&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed OPLxpMV\" title=\"CodePen Embed OPLxpMV\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">You Can Open\/Close a Popover with a Button Alone<\/h2>\n\n\n\n<p>No JavaScript is required to make the opening and closing of a popover work.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">popovertarget<\/span>=<span class=\"hljs-string\">\"the-popover\"<\/span>&gt;<\/span>Open Popover<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">popover<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"the-popover\"<\/span>&gt;<\/span>\n  I'm a popover.\n  \n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">popovertarget<\/span>=<span class=\"hljs-string\">\"the-popover\"<\/span>&gt;<\/span>Close Popover<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If you&#8217;d prefer that the popover be closed by just a click anywhere outside of it (that&#8217;s called a &#8220;light dismiss&#8221;) then update the popover attribute to <code>popover=\"auto\"<\/code> and that&#8217;ll do it.<\/p>\n\n\n\n<p>The &#8220;targetting&#8221; you can see happening with those buttons is an example of an <a href=\"https:\/\/thathtml.blog\/2023\/11\/invokers-are-coming\/\">&#8220;Invoker&#8221;<\/a>, which is poised bring great power to HTML in coming years. <\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_GgKvypJ\" src=\"\/\/codepen.io\/anon\/embed\/GgKvypJ?height=450&amp;theme-id=47434&amp;slug-hash=GgKvypJ&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed GgKvypJ\" title=\"CodePen Embed GgKvypJ\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>You can&#8217;t close a popover with a form submission like you can a <code>&lt;dialog&gt;<\/code>, but a popover probably isn&#8217;t a great place for a form anyway so that&#8217;s fine. Another interesting sidenote is you can make a <code>&lt;dialog popover&gt;<\/code> if you like, getting you this button behavior for free.<\/p>\n\n\n\n<p><a href=\"https:\/\/frontendmasters.com\/blog\/whats-the-difference-between-htmls-dialog-element-and-popovers\/\">There are quite a few differences between dialogs and popovers<\/a>, and both are awfully useful. Perhaps the most important two features being the focus trap potential and the fact they are promoted to the &#8220;top layer&#8221; of the rendered site, meaning no futzing with <code>z-index<\/code>. <\/p>\n\n\n\n<p>The situation we&#8217;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 <a href=\"https:\/\/blogs.igalia.com\/plampe\/contributing-to-css-anchor-positioning-in-webkit\/\">current guess is 2026<\/a> for interop on that. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Checkboxes can be Toggle Switches<\/h2>\n\n\n\n<p>It&#8217;s as easy as:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"checkbox\"<\/span> <span class=\"hljs-attr\">switch<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Although only Safari supports it for now and it&#8217;s not actually specced yet so it could be said they jumped the gun a bit. <a href=\"https:\/\/github.com\/whatwg\/html\/pull\/9546\">Main discussion here<\/a>. And I guess we should call it a &#8220;switch&#8221; to be proper.<\/p>\n\n\n\n<p>I&#8217;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&#8230; hard to get wrong. <\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_QWREJPR\" src=\"\/\/codepen.io\/anon\/embed\/QWREJPR?height=450&amp;theme-id=47434&amp;slug-hash=QWREJPR&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed QWREJPR\" title=\"CodePen Embed QWREJPR\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p><a href=\"https:\/\/www.smashingmagazine.com\/2024\/05\/switching-it-up-html-latest-control\/\">Daniel Yuschick has an article<\/a> digging into the details. I like the idea that pseudo elements specific to this UI will be exposed, like <code>::thumb<\/code>&nbsp;and&nbsp;<code>::track<\/code>, but I can&#8217;t tell you what the status of that is right now. Even <a href=\"https:\/\/webkit.org\/demos\/html-switch\/\">the official demos<\/a> in Safari Nightly Preview <em>with<\/em> the flag turned on aren&#8217;t rendering properly for me.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrap your Search<\/h2>\n\n\n\n<p>This will be easy to remember. Got an area of your site that is meant for searching? Wrap it.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">search<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">search<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>It&#8217;s the same as doing <code>&lt;div role=\"search\"&gt;<\/code>, but my bet is that you&#8217;ll actually remember to do it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">You probably don&#8217;t need noopener noreferrer on links anymore<\/h2>\n\n\n\n<p>I&#8217;ve used linters on projects that help ensure that a link like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> \n  <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/google.com\"<\/span> \n  <span class=\"hljs-attr\">target<\/span>=<span class=\"hljs-string\">\"_blank\"<\/span>\n&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Has attributes like this as well:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">  <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/google.com\"<\/span> <\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">  <span class=\"hljs-attr\">target<\/span>=<span class=\"hljs-string\">\"_blank\"<\/span><\/span>\n<\/span><\/span><mark class='shcb-loc'><span><span class=\"hljs-tag\">  <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"noopener noreferrer\"<\/span><\/span>\n<\/span><\/mark><span class='shcb-loc'><span><span class=\"hljs-tag\">&gt;<\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>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.<\/p>\n<cite><a href=\"https:\/\/werd.io\/2024\/browsers-imply-noopener-for-links-in-new-tab\">Ben Werd<\/a><\/cite><\/blockquote>\n\n\n\n<p>This is not new &#8220;2025&#8221; information, but I&#8217;m only just learning that this isn&#8217;t really needed anymore. Chrome was <a href=\"https:\/\/chromestatus.com\/feature\/6140064063029248\">the last to automatically apply this behavior<\/a> to <code>_blank<\/code> links and that was 2021. I&#8217;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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Declarative Shadow DOM Paves the Way for Better Web Component Frameworks<\/h2>\n\n\n\n<p>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). <\/p>\n\n\n\n<p>Now we&#8217;ve got <a href=\"https:\/\/12daysofweb.dev\/2024\/declarative-shadow-dom\/\">Declarative Shadow DOM<\/a> and the gap has closed. <\/p>\n\n\n\n<p>I think it&#8217;s cool to see the Shadow DOM at work with no JavaScript at all:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"963\" height=\"1024\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/Screenshot-2025-01-01-at-10.03.35%E2%80%AFAM.png?resize=963%2C1024&#038;ssl=1\" alt=\"\" class=\"wp-image-4913\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/Screenshot-2025-01-01-at-10.03.35%E2%80%AFAM.png?resize=963%2C1024&amp;ssl=1 963w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/Screenshot-2025-01-01-at-10.03.35%E2%80%AFAM.png?resize=282%2C300&amp;ssl=1 282w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/Screenshot-2025-01-01-at-10.03.35%E2%80%AFAM.png?resize=768%2C816&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/Screenshot-2025-01-01-at-10.03.35%E2%80%AFAM.png?w=1270&amp;ssl=1 1270w\" sizes=\"auto, (max-width: 963px) 100vw, 963px\" \/><figcaption class=\"wp-element-caption\"><a href=\"https:\/\/codepen.io\/chriscoyier\/pen\/pvzWqye?editors=1000\">Demo<\/a><\/figcaption><\/figure>\n\n\n\n<p>What I hope we&#8217;ll see in 2025 and beyond is frameworks actually help use this. It feels like foundational technology that mostly isn&#8217;t expected to be written by hand by authors, but instead used by libraries\/frameworks to build great authoring experiences around. <\/p>\n\n\n\n<p>React 19 was the last framework to <a href=\"https:\/\/custom-elements-everywhere.com\/\">fully correctly support Web Components<\/a>, so perhaps we&#8217;ll see frameworks do more than support them now but embrace them. I would expect to see a &#8220;Next.js of Web Components&#8221; at some point.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Import Maps<\/h2>\n\n\n\n<p>I used to be fond of point out that a line like this <em>isn&#8217;t standard JavaScript.<\/em><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>That looks like ES Modules code, but the fact that the value in quotes doesn&#8217;t start with an absolute URL or a <code>.<\/code> (a relative path) means it&#8217;s&#8230; not. It&#8217;s just a convention that we all got used to writing because JavaScript bundlers understand it to mean &#8220;that&#8217;s a thing from npm so I should go look for it in the <code>node_modules<\/code> folder. <\/p>\n\n\n\n<p>That&#8217;s changed now, since you can, via HTML <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Element\/script\/type\/importmap\">Import Maps<\/a>, map the value &#8220;react&#8221; to something else via Import Maps.<\/p>\n\n\n\n<p>So if you executed that JavaScript above from an HTML file that included an import map like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"importmap\"<\/span>&gt;<\/span><span class=\"actionscript\">\n  {\n    <span class=\"hljs-string\">\"imports\"<\/span>: {\n      <span class=\"hljs-string\">\"react\"<\/span>: <span class=\"hljs-string\">\"https:\/\/esm.sh\/react@18\"<\/span>,\n      <span class=\"hljs-string\">\"reactdom\"<\/span>: <span class=\"hljs-string\">\"https:\/\/esm.sh\/react-dom@18\"<\/span>\n    }\n  }\n<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"has-small-font-size\"><a href=\"https:\/\/codepen.io\/chriscoyier\/pen\/EaYbwKM\">(Basic demo.)<\/a><\/p>\n\n\n\n<p>It would work and import the JavaScript from those locations instead. This opens up the door for <em>not needing to use a bundler<\/em> 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Don&#8217;t Sleep on the <code>inert<\/code> Attribute<\/h2>\n\n\n\n<p>You can make an element, and the entire chunk of DOM under it, ignored completely from an interactivity perspective, just by by using the <code>inert<\/code> attribute. It&#8217;s quite powerful. No clicks, no focus, the element(s) are gone from the accessibility tree, nothing can be selected, heck, the on-page &#8220;find&#8221; command won&#8217;t even find text within there.<\/p>\n\n\n\n<p>If you&#8217;ve got any reason at all to put stuff in the DOM but have it essentially behave as if it isn&#8217;t there, make it <code>inert<\/code> 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 <em>not<\/em> inert, so future or previous form controls aren&#8217;t accidentally used until ready. <\/p>\n\n\n\n<p>I&#8217;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 <code>&lt;dialog&gt;<\/code>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Keep your find-on-page working properly<\/h2>\n\n\n\n<p>Another interesting attribute here. We&#8217;ve long had <code>hidden<\/code> as an attribute (even though it&#8217;s <a href=\"https:\/\/meowni.ca\/hidden.is.a.lie.html\">kinda weak<\/a>). The change here is it taking a value, like <code>hidden=\"until-found\"<\/code>. That will hide the element as <code>hidden<\/code> does, but the content within it will still be findable with on-page text search. When it is found, <s>it&#8217;s on you to react to the DOM event <code>beforematch<\/code> to un-hide (by removing the attribute) the content so it can be seen<\/s> the <code>hidden<\/code> attribute is removed automatically, plus you&#8217;ve got the <code>beforematch<\/code> event to hook into if you need to do additional work (<a href=\"https:\/\/frontendmasters.com\/blog\/bone-up-html-2025\/#comment-18926\">thx Nathan<\/a>). <\/p>\n\n\n\n<p>Here&#8217;s the demo <a href=\"https:\/\/developer.chrome.com\/docs\/css-ui\/hidden-until-found\">from chrome for developers<\/a>, which you might need to try <a href=\"https:\/\/cdpn.io\/pen\/debug\/JjMxmom\">in Debug View<\/a> for it to trigger properly.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_JjMxmom\" src=\"\/\/codepen.io\/anon\/embed\/JjMxmom?height=450&amp;theme-id=47434&amp;slug-hash=JjMxmom&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed JjMxmom\" title=\"CodePen Embed JjMxmom\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>You&#8217;d think this would be useful for <code>&lt;details&gt;<\/code> elements in how they hide content, but this behavior is baked into them. This is more solid evidence for using native features \u2014 because they get the details right (generally) rather than you needing to replicate them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Multi-Page View Transitions<\/h2>\n\n\n\n<p>You have to opt-in to this via CSS like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@view-transition<\/span> {\n  <span class=\"hljs-selector-tag\">navigation<\/span>: <span class=\"hljs-selector-tag\">auto<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then once you have, regular ol&#8217; clicked links that move to a new page (on the same domain) can have view transitions. That is, you&#8217;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.<\/p>\n\n\n\n<p>I&#8217;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&#8230;<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-code-table\"><span class='shcb-loc'><span><span class=\"hljs-comment\">&lt;!-- homepage --&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"card\"<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span> <\/span>\n<\/span><\/span><mark class='shcb-loc'><span><span class=\"hljs-tag\">    <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">\"view-transition-name: post-title-087afd;\"<\/span><\/span>\n<\/span><\/mark><span class='shcb-loc'><span><span class=\"hljs-tag\">  &gt;<\/span>Blog Post Title<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>...<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/blog-post\"<\/span>&gt;<\/span>Read the article Blog Post Title<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-comment\">&lt;!-- blog post --&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span> <\/span>\n<\/span><\/span><mark class='shcb-loc'><span><span class=\"hljs-tag\">    <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">\"view-transition-name: post-title-087afd;\"<\/span><\/span>\n<\/span><\/mark><span class='shcb-loc'><span><span class=\"hljs-tag\">  &gt;<\/span>Blog Post Title<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>...<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n<\/span><\/span><span class='shcb-loc'><span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n<\/span><\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Above, I&#8217;m imagining the &#8220;card&#8221; as a component that is generated from data and is likely one of many on the page. So it <em>requires<\/em> having a <em>unique<\/em> <code>view-transition-name<\/code>, and really the only good opportunity to apply that is in HTML.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Responsive Video is catching up to Responsive Images<\/h2>\n\n\n\n<p>With the <code>&lt;picture&gt;<\/code> element in HTML we get the ability to use the <code>&lt;source&gt;<\/code> element within and control exactly when we swap out to different source <em>images<\/em>. It&#8217;s a powerful concept that can offer big performance wins.<\/p>\n\n\n\n<p>That idea actually originally came from a concept with the <code>&lt;video&gt;<\/code> tag, but then that was bizarrely removed from (most) browsers. But now it&#8217;s back thanks to <a href=\"https:\/\/scottjehl.com\/posts\/responsive-video\/\">some serious work by Scott Jehl<\/a> and others he convinced to help the revival along.<\/p>\n\n\n\n<p>You can do <code>media<\/code> attribute control the sources, which will probably mostly be used for width query stuff, but it can do anything media can do. <a href=\"https:\/\/www.htmhell.dev\/adventcalendar\/2024\/19\/\">Scott wrote up some examples here<\/a>, like:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">video<\/span> <span class=\"hljs-attr\">autoplay<\/span> <span class=\"hljs-attr\">controls<\/span> <span class=\"hljs-attr\">playsinline<\/span> <span class=\"hljs-attr\">muted<\/span> <span class=\"hljs-attr\">loop<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">source<\/span> <span class=\"hljs-attr\">media<\/span>=<span class=\"hljs-string\">\"(orientation: landscape)\"<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"sunset-landscape-1080.mp4\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">source<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"sunset-portrait-1080.mp4\"<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">video<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">HTML Imports are Coming Back<\/h2>\n\n\n\n<p>Just kidding they totally aren&#8217;t.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Did we miss anything?<\/h2>\n\n\n\n<p>Any newfangled HTML out there you&#8217;ve been eyeing up or using?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Accordion details, toggle switches, styleable selects, responsive video, and more! <\/p>\n","protected":false},"author":1,"featured_media":4930,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[211,98,31,276,264,101],"class_list":["post-4732","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-details","tag-dialog","tag-html","tag-import-maps","tag-inputs","tag-view-transitions"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/pexels-photo-38196.jpeg?fit=1880%2C1253&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/4732","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=4732"}],"version-history":[{"count":25,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/4732\/revisions"}],"predecessor-version":[{"id":4941,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/4732\/revisions\/4941"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/4930"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=4732"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=4732"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=4732"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}