Frontend Academy · Lektion

Portaler til modaler og tooltips

Brug ReactDOM.createPortal til at rendere underkomponenter i en anden DOM-node, så modaler og tooltips kan undslippe containere med overflow:hidden.

Lektion 3 af 414 trin

Portaler til modaler og tooltips er en gratis Frontend Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Frontend Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Frontend Academy-kurset indeholder 4 lektioner i alt.

Problemet med at undslippe containere

Modale vinduer og værktøjstip skal gengives øverst i DOM'en, så de undslipper forælderens overflow:hidden, z-index-stabling og transform-baserede kontekster. Løsningen er portaler.

createPortal-API'en

createPortal(children, container) gengiver children i container, altså en vilkårlig DOM-node, samtidig med at de logisk forbliver underkomponenter af React-komponenten med hensyn til hændelser og kontekst.

import { createPortal } from 'react-dom';

function Modal({ children, onClose }) {
  return createPortal(
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal-content" onClick={e => e.stopPropagation()}>
        {children}
      </div>
    </div>,
    document.body
  );
}

Portalcontainere

Almindelige mål er document.body, en dedikeret #modal-root-div i index.html eller en container via ref, som oprettes efter behov.

<!-- index.html -->
<div id="root"></div>
<div id="modal-root"></div>

// component:
const modalRoot = document.getElementById('modal-root');
return createPortal(<div>...</div>, modalRoot);

Hvorfor ikke bare gengive direkte?

Hvis en forælder har overflow: hidden, bliver et underliggende modalt vindue beskåret. Hvis en forælder har transform: scale, bliver modalvinduets faste positionering relativ til forælderen. Portaler undgår alt dette.

Hændelser bobler stadig op

Selvom indholdet gengives et andet sted i DOM'en, bobler React-hændelser gennem komponenttræet og ikke DOM-træet. Et klik i portalen bobler stadig op til onClick-håndteringer på overordnede React-komponenter.

Lukning ved klik på overlayet

Stop hændelsespropageringen på modalindholdet, så klik inden i det ikke lukker modalvinduet.

function Modal({ onClose, children }) {
  return createPortal(
    <div className="backdrop" onClick={onClose}>
      <div className="content" onClick={e => e.stopPropagation()}>
        {children}
      </div>
    </div>,
    document.body
  );
}

Lukning med Escape-tasten

Tilføj en keydown-lytter, mens modalvinduet er åbent, og fjern den, når komponenten afmonteres.

useEffect(() => {
  const onKey = (e) => { if (e.key === 'Escape') onClose(); };
  window.addEventListener('keydown', onKey);
  return () => window.removeEventListener('keydown', onKey);
}, [onClose]);

Fokusstyring i portaler

Når et modalt vindue åbnes: flyt fokus ind i det, fasthold fokus, indtil det lukkes, og gendan derefter fokus på det element, der åbnede modalvinduet. Brug et bibliotek som focus-trap-react for at undgå at implementere dette igen.

Det indbyggede dialog-element

HTML's <dialog> håndterer modal positionering, baggrund, fokusfastholdelse og lukning med Escape indbygget. Til de fleste modale vinduer er det et bedre udgangspunkt end en portal.

function Modal({ open, onClose, children }) {
  const ref = useRef(null);
  useEffect(() => {
    if (open) ref.current?.showModal();
    else ref.current?.close();
  }, [open]);
  return (
    <dialog ref={ref} onClose={onClose}>
      {children}
    </dialog>
  );
}

Værktøjstip og popovers

Værktøjstip positioneres relativt til et ankerelement. En portal lader dem undslippe stablingskontekster. Kombinér med floating-ui til kollisionsregistrering, vending og positionering.

import { useFloating, autoUpdate } from '@floating-ui/react';

function Tooltip({ children, content }) {
  const { refs, floatingStyles } = useFloating({ whileElementsMounted: autoUpdate });
  const [open, setOpen] = useState(false);
  return (
    <>
      <button ref={refs.setReference} onMouseEnter={() => setOpen(true)} onMouseLeave={() => setOpen(false)}>
        {children}
      </button>
      {open && createPortal(
        <div ref={refs.setFloating} style={floatingStyles}>{content}</div>,
        document.body
      )}
    </>
  );
}

SSR-forbehold

document findes ikke på serveren. Gengiv enten kun på klienten, ved at kontrollere typeof window, eller brug Next.js' dynamic med ssr:false.

Tilgængelighed: aria-modal

Modale containere bør have role="dialog", aria-modal="true" og aria-labelledby, der peger på modalvinduets overskrift. Eller brug det indbyggede <dialog>-element.

Hurtigt tjek

Hvorfor skal du bruge createPortal til modale vinduer i stedet for at gengive dem direkte i komponenttræet?

Opsummering: Portaler

createPortal(children, container) gengiver DOM-indhold et andet sted, samtidig med at det logiske React-træ bevares. Det løser problemer med at undslippe overflow, transform og z-index. Hændelser bobler stadig gennem React-træet. Tilføj lukning med Escape og fokusstyring. Det indbyggede <dialog>-element håndterer meget af dette for modale vinduer. Kombinér med floating-ui til værktøjstip. Glem ikke SSR, og kontrollér typeof window.

Gratis at komme i gang

Lær HTML med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
41
Lektioner
163

Ofte stillede spørgsmål

Er lektionen “Portaler til modaler og tooltips” gratis?

Ja — hele teksten til “Portaler til modaler og tooltips” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Frontend Academy-kurset, skal du opgradere til CoddyKit PRO. Frontend Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Portaler til modaler og tooltips”?

Brug ReactDOM.createPortal til at rendere underkomponenter i en anden DOM-node, så modaler og tooltips kan undslippe containere med overflow:hidden. Du øver dig i Frontend Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Frontend Academy?

Der kræves ingen tidligere erfaring. Frontend Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Portaler til modaler og tooltips”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Frontend Academy-lektion?

Ja. Alle Frontend Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Sammensatte komponenter med Context
  2. Render Props- og HOC-mønstre
  3. Portaler til modaler og tooltips
  4. Error Boundaries
← Tilbage til Frontend Academy