CSS Anchor Positioning & Popover API: Kein JS mehr für Popups im Jahr 2026

前端工程

CSS Anchor Positioning: Die „Emanzipationsproklamation" für Frontend-Entwickler

Jeder Frontend-Entwickler hat diesen Schmerz erlebt: JS zur Berechnung von Tooltip-Positionen verwenden, Boundary-Overflow behandeln, Scroll- und Resize-Events abhören... Jetzt kann CSS all dies nativ erledigen.

Historischer Rückblick: 2016 nutzten wir Popper.js, 2020 Floating UI, und 2026 haben wir endlich natives CSS-Anchor-Positioning. Nach 10 Jahren ist Popup-Positionierung keine JS-Aufgabe mehr.

Evolution von JS-Positionierung zu CSS-Positionierung

2016    jQuery offset() + manuelle Berechnung
        Neuberechnung bei jedem Scroll/Resize

2020    Floating UI / Popper.js
        Auto-Flip, Offset, Boundary-Erkennung
        Aber erfordert immer noch JS-Init und Destroy

2024    CSS Anchor Positioning (Chrome 125+)
        Reine CSS-deklarative Positionierung
        Browser verarbeitet Grenzen und Scrolling nativ

2026    Anchor Positioning + Popover API
        Reine CSS-Popups: Zero-JS-Toggle, Zero-JS-Positionierung
        Vollständige deklarative Popup-Lösung

anchor-name und position-anchor

Grundlegende Verwendung

<div class="card">
  <button class="trigger">Weitere Aktionen</button>
  <div class="dropdown">Dropdown-Inhalt</div>
</div>
.trigger {
  anchor-name: --my-anchor;
}

.dropdown {
  position: fixed;
  position-anchor: --my-anchor;
  top: anchor(bottom);
  left: anchor(left);
}

anchor()-Funktionsreferenz

.tooltip {
  position: fixed;
  position-anchor: --trigger-anchor;

  /* Relativ zu Anker-Kanten */
  top: anchor(bottom);
  bottom: anchor(top);
  left: anchor(left);
  right: anchor(right);

  /* Anker-Mittelpunkte */
  left: anchor(50%);
  top: anchor(50%);

  /* Mit Versatz */
  top: calc(anchor(bottom) + 8px);
  left: calc(anchor(left) - 4px);
}

position-area: Neun-Feld-Positionierung

Neun-Feld-Syntax

┌─────────────┬─────────────┬─────────────┐
│  top left   │   top center│  top right  │
│             │             │             │
├─────────────┼─────────────┼─────────────┤
│ center left │   center    │ center right│
│             │             │             │
├─────────────┼─────────────┼─────────────┤
│ bottom left │bottom center│ bottom right│
│             │             │             │
└─────────────┴─────────────┴─────────────┘
.tooltip-below {
  position-area: bottom center;
}

.tooltip-right {
  position-area: center right;
}

.dropdown-below-left {
  position-area: bottom left;
}

position-fallback und mehrstufige Fallback-Strategie

Boundary-Overflow Auto-Flip

.dropdown {
  position: fixed;
  position-anchor: --trigger;

  /* Bevorzugt: unterhalb des Ankers */
  top: anchor(bottom);
  left: anchor(left);

  position-fallback: --dropdown-fallback;
}

@position-fallback --dropdown-fallback {
  /* Fallback 1: oberhalb des Ankers */
  @try {
    bottom: anchor(top);
    left: anchor(left);
  }

  /* Fallback 2: unterhalb des Ankers, rechtsbündig */
  @try {
    top: anchor(bottom);
    right: anchor(right);
  }

  /* Fallback 3: oberhalb des Ankers, rechtsbündig */
  @try {
    bottom: anchor(top);
    right: anchor(right);
  }
}

Popover API: Native Popover-Schicht

Grundlegende Verwendung

<button popovertarget="my-popover">Popover öffnen</button>

<div id="my-popover" popover>
  <p>Dies ist nativer Popover-Inhalt</p>
  <button popovertarget="my-popover" popovertargetaction="hide">Schließen</button>
</div>
[popover] {
  position: fixed;
  inset: unset;
  margin: 0;
  padding: 16px;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  background: white;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}

Popover + Anchor Kombination

<button class="menu-trigger" popovertarget="menu-popover">Menü</button>

<div id="menu-popover" popover class="menu-dropdown">
  <a href="/profile">Profil</a>
  <a href="/settings">Einstellungen</a>
  <a href="/logout">Abmelden</a>
</div>
.menu-trigger {
  anchor-name: --menu-anchor;
}

.menu-dropdown {
  position-anchor: --menu-anchor;
  position-area: bottom left;
  margin: 4px;
}

anchor-size(): Auto-Größenanpassung basierend auf dem Anker-Element

.trigger {
  anchor-name: --select-anchor;
}

.select-dropdown {
  position: fixed;
  position-anchor: --select-anchor;
  top: anchor(bottom);
  left: anchor(left);

  /* Dropdown-Breite folgt dem Trigger-Button */
  width: anchor-size(width);

  /* Oder Mindestbreite festlegen */
  min-width: anchor-size(width);
}

Praxis: Gängige UI-Komponenten in reinem CSS

Tooltip

<span class="tooltip-trigger" tabindex="0">
  Hilfe
  <span class="tooltip-content" role="tooltip">Dies ist ein Hilfe-Tooltip</span>
</span>
.tooltip-trigger {
  anchor-name: --tt-anchor;
  position: relative;
  cursor: help;
  text-decoration: underline dotted;
}

.tooltip-content {
  position: fixed;
  position-anchor: --tt-anchor;
  position-area: top center;
  margin: 8px;
  padding: 6px 10px;
  background: #1f2937;
  color: white;
  border-radius: 4px;
  font-size: 13px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s;

  position-fallback: --tt-fallback;
}

.tooltip-trigger:hover .tooltip-content,
.tooltip-trigger:focus .tooltip-content {
  opacity: 1;
}

@position-fallback --tt-fallback {
  @try { position-area: bottom center; }
  @try { position-area: center right; }
  @try { position-area: center left; }
}
<button class="dropdown-trigger" popovertarget="dd-menu">
  Optionen ▾
</button>
<div id="dd-menu" popover class="dropdown-menu">
  <button class="dropdown-item">Bearbeiten</button>
  <button class="dropdown-item">Kopieren</button>
  <button class="dropdown-item">Löschen</button>
</div>
.dropdown-trigger {
  anchor-name: --dd-anchor;
}

.dropdown-menu {
  position-anchor: --dd-anchor;
  position-area: bottom left;
  margin: 4px;
  width: anchor-size(width);
  min-width: 160px;
  padding: 4px;
  border-radius: 8px;
  background: white;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);

  position-fallback: --dd-fallback;
}

.dropdown-item {
  display: block;
  width: 100%;
  padding: 8px 12px;
  border: none;
  background: none;
  text-align: left;
  border-radius: 4px;
  cursor: pointer;
}

.dropdown-item:hover {
  background: #f3f4f6;
}

@position-fallback --dd-fallback {
  @try { position-area: top left; }
}

Vergleich mit Floating UI/Popper.js

Dimension CSS Anchor + Popover Floating UI
JS-Abhängigkeit Zero JS 12KB gzip
Leistung Browser-nativ JS-Berechnung
Deklarativ CSS-deklarativ JS-imperativ
Boundary-Flip position-fallback flip()-Middleware
Versatz margin/anchor() offset()-Middleware
Pfeil CSS-Pseudo-Element SVG/HTML-Element
Virtuelle Elemente Nicht unterstützt Unterstützt
Dynamischer Inhalt Auto-Follow Benötigt update()
Browser-Support Chrome 125+ Alle Browser
SSR-freundlich Vollständig freundlich Benötigt Client-JS

Wann Sie noch JS-Bibliotheken benötigen

Szenarien, die noch Floating UI erfordern:
1. Ältere Browser unterstützen müssen (Safari < 17.5, Firefox < 131)
2. Virtuelle Element-Positionierung benötigen (Cursor-Position folgen)
3. Komplexe Middleware-Ketten benötigen (autoUpdate, size, hide)
4. React/Vue-deklarative Wrapper-Anforderungen

Szenarien, in denen CSS Anchor funktioniert:
1. Tooltip, Dropdown, Popover und andere Standard-Popups
2. Nur moderne Browser unterstützen müssen
3. Zero-JS-Abhängigkeit anstreben
4. Leistungs-sensitive Szenarien

Browserkompatibilität und Polyfill

Support-Status

Browser Anchor Positioning Popover API
Chrome 125+
Edge 125+
Safari 17.5+
Firefox 131+
iOS Safari 17.5+

Polyfill-Lösungen

<script src="https://cdn.jsdelivr.net/npm/@oddbird/css-anchor-positioning@0.3.0/dist/css-anchor-positioning.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@oddbird/popover-polyfill@0.4.0/dist/popover.min.js"></script>

Kombination mit @starting-style für Popup-Animationen

[popover] {
  opacity: 0;
  transform: translateY(-8px) scale(0.95);
  transition: opacity 0.2s, transform 0.2s, display 0.2s allow-discrete;
  overlay: none;
}

[popover]:popover-open {
  opacity: 1;
  transform: translateY(0) scale(1);
  overlay: auto;
}

@starting-style {
  [popover]:popover-open {
    opacity: 0;
    transform: translateY(-8px) scale(0.95);
  }
}

Zusammenfassung

  1. CSS Anchor Positioning ist die ultimative Lösung für Popup-Positionierung — Zero JS, deklarativ, browser-nativ
  2. Die Popover API macht Popup-Toggling ebenfalls Zero JS — das popovertarget-Attribut erledigt es in einer Zeile
  3. position-fallback löst Boundary-Overflow — Keine JS-Berechnung für Flipping mehr
  4. Alle wichtigen Browser unterstützen es 2026 — Sicher in der Produktion einsetzbar

Nach 10 Jahren ist Popup-Positionierung endlich dorthin zurückgekehrt, wo sie hingehört: CSS. Dies ist keine schrittweise Verbesserung — es ist ein Paradigmenwechsel, genau wie Flexbox Float-Layouts abgelöst hat.

Probiere diese browser-lokalen Tools aus — keine Registrierung erforderlich →

#CSS锚点定位#Anchor Positioning#Popover API#弹出层#CSS