Popover
اللوحة المنبثقةpopover="auto" + role="dialog"
also calledpopup panel، floating panel، anchored overlay، flyout، popover panel، بوب أوفر، بوب أب، صندوق منبثق، نافذة طافية، لوحة عائمة، فقاعة منبثقة
A popover is a small layer that opens when you press a trigger, sits anchored to it, and carries real interactive content: fields, buttons, switches. It is non-modal, so the page underneath stays clickable, focus is not trapped inside it, and an outside click or the Escape key closes it. Four different things collect the same description, "a little box that pops up", and two questions separate them: what opens it, and whether it blocks what is underneath. A tooltip opens on hover or on keyboard focus, holds text that describes the element it is tied to, and must never carry a button, because the keyboard has no route into it. A menu is a row of commands where picking one closes it, arrow keys move through it rather than Tab, and it carries role="menu" with role="menuitem" instead of role="dialog". A modal covers the page under it and traps focus, declares as much with aria-modal="true", and does not go away without a decision. A hover card holds content the way a popover does, but the user never meant to open it, so nothing that exists only there belongs inside one, and a touch screen has no hover at all.
If you called it…
Live specimen
Interact with the demo. Every part is real and numbered.
تصفية النتائج
Anatomy: every part, named
Hover a row to locate it in the demo above.
Build prompt
How it behaves right-to-left
This section is ours alone.
Placement keywords: logical vs physical
mirrorsposition-area takes physical keywords (top, left, right, bottom) and logical ones (block-start, inline-start, inline-end), and only the logical set is resolved against direction. position-area: block-end span-inline-start puts the panel below the trigger extending toward the left in English and toward the right in Arabic, while position-area: bottom left stays on the left in both. Positioning libraries split the same way: Floating UI resolves the -start and -end suffixes from the direction it computes on the floating element itself, so bottom-start aligns to the right edge on an RTL page, while the base side (top, bottom, left, right) never mirrors however the page flips.
The arrow offset
mirrorsA positioning library hands you the arrow offset as a physical number: middlewareData.arrow.x in Floating UI is measured from the left edge of the panel whatever the page direction. Feed it to inset-inline-start and the browser measures from the right under [dir="rtl"], so the arrow lands at the opposite end; assign it to left exactly as it arrives and keep inset-inline-start for offsets you author yourself. Pure CSS drops the arithmetic: an absolutely positioned arrow sharing the panel position-anchor takes justify-self: anchor-center, centres itself on the anchor, and never asks which side is which.
A portalled panel loses dir
mirrorsA native popover stays where it is in the DOM and is only painted in the top layer, so it inherits dir like anything else. createPortal into document.body takes it out of the Arabic subtree: if dir="rtl" is written on a <div id="app"> instead of on <html>, the portalled panel inherits LTR, Arabic text goes flush left, trailing punctuation lands at the wrong end, and every logical property inside resolves backwards. Put dir on <html>, or set it explicitly on the portal root when you create it, because Floating UI reads that same LTR direction off the panel and aligns bottom-start to the wrong edge on top of everything else.
Flipping at the viewport edge
mirrorsWhich edge runs out of room changes with direction: a panel placed with span-inline-start extends to the left in English and to the right in Arabic, so a trigger that never flipped in English starts flipping in Arabic. flip-inline inside position-try-fallbacks works on the inline axis and follows direction by itself, while a hand-rolled check such as if (rect.right > innerWidth) tests one physical edge and never sees the overflow on the other side. The measurement flips too: in an RTL horizontal scroller current browsers report scrollLeft as 0 at the far right, going negative as the user scrolls left, so a formula like trigger.offsetLeft - scroller.scrollLeft pushes the panel the wrong way as long as it assumes a positive value.
The block axis does not mirror
never mirrorsdirection acts on the inline axis only, so a panel that opens below its trigger still opens below it in Arabic, only writing-mode would move it, and block-end in position-area needs no [dir="rtl"] exception. A blanket rule such as [dir="rtl"] .popover { transform: scaleX(-1) } mirrors the text and the icons along with the box and leaves the whole panel drawn backwards. One thing does need a hand-written override: transform-origin accepts no logical keyword on either axis, so a scale-in written as transform-origin: top left has to be restated as top right under [dir="rtl"] while the vertical half stays top.
In code
Each row is one framework's word for the same thing. Take the row your project speaks.
See also
Updated · 2026-08-19