{"id":1948,"date":"2024-04-30T12:12:46","date_gmt":"2024-04-30T18:12:46","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=1948"},"modified":"2024-05-07T08:25:50","modified_gmt":"2024-05-07T14:25:50","slug":"popover-api-is-here","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/popover-api-is-here\/","title":{"rendered":"Popover API is Here"},"content":{"rendered":"\n<p>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Popover_API\">Popover API<\/a> has <a href=\"https:\/\/caniuse.com\/mdn-api_htmlelement_popover\">support across browsers<\/a> now, and apparently the new way to say that is <a href=\"https:\/\/web.dev\/blog\/popover-api\">&#8220;landed in Baseline&#8221;<\/a>, albeit as &#8220;newly available&#8221; rather than &#8220;widely available&#8221;, which may be an <a href=\"https:\/\/web.dev\/blog\/baseline-definition-update\">important distinction<\/a> for you. <\/p>\n\n\n\n<p>A popover is very much like a <code><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Element\/dialog\">&lt;dialog&gt;<\/a><\/code> in that you don&#8217;t have to worry about where it exists in the DOM. When it&#8217;s open, it will be &#8220;on top&#8221;. That alone is a sick feature. I dislike having to put modals as children of the <code>&lt;body&gt;<\/code> just so they don&#8217;t have other elements inescapable stacking contexts to worry about.<\/p>\n\n\n\n<p>So then how is it different than a <code>&lt;dialog&gt;<\/code>? Popups are not &#8220;modal&#8221;. The web-world definition of modal is that it <em>forces<\/em> a user to deal with it (the rest of the page cannot receive focus, it is <code>inert<\/code>). Popups just&#8230; pop&#8230; up. The user is free to do anything else while a popup is open. Dialogs, not so much.<\/p>\n\n\n\n<p><a href=\"https:\/\/www.csscade.com\/popover-api\">Robin showed off<\/a> how extremely very <a href=\"https:\/\/codepen.io\/chriscoyier\/pen\/XWQwjPY\/8c499122e4ab74c76d4997e1ce8a3ce6\">easy it is to use<\/a>:<\/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\">button<\/span> <span class=\"hljs-attr\">popovertarget<\/span>=<span class=\"hljs-string\">\"mypopover\"<\/span>&gt;<\/span>Toggle the 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\">id<\/span>=<span class=\"hljs-string\">\"mypopover\"<\/span> <span class=\"hljs-attr\">popover<\/span>&gt;<\/span>Popover content<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/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>The fact that that&#8217;s possible in <em>HTML alone<\/em> is awfully nice. But of course you can style it with CSS if you like. Plus you get freebies like the fact that they ESC key closes it. Taking it a bit further, here&#8217;s an only slightly more fleshed out example using other cool freebies like <code>popovertargetaction=\"hide\"<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_mdzpGwq\" src=\"\/\/codepen.io\/anon\/embed\/mdzpGwq?height=450&amp;theme-id=47434&amp;slug-hash=mdzpGwq&amp;default-tab=html,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed mdzpGwq\" title=\"CodePen Embed mdzpGwq\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>(p.s. I dig the trick of getting a white \u274c with the <code>filter<\/code> property as shown above. Golf clap.)<\/p>\n\n\n\n<p>Robin goes on to say that the logic for using it is something like this:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<ol class=\"wp-block-list\">\n<li>Use&nbsp;<code>title<\/code>&nbsp;if the content in my popover is just text.<\/li>\n\n\n\n<li>Use the&nbsp;<code>popover<\/code>&nbsp;attribute if the content is more than plain text and like a menu of options or something.<\/li>\n\n\n\n<li>Use&nbsp;<code>&lt;dialog&gt;<\/code>&nbsp;if you need to force the user to make a decision or block all other interactions on the page.<\/li>\n<\/ol>\n<\/blockquote>\n\n\n\n<p>I only disagree on the first one. I think <code>title<\/code> is pretty useless and I only tend to include one if some accessibility tool warns me to add one, like on an <code>&lt;iframe><\/code>. The <code>title<\/code> attribute does nothing on mobile\/touch devices or screen readers. You can&#8217;t control anything about it, like how it looks, where it goes, or how long it takes to show up if it does at all. If we get more control over it (which, who knows, we might) then I&#8217;d be happy to take another look, but it seems likely it&#8217;ll still be a &#8220;only use if it&#8217;s a <em>just text<\/em>&#8221; situation.<\/p>\n\n\n\n<p>I&#8217;m certainly a fan of this API existing, but I do think it&#8217;s very hampered right now without the Anchor Position API being nearly <a href=\"https:\/\/caniuse.com\/css-anchor-positioning\">as well supported<\/a>. Massive use cases like tooltips or flyout menus aren&#8217;t really possible without it. Una has written about this as well. And <em>good news<\/em>, it can <em>also<\/em> be HTML powered. <\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" 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\">id<\/span>=<span class=\"hljs-string\">\"menu-toggle\"<\/span> <span class=\"hljs-attr\">popovertarget<\/span>=<span class=\"hljs-string\">\"menu-items\"<\/span>&gt;<\/span>\n  Open Menu\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"menu-items\"<\/span> <span class=\"hljs-attr\">popover<\/span> <span class=\"hljs-attr\">anchor<\/span>=<span class=\"hljs-string\">\"menu-toggle\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"item\"<\/span>&gt;<\/span>...<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"item\"<\/span>&gt;<\/span>...<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ul<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><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>Note the <code>anchor<\/code> attribute there connecting the two elements. So cool. And again, you can take finer grained control with CSS if you&#8217;d like. &#8220;Open right next to this other element&#8221; is clutch. Heads up though, <a href=\"https:\/\/twitter.com\/Una\/status\/1783913923072180603\">the <code>anchor<\/code> attribute is not ready yet<\/a>. <\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"twitter-tweet\" data-width=\"500\" data-dnt=\"true\"><p lang=\"en\" dir=\"ltr\">\ud83d\udea8 PSA for folks with anchor positioning demos: \ud83d\udea8<br><br>The anchor HTML attribute was removed from the initial launch.<br><br>You can only set up anchors in CSS now using anchor-name and position-anchor or the anchor-name directly in the anchor() function.<\/p>&mdash; Una \ud83c\uddfa\ud83c\udde6 (@Una) <a href=\"https:\/\/twitter.com\/Una\/status\/1783913923072180603?ref_src=twsrc%5Etfw\">April 26, 2024<\/a><\/blockquote><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<\/div><\/figure>\n\n\n\n<p>Taking it futher, <a href=\"https:\/\/codepen.io\/web-dot-dev\/pen\/XWxPBdr\">here&#8217;s another idea from Una<\/a> that uses an anchor element as a central position and then moves individual items in a circle around it. <\/p>\n\n\n\n\t\t<figure class=\"wp-block-jetpack-videopress jetpack-videopress-player\" style=\"\" >\n\t\t\t<div class=\"jetpack-videopress-player__wrapper\"> <iframe title=\"VideoPress Video Player\" aria-label='VideoPress Video Player' width='500' height='264' src='https:\/\/videopress.com\/embed\/D5XAErjw?cover=1&amp;autoPlay=0&amp;controls=1&amp;loop=0&amp;muted=0&amp;persistVolume=1&amp;playsinline=0&amp;preloadContent=metadata&amp;useAverageColor=1&amp;hd=0' frameborder='0' allowfullscreen data-resize-to-parent=\"true\" allow='clipboard-write'><\/iframe><script src='https:\/\/v0.wordpress.com\/js\/next\/videopress-iframe.js?m=1674852142'><\/script><\/div>\n\t\t\t\n\t\t\t\n\t\t<\/figure>\n\t\t\n\n\n<p>I&#8217;ll tell ya, Una is <em>ready<\/em> with all this! Particularly with the Anchor Positioning API, she&#8217;s got <a href=\"https:\/\/codepen.io\/collection\/ExkRWw\">a bunch of demos<\/a> and <a href=\"https:\/\/anchor-tool.com\/\">a little helper website<\/a> to make sure you can declare the positioning CSS you intend:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/anchor-tool.com\/\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/04\/Screenshot-2024-04-30-at-9.02.58%E2%80%AFAM.png?resize=1024%2C683&#038;ssl=1\" alt=\"\" class=\"wp-image-1963\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/04\/Screenshot-2024-04-30-at-9.02.58%E2%80%AFAM.png?resize=1024%2C683&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/04\/Screenshot-2024-04-30-at-9.02.58%E2%80%AFAM.png?resize=300%2C200&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/04\/Screenshot-2024-04-30-at-9.02.58%E2%80%AFAM.png?resize=768%2C512&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/04\/Screenshot-2024-04-30-at-9.02.58%E2%80%AFAM.png?resize=1536%2C1024&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/04\/Screenshot-2024-04-30-at-9.02.58%E2%80%AFAM.png?w=1644&amp;ssl=1 1644w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/a><\/figure>\n\n\n\n<p>I now will await patiently the Anchor Positioning API to drop everwhere. Alas, Popover was <a href=\"https:\/\/frontendmasters.com\/blog\/comparing-interop-2024-choices-to-the-popular-vote\/\">part of interop 2024<\/a> where Anchor was not. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>This API, which you can use entirely in HTML, allows you to open an element on top of *everything* despite where it lives in the DOM and without any particular styling. <\/p>\n","protected":false},"author":1,"featured_media":1975,"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":[121,7,120],"class_list":["post-1948","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-anchor","tag-css","tag-popover"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/04\/popup-thumb.jpg?fit=1000%2C500&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/1948","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=1948"}],"version-history":[{"count":9,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/1948\/revisions"}],"predecessor-version":[{"id":2080,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/1948\/revisions\/2080"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/1975"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=1948"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=1948"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=1948"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}